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
99aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org#include "src/base/bits.h"
10b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org#include "src/code-factory.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/code-stubs.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
134b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/deoptimizer.h"
14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/hydrogen-osr.h"
15a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org#include "src/ic/ic.h"
16b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org#include "src/ic/stub-cache.h"
174b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/x87/lithium-codegen-x87.h"
18864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
19864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace v8 {
20864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgnamespace internal {
21864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
22864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
23864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// When invoking builtins, we need to record the safepoint in the middle of
24864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// the invoke instruction sequence generated by the macro assembler.
25ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.orgclass SafepointGenerator FINAL : public CallWrapper {
26864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org public:
27864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SafepointGenerator(LCodeGen* codegen,
28864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     LPointerMap* pointers,
29864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     Safepoint::DeoptMode mode)
30864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : codegen_(codegen),
31864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        pointers_(pointers),
32864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        deopt_mode_(mode) {}
33864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  virtual ~SafepointGenerator() {}
34864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
35ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  virtual void BeforeCall(int call_size) const OVERRIDE {}
36864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
37ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  virtual void AfterCall() const OVERRIDE {
38864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    codegen_->RecordSafepoint(pointers_, deopt_mode_);
39864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
40864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
41864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org private:
42864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LCodeGen* codegen_;
43864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LPointerMap* pointers_;
44864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Safepoint::DeoptMode deopt_mode_;
45864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org};
46864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
47864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
48864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#define __ masm()->
49864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
50864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool LCodeGen::GenerateCode() {
51864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LPhase phase("Z_Code generation", chunk());
52e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_unused());
53864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  status_ = GENERATING;
54864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
55864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Open a frame scope to indicate that there is a frame on the stack.  The
56864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // MANUAL indicates that the scope shouldn't actually generate code to set up
57864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the frame (that is done in GeneratePrologue).
58864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  FrameScope frame_scope(masm_, StackFrame::MANUAL);
59864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
60864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  support_aligned_spilled_doubles_ = info()->IsOptimizing();
61864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
62864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  dynamic_frame_alignment_ = info()->IsOptimizing() &&
63864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ((chunk()->num_double_slots() > 2 &&
64864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        !chunk()->graph()->is_recursive()) ||
65864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       !info()->osr_ast_id().IsNone());
66864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
67864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return GeneratePrologue() &&
68864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      GenerateBody() &&
69864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      GenerateDeferredCode() &&
70864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      GenerateJumpTable() &&
71864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      GenerateSafepointTable();
72864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
73864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
74864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
75864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::FinishCode(Handle<Code> code) {
76e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_done());
77864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  code->set_stack_slots(GetStackSlotCount());
78864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
79864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code);
80864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PopulateDeoptimizationData(code);
81864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!info()->IsStub()) {
82864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
83864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
84864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
85864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
86864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
87864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef _MSC_VER
88864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::MakeSureStackPagesMapped(int offset) {
89864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int kPageSize = 4 * KB;
90864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
91864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(esp, offset), eax);
92864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
93864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
94864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
95864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
96864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
97864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool LCodeGen::GeneratePrologue() {
98e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_generating());
99864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (info()->IsOptimizing()) {
101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ProfileEntryHookStub::MaybeCallEntryHook(masm_);
102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef DEBUG
104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (strlen(FLAG_stop_at) > 0 &&
105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ int3();
107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Sloppy mode functions and builtins need to replace the receiver with the
111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // global proxy when called as functions (without an explicit receiver
112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // object).
113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (info_->this_has_uses() &&
114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        info_->strict_mode() == SLOPPY &&
115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        !info_->is_native()) {
116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label ok;
117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // +1 for return address.
118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ecx, Operand(esp, receiver_offset));
120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(ecx, isolate()->factory()->undefined_value());
122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &ok, Label::kNear);
123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ecx, GlobalObjectOperand());
125d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org      __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));
126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(Operand(esp, receiver_offset), ecx);
128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&ok);
130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Move state of dynamic frame alignment into edx.
134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Move(edx, Immediate(kNoAlignmentPadding));
135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label do_not_pad, align_loop;
137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Align esp + 4 to a multiple of 2 * kPointerSize.
139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(esp, Immediate(kPointerSize));
140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_zero, &do_not_pad, Label::kNear);
141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(0));
142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ebx, esp);
143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(edx, Immediate(kAlignmentPaddingPushed));
144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Copy arguments, receiver, and return address.
145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ecx, Immediate(scope()->num_parameters() + 2));
146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&align_loop);
148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(eax, Operand(ebx, 1 * kPointerSize));
149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(Operand(ebx, 0), eax);
150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ add(Operand(ebx), Immediate(kPointerSize));
151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ dec(ecx);
152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_zero, &align_loop, Label::kNear);
153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue));
154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&do_not_pad);
155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  info()->set_prologue_offset(masm_->pc_offset());
159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (NeedsEagerFrame()) {
160e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!frame_is_built_);
161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    frame_is_built_ = true;
162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (info()->IsStub()) {
163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ StubPrologue();
164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Prologue(info()->IsCodePreAgingActive());
166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    info()->AddNoFrameRange(0, masm_->pc_offset());
168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (info()->IsOptimizing() &&
171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      dynamic_frame_alignment_ &&
172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FLAG_debug_code) {
173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(esp, Immediate(kPointerSize));
174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Assert(zero, kFrameIsExpectedToBeAligned);
175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Reserve space for the stack slots needed by the code.
178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int slots = GetStackSlotCount();
179e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(slots != 0 || !info()->IsOptimizing());
180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (slots > 0) {
181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (slots == 1) {
182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (dynamic_frame_alignment_) {
183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(edx);
184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Immediate(kNoAlignmentPadding));
186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (FLAG_debug_code) {
189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ sub(Operand(esp), Immediate(slots * kPointerSize));
190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef _MSC_VER
191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        MakeSureStackPagesMapped(slots * kPointerSize);
192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(eax);
194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(Operand(eax), Immediate(slots));
195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Label loop;
196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&loop);
197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(MemOperand(esp, eax, times_4, 0),
198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               Immediate(kSlotsZapValue));
199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ dec(eax);
200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(not_zero, &loop);
201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ pop(eax);
202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ sub(Operand(esp), Immediate(slots * kPointerSize));
204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#ifdef _MSC_VER
205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        MakeSureStackPagesMapped(slots * kPointerSize);
206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif
207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (support_aligned_spilled_doubles_) {
210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Comment(";;; Store dynamic frame alignment tag for spilled doubles");
211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Store dynamic frame alignment state in the first local.
212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset;
213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (dynamic_frame_alignment_) {
214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ mov(Operand(ebp, offset), edx);
215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding));
217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Possibly allocate a local context.
223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (heap_slots > 0) {
225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment(";;; Allocate local context");
226d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org    bool need_write_barrier = true;
227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Argument to NewContext is the function, which is still in edi.
228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FastNewContextStub stub(isolate(), heap_slots);
230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallStub(&stub);
231d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org      // Result of FastNewContextStub is always in new space.
232d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org      need_write_barrier = false;
233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(edi);
23547390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      __ CallRuntime(Runtime::kNewFunctionContext, 1);
236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordSafepoint(Safepoint::kNoLazyDeopt);
238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Context is returned in eax.  It replaces the context passed to us.
239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // It's saved in the stack and kept live in esi.
240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, eax);
241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Copy parameters into context if necessary.
244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int num_parameters = scope()->num_parameters();
245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; i < num_parameters; i++) {
246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Variable* var = scope()->parameter(i);
247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (var->IsContextSlot()) {
248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            (num_parameters - 1 - i) * kPointerSize;
250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Load parameter from stack.
251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(eax, Operand(ebp, parameter_offset));
252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Store it in the context.
253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        int context_offset = Context::SlotOffset(var->index());
254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(Operand(esi, context_offset), eax);
255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Update the write barrier. This clobbers eax and ebx.
256d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org        if (need_write_barrier) {
25706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org          __ RecordWriteContextSlot(esi, context_offset, eax, ebx,
25806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                    kDontSaveFPRegs);
259d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org        } else if (FLAG_debug_code) {
260d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org          Label done;
261d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org          __ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
262d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org          __ Abort(kExpectedNewSpaceObject);
263d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org          __ bind(&done);
264d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org        }
265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment(";;; End allocate local context");
268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
27006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Initailize FPU state.
27106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fninit();
272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Trace the call.
273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_trace && info()->IsOptimizing()) {
274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // We have not executed any compiled code yet, so esi still holds the
275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // incoming context.
276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallRuntime(Runtime::kTraceEnter, 0);
277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return !is_aborted();
279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::GenerateOsrPrologue() {
283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Generate the OSR entry prologue at the first unknown OSR value, or if there
284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // are none, at the OSR entrypoint instruction.
285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (osr_pc_offset_ >= 0) return;
286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  osr_pc_offset_ = masm()->pc_offset();
288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Move state of dynamic frame alignment into edx.
290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(edx, Immediate(kNoAlignmentPadding));
291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label do_not_pad, align_loop;
294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Align ebp + 4 to a multiple of 2 * kPointerSize.
295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(ebp, Immediate(kPointerSize));
296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(zero, &do_not_pad, Label::kNear);
297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(0));
298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, esp);
299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, Immediate(kAlignmentPaddingPushed));
300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Move all parts of the frame over one word. The frame consists of:
302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // unoptimized frame slots, alignment state, context, frame pointer, return
303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // address, receiver, and the arguments.
304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ecx, Immediate(scope()->num_parameters() +
305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           5 + graph()->osr()->UnoptimizedFrameSlots()));
306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&align_loop);
308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, Operand(ebx, 1 * kPointerSize));
309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(ebx, 0), eax);
310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ add(Operand(ebx), Immediate(kPointerSize));
311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ dec(ecx);
312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &align_loop, Label::kNear);
313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue));
314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sub(Operand(ebp), Immediate(kPointerSize));
315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&do_not_pad);
316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Save the first local, which is overwritten by the alignment state.
319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand alignment_loc = MemOperand(ebp, -3 * kPointerSize);
320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(alignment_loc);
321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the dynamic frame alignment state.
323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(alignment_loc, edx);
324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Adjust the frame size, subsuming the unoptimized frame into the
326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // optimized frame.
327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
328e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(slots >= 1);
329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(esp, Immediate((slots - 1) * kPointerSize));
33006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
33106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Initailize FPU state.
33206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fninit();
333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->IsCall()) {
338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!instr->IsLazyBailout() && !instr->IsGap()) {
341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    safepoints_.BumpLastLazySafepointIndex();
342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  FlushX87StackIfNecessary(instr);
344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) {
34806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // When return from function call, FPU should be initialized again.
34906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (instr->IsCall() && instr->ClobbersDoubleRegisters(isolate())) {
35006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    bool double_result = instr->HasDoubleRegisterResult();
35106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    if (double_result) {
35206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ lea(esp, Operand(esp, -kDoubleSize));
35306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ fstp_d(Operand(esp, 0));
35406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    }
35506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fninit();
35606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    if (double_result) {
35706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ fld_d(Operand(esp, 0));
35806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ lea(esp, Operand(esp, kDoubleSize));
35906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    }
36006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->IsGoto()) {
36206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr), this);
363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (FLAG_debug_code && FLAG_enable_slow_asserts &&
364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             !instr->IsGap() && !instr->IsReturn()) {
365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->ClobbersDoubleRegisters(isolate())) {
366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (instr->HasDoubleRegisterResult()) {
367e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK_EQ(1, x87_stack_.depth());
368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
369e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK_EQ(0, x87_stack_.depth());
370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ VerifyX87StackDepth(x87_stack_.depth());
373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool LCodeGen::GenerateJumpTable() {
378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label needs_frame;
379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (jump_table_.length() > 0) {
380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Comment(";;; -------------------- Jump table --------------------");
381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < jump_table_.length(); i++) {
383a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i];
384a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    __ bind(&table_entry->label);
385a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    Address entry = table_entry->address;
38606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    DeoptComment(table_entry->reason);
387a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    if (table_entry->needs_frame) {
388e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!info()->saves_caller_doubles());
389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(ExternalReference::ForDeoptEntry(entry)));
390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (needs_frame.is_bound()) {
391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ jmp(&needs_frame);
392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&needs_frame);
394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset));
395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // This variant of deopt can only be used with stubs. Since we don't
396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // have a function pointer to install in the stack frame that we're
397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // building, install a special marker there instead.
398e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(info()->IsStub());
399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Push a PC inside the function so that the deopt code can find where
401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // the deopt comes from. It doesn't have to be the precise return
402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // address of a "calling" LAZY deopt, it only has to be somewhere
403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // inside the code body.
404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Label push_approx_pc;
405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ call(&push_approx_pc);
406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&push_approx_pc);
407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Push the continuation which was stashed were the ebp should
408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // be. Replace it with the saved ebp.
409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(MemOperand(esp, 3 * kPointerSize));
410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(MemOperand(esp, 4 * kPointerSize), ebp);
411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ lea(ebp, MemOperand(esp, 4 * kPointerSize));
412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ ret(0);  // Call the continuation without clobbering registers.
413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ call(entry, RelocInfo::RUNTIME_ENTRY);
416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return !is_aborted();
419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool LCodeGen::GenerateDeferredCode() {
423e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_generating());
424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (deferred_.length() > 0) {
425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      LDeferredCode* code = deferred_[i];
427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87Stack copy(code->x87_stack());
428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      x87_stack_ = copy;
429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      HValue* value =
431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          instructions_->at(code->instruction_index())->hydrogen_value();
432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      RecordAndWritePosition(
433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          chunk()->graph()->SourcePositionToScriptPosition(value->position()));
434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Comment(";;; <@%d,#%d> "
436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              "-------------------- Deferred %s --------------------",
437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              code->instruction_index(),
438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              code->instr()->hydrogen_value()->id(),
439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              code->instr()->Mnemonic());
440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(code->entry());
441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (NeedsDeferredFrame()) {
442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Comment(";;; Build frame");
443e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(!frame_is_built_);
444e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(info()->IsStub());
445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        frame_is_built_ = true;
446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Build the frame in such a way that esi isn't trashed.
447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(ebp);  // Caller's frame pointer.
448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Operand(ebp, StandardFrameConstants::kContextOffset));
449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ lea(ebp, Operand(esp, 2 * kPointerSize));
451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Comment(";;; Deferred code");
452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      code->Generate();
454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (NeedsDeferredFrame()) {
455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(code->done());
456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Comment(";;; Destroy frame");
457e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(frame_is_built_);
458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        frame_is_built_ = false;
459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(esp, ebp);
460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ pop(ebp);
461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(code->exit());
463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Deferred code is the last part of the instruction sequence. Mark
467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the generated code as done unless we bailed out.
468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!is_aborted()) status_ = DONE;
469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return !is_aborted();
470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool LCodeGen::GenerateSafepointTable() {
474e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_done());
475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!info()->IsStub()) {
476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // For lazy deoptimization we need space to patch a call after every call.
477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Ensure there is always space for such patching, even if the code ends
478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // in a call.
479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int target_offset = masm()->pc_offset() + Deoptimizer::patch_size();
480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    while (masm()->pc_offset() < target_offset) {
481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      masm()->nop();
482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  safepoints_.Emit(masm(), GetStackSlotCount());
485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return !is_aborted();
486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgRegister LCodeGen::ToRegister(int index) const {
490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return Register::FromAllocationIndex(index);
491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgX87Register LCodeGen::ToX87Register(int index) const {
495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return X87Register::FromAllocationIndex(index);
496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87LoadForUsage(X87Register reg) {
500e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(x87_stack_.Contains(reg));
501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  x87_stack_.Fxch(reg);
502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  x87_stack_.pop();
503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) {
507e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(x87_stack_.Contains(reg1));
508e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(x87_stack_.Contains(reg2));
50906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (reg1.is(reg2) && x87_stack_.depth() == 1) {
51006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(x87_stack_.st(reg1));
51106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.push(reg1);
51206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.pop();
51306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.pop();
51406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  } else {
51506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.Fxch(reg1, 1);
51606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.Fxch(reg2);
51706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.pop();
51806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.pop();
51906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
52006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org}
52106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
52206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
52306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgint LCodeGen::X87Stack::GetLayout() {
52406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  int layout = stack_depth_;
52506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  for (int i = 0; i < stack_depth_; i++) {
52606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    layout |= (stack_[stack_depth_ - 1 - i].code() << ((i + 1) * 3));
52706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
52806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
52906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  return layout;
530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
534e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_mutable_);
535e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(Contains(reg) && stack_depth_ > other_slot);
536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int i  = ArrayIndex(reg);
537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int st = st2idx(i);
538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (st != other_slot) {
539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int other_i = st2idx(other_slot);
540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Register other = stack_[other_i];
541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    stack_[other_i]   = reg;
542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    stack_[i]         = other;
543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (st == 0) {
544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fxch(other_slot);
545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (other_slot == 0) {
546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fxch(st);
547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fxch(st);
549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fxch(other_slot);
550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fxch(st);
551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgint LCodeGen::X87Stack::st2idx(int pos) {
557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return stack_depth_ - pos - 1;
558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgint LCodeGen::X87Stack::ArrayIndex(X87Register reg) {
562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < stack_depth_; i++) {
563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (stack_[i].is(reg)) return i;
564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UNREACHABLE();
566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return -1;
567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool LCodeGen::X87Stack::Contains(X87Register reg) {
571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < stack_depth_; i++) {
572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (stack_[i].is(reg)) return true;
573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return false;
575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87Stack::Free(X87Register reg) {
579e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_mutable_);
580e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(Contains(reg));
581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int i  = ArrayIndex(reg);
582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int st = st2idx(i);
583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (st > 0) {
584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // keep track of how fstp(i) changes the order of elements
585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int tos_i = st2idx(0);
586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    stack_[i] = stack_[tos_i];
587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  pop();
589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ fstp(st);
590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (x87_stack_.Contains(dst)) {
595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    x87_stack_.Fxch(dst);
596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ fstp(0);
597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    x87_stack_.push(dst);
599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Fld(src, opts);
601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
60406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid LCodeGen::X87Mov(X87Register dst, X87Register src, X87OperandType opts) {
60506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (x87_stack_.Contains(dst)) {
60606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.Fxch(dst);
60706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fstp(0);
60806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.pop();
60906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Push ST(i) onto the FPU register stack
61006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(x87_stack_.st(src));
61106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.push(dst);
61206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  } else {
61306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Push ST(i) onto the FPU register stack
61406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(x87_stack_.st(src));
61506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    x87_stack_.push(dst);
61606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
61706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org}
61806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
61906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87Fld(Operand src, X87OperandType opts) {
621e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!src.is_reg_only());
622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (opts) {
623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case kX87DoubleOperand:
624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fld_d(src);
625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case kX87FloatOperand:
627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fld_s(src);
628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case kX87IntOperand:
630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fild_s(src);
631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
639e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!dst.is_reg_only());
640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  x87_stack_.Fxch(src);
641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (opts) {
642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case kX87DoubleOperand:
643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fst_d(dst);
644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
64506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    case kX87FloatOperand:
64606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ fst_s(dst);
64706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      break;
648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case kX87IntOperand:
649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fist_s(dst);
650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
658e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_mutable_);
659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (Contains(reg)) {
660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Free(reg);
661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Mark this register as the next register to write to
663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  stack_[stack_depth_] = reg;
664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87Stack::CommitWrite(X87Register reg) {
668e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(is_mutable_);
669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Assert the reg is prepared to write, but not on the virtual stack yet
670e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!Contains(reg) && stack_[stack_depth_].is(reg) &&
671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      stack_depth_ < X87Register::kMaxNumAllocatableRegisters);
672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  stack_depth_++;
673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87PrepareBinaryOp(
677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Register left, X87Register right, X87Register result) {
678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // You need to use DefineSameAsFirst for x87 instructions
679e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result.is(left));
680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  x87_stack_.Fxch(right, 1);
681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  x87_stack_.Fxch(left);
682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters(isolate())) {
687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bool double_inputs = instr->HasDoubleRegisterInput();
688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Flush stack from tos down, since FreeX87() will mess with tos
690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = stack_depth_-1; i >= 0; i--) {
691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87Register reg = stack_[i];
692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Skip registers which contain the inputs for the next instruction
693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // when flushing the stack
694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        continue;
696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Free(reg);
698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (i < stack_depth_-1) i++;
699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->IsReturn()) {
702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    while (stack_depth_ > 0) {
703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fstp(0);
704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      stack_depth_--;
705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (FLAG_debug_code && FLAG_enable_slow_asserts) __ VerifyX87StackDepth(0);
707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
71106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr,
71206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                      LCodeGen* cgen) {
71306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // For going to a joined block, an explicit LClobberDoubles is inserted before
71406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // LGoto. Because all used x87 registers are spilled to stack slots. The
71506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // ResolvePhis phase of register allocator could guarantee the two input's x87
71606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // stacks have the same layout. So don't check stack_depth_ <= 1 here.
71706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  int goto_block_id = goto_instr->block_id();
71806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (current_block_id + 1 != goto_block_id) {
719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If we have a value on the x87 stack on leaving a block, it must be a
720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // phi input. If the next block we compile is not the join block, we have
721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // to discard the stack state.
72206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Before discarding the stack state, we need to save it if the "goto block"
72306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // has unreachable last predecessor when FLAG_unreachable_code_elimination.
72406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    if (FLAG_unreachable_code_elimination) {
72506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      int length = goto_instr->block()->predecessors()->length();
72606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      bool has_unreachable_last_predecessor = false;
72706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      for (int i = 0; i < length; i++) {
72806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org        HBasicBlock* block = goto_instr->block()->predecessors()->at(i);
72906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org        if (block->IsUnreachable() &&
73006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org            (block->block_id() + 1) == goto_block_id) {
73106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org          has_unreachable_last_predecessor = true;
73206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org        }
73306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      }
73406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      if (has_unreachable_last_predecessor) {
73506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org        if (cgen->x87_stack_map_.find(goto_block_id) ==
73606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org            cgen->x87_stack_map_.end()) {
73706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org          X87Stack* stack = new (cgen->zone()) X87Stack(*this);
73806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org          cgen->x87_stack_map_.insert(std::make_pair(goto_block_id, stack));
73906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org        }
74006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      }
74106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    }
74206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
74306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Discard the stack state.
744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    stack_depth_ = 0;
745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitFlushX87ForDeopt() {
750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The deoptimizer does not support X87 Registers. But as long as we
751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // deopt from a stub its not a problem, since we will re-materialize the
752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // original stub inputs, which can't be double registers.
75306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // DCHECK(info()->IsStub());
754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_debug_code && FLAG_enable_slow_asserts) {
755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pushfd();
756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ VerifyX87StackDepth(x87_stack_.depth());
757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ popfd();
758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
75906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
76006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Flush X87 stack in the deoptimizer entry.
761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgRegister LCodeGen::ToRegister(LOperand* op) const {
765e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(op->IsRegister());
766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return ToRegister(op->index());
767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgX87Register LCodeGen::ToX87Register(LOperand* op) const {
771e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(op->IsDoubleRegister());
772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return ToX87Register(op->index());
773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgint32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return ToRepresentation(op, Representation::Integer32());
778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgint32_t LCodeGen::ToRepresentation(LConstantOperand* op,
782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                   const Representation& r) const {
783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HConstant* constant = chunk_->LookupConstant(op);
784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t value = constant->Integer32Value();
785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (r.IsInteger32()) return value;
786e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(r.IsSmiOrTagged());
787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return reinterpret_cast<int32_t>(Smi::FromInt(value));
788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgHandle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HConstant* constant = chunk_->LookupConstant(op);
793e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return constant->handle(isolate());
795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgdouble LCodeGen::ToDouble(LConstantOperand* op) const {
799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HConstant* constant = chunk_->LookupConstant(op);
800e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(constant->HasDoubleValue());
801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return constant->DoubleValue();
802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const {
806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HConstant* constant = chunk_->LookupConstant(op);
807e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(constant->HasExternalReferenceValue());
808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return constant->ExternalReferenceValue();
809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool LCodeGen::IsInteger32(LConstantOperand* op) const {
813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgbool LCodeGen::IsSmi(LConstantOperand* op) const {
818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return chunk_->LookupLiteralRepresentation(op).IsSmi();
819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic int ArgumentsOffsetWithoutFrame(int index) {
823e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(index < 0);
824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return -(index + 1) * kPointerSize + kPCOnStackSize;
825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgOperand LCodeGen::ToOperand(LOperand* op) const {
829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (op->IsRegister()) return Operand(ToRegister(op));
830e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!op->IsDoubleRegister());
831e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (NeedsEagerFrame()) {
833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return Operand(ebp, StackSlotOffset(op->index()));
834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Retrieve parameter without eager stack-frame relative to the
836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // stack-pointer.
837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return Operand(esp, ArgumentsOffsetWithoutFrame(op->index()));
838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgOperand LCodeGen::HighOperand(LOperand* op) {
843e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(op->IsDoubleStackSlot());
844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (NeedsEagerFrame()) {
845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize);
846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Retrieve parameter without eager stack-frame relative to the
848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // stack-pointer.
849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return Operand(
850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        esp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::WriteTranslation(LEnvironment* environment,
856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                Translation* translation) {
857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (environment == NULL) return;
858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The translation includes one command per value in the environment.
860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int translation_size = environment->translation_size();
861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The output frame height does not include the parameters.
862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int height = translation_size - environment->parameter_count();
863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  WriteTranslation(environment->outer(), translation);
865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool has_closure_id = !info()->closure().is_null() &&
866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      !info()->closure().is_identical_to(environment->closure());
867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int closure_id = has_closure_id
868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? DefineDeoptimizationLiteral(environment->closure())
869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : Translation::kSelfLiteralId;
870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (environment->frame_type()) {
871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case JS_FUNCTION:
872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->BeginJSFrame(environment->ast_id(), closure_id, height);
873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case JS_CONSTRUCT:
875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->BeginConstructStubFrame(closure_id, translation_size);
876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case JS_GETTER:
878e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(translation_size == 1);
879e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(height == 0);
880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->BeginGetterStubFrame(closure_id);
881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case JS_SETTER:
883e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(translation_size == 2);
884e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(height == 0);
885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->BeginSetterStubFrame(closure_id);
886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case ARGUMENTS_ADAPTOR:
888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case STUB:
891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->BeginCompiledStubFrame();
892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int object_index = 0;
898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int dematerialized_index = 0;
899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < translation_size; ++i) {
900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LOperand* value = environment->values()->at(i);
901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    AddToTranslation(environment,
902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     translation,
903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     value,
904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     environment->HasTaggedValueAt(i),
905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     environment->HasUint32ValueAt(i),
906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     &object_index,
907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     &dematerialized_index);
908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::AddToTranslation(LEnvironment* environment,
913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                Translation* translation,
914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                LOperand* op,
915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                bool is_tagged,
916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                bool is_uint32,
917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                int* object_index_pointer,
918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                int* dematerialized_index_pointer) {
919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (op == LEnvironment::materialization_marker()) {
920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int object_index = (*object_index_pointer)++;
921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (environment->ObjectIsDuplicateAt(object_index)) {
922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int dupe_of = environment->ObjectDuplicateOfAt(object_index);
923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->DuplicateObject(dupe_of);
924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return;
925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int object_length = environment->ObjectLengthAt(object_index);
927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (environment->ObjectIsArgumentsAt(object_index)) {
928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->BeginArgumentsObject(object_length);
929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->BeginCapturedObject(object_length);
931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int dematerialized_index = *dematerialized_index_pointer;
933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int env_offset = environment->translation_size() + dematerialized_index;
934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    *dematerialized_index_pointer += object_length;
935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; i < object_length; ++i) {
936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      LOperand* value = environment->values()->at(env_offset + i);
937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      AddToTranslation(environment,
938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       translation,
939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       value,
940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       environment->HasTaggedValueAt(env_offset + i),
941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       environment->HasUint32ValueAt(env_offset + i),
942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       object_index_pointer,
943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       dematerialized_index_pointer);
944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (op->IsStackSlot()) {
949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (is_tagged) {
950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->StoreStackSlot(op->index());
951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (is_uint32) {
952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->StoreUint32StackSlot(op->index());
953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->StoreInt32StackSlot(op->index());
955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (op->IsDoubleStackSlot()) {
957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    translation->StoreDoubleStackSlot(op->index());
958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (op->IsRegister()) {
959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register reg = ToRegister(op);
960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (is_tagged) {
961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->StoreRegister(reg);
962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (is_uint32) {
963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->StoreUint32Register(reg);
964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translation->StoreInt32Register(reg);
966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
96706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  } else if (op->IsDoubleRegister()) {
96806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Register reg = ToX87Register(op);
96906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    translation->StoreDoubleRegister(reg);
970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (op->IsConstantOperand()) {
971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    translation->StoreLiteral(src_index);
974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    UNREACHABLE();
976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::CallCodeGeneric(Handle<Code> code,
981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               RelocInfo::Mode mode,
982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               LInstruction* instr,
983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               SafepointMode safepoint_mode) {
984e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr != NULL);
985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ call(code, mode);
986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepointWithLazyDeopt(instr, safepoint_mode);
987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Signal that we don't inline smi code before these stubs in the
989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // optimizing code generator.
990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (code->kind() == Code::BINARY_OP_IC ||
991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      code->kind() == Code::COMPARE_IC) {
992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ nop();
993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::CallCode(Handle<Code> code,
998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        RelocInfo::Mode mode,
999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        LInstruction* instr) {
1000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
1001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
100406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.orgvoid LCodeGen::CallRuntime(const Runtime::Function* fun, int argc,
100506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                           LInstruction* instr, SaveFPRegsMode save_doubles) {
1006e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr != NULL);
1007e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->HasPointerMap());
1008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
100906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ CallRuntime(fun, argc, save_doubles);
1010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
1012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1013e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(info()->is_calling());
1014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::LoadContextFromDeferred(LOperand* context) {
1018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (context->IsRegister()) {
1019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!ToRegister(context).is(esi)) {
1020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(esi, ToRegister(context));
1021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (context->IsStackSlot()) {
1023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, ToOperand(context));
1024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (context->IsConstantOperand()) {
1025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    HConstant* constant =
1026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        chunk_->LookupConstant(LConstantOperand::cast(context));
1027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ LoadObject(esi, Handle<Object>::cast(constant->handle(isolate())));
1028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    UNREACHABLE();
1030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
1034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       int argc,
1035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       LInstruction* instr,
1036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       LOperand* context) {
1037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LoadContextFromDeferred(context);
1038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
103906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ CallRuntimeSaveDoubles(id);
1040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepointWithRegisters(
1041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
1042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1043e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(info()->is_calling());
1044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::RegisterEnvironmentForDeoptimization(
1048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LEnvironment* environment, Safepoint::DeoptMode mode) {
1049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  environment->set_has_been_used();
1050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!environment->HasBeenRegistered()) {
1051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Physical stack frame layout:
1052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // -x ............. -4  0 ..................................... y
1053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // [incoming arguments] [spill slots] [pushed outgoing arguments]
1054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Layout of the environment:
1056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // 0 ..................................................... size-1
1057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // [parameters] [locals] [expression stack including arguments]
1058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Layout of the translation:
1060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // 0 ........................................................ size - 1 + 4
1061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // [expression stack including arguments] [locals] [4 words] [parameters]
1062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // |>------------  translation_size ------------<|
1063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int frame_count = 0;
1065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int jsframe_count = 0;
1066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
1067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ++frame_count;
1068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (e->frame_type() == JS_FUNCTION) {
1069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ++jsframe_count;
1070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Translation translation(&translations_, frame_count, jsframe_count, zone());
1073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    WriteTranslation(environment, &translation);
1074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int deoptimization_index = deoptimizations_.length();
1075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int pc_offset = masm()->pc_offset();
1076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    environment->Register(deoptimization_index,
1077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                          translation.index(),
1078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                          (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
1079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    deoptimizations_.Add(environment, zone());
1080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1084a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
108506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                            const char* detail,
1086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            Deoptimizer::BailoutType bailout_type) {
1087a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  LEnvironment* environment = instr->environment();
1088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
1089e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(environment->HasBeenRegistered());
1090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int id = environment->deoptimization_index();
1091e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(info()->IsOptimizing() || info()->IsStub());
1092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Address entry =
1093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
1094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (entry == NULL) {
1095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Abort(kBailoutWasNotPrepared);
1096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (DeoptEveryNTimes()) {
1100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ExternalReference count = ExternalReference::stress_deopt_count(isolate());
1101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label no_deopt;
1102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pushfd();
1103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(eax);
1104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, Operand::StaticVariable(count));
1105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sub(eax, Immediate(1));
1106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &no_deopt, Label::kNear);
1107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (FLAG_trap_on_deopt) __ int3();
1108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, Immediate(FLAG_deopt_every_n_times));
1109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand::StaticVariable(count), eax);
1110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(eax);
1111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ popfd();
1112e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(frame_is_built_);
111306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Put the x87 stack layout in TOS.
111406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
111506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ push(Immediate(x87_stack_.GetLayout()));
111606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fild_s(MemOperand(esp, 0));
111706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Don't touch eflags.
111806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ lea(esp, Operand(esp, kPointerSize));
1119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ call(entry, RelocInfo::RUNTIME_ENTRY);
1120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&no_deopt);
1121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand::StaticVariable(count), eax);
1122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(eax);
1123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ popfd();
1124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
112606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Put the x87 stack layout in TOS, so that we can save x87 fp registers in
112706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // the correct location.
112806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  {
1129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done;
1130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
113106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
113206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
113306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    int x87_stack_layout = x87_stack_.GetLayout();
113406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ push(Immediate(x87_stack_layout));
113506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fild_s(MemOperand(esp, 0));
113606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Don't touch eflags.
113706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ lea(esp, Operand(esp, kPointerSize));
1138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
1139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (info()->ShouldTrapOnDeopt()) {
1142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done;
1143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
1144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ int3();
1145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
1146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
114806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
114906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                             instr->Mnemonic(), detail);
1150e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(info()->IsStub() || frame_is_built_);
1151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (cc == no_condition && frame_is_built_) {
115206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    DeoptComment(reason);
1153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ call(entry, RelocInfo::RUNTIME_ENTRY);
1154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
115506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type,
115606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                            !frame_is_built_);
1157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // We often have several deopts to the same entry, reuse the last
1158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // jump entry if this is the case.
1159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (jump_table_.is_empty() ||
116006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org        !table_entry.IsEquivalentTo(jump_table_.last())) {
1161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      jump_table_.Add(table_entry, zone());
1162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (cc == no_condition) {
1164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&jump_table_.last().label);
1165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
1166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(cc, &jump_table_.last().label);
1167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1172a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
117306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                            const char* detail) {
1174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Deoptimizer::BailoutType bailout_type = info()->IsStub()
1175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? Deoptimizer::LAZY
1176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      : Deoptimizer::EAGER;
117706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  DeoptimizeIf(cc, instr, detail, bailout_type);
1178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
1182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int length = deoptimizations_.length();
1183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (length == 0) return;
1184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<DeoptimizationInputData> data =
11856474a1cfee1cdad45de5cc96960085e1c7daf11cmachenbach@chromium.org      DeoptimizationInputData::New(isolate(), length, TENURED);
1186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<ByteArray> translations =
1188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      translations_.CreateByteArray(isolate()->factory());
1189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  data->SetTranslationByteArray(*translations);
1190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
1191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  data->SetOptimizationId(Smi::FromInt(info_->optimization_id()));
1192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (info_->IsOptimizing()) {
1193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Reference to shared function info does not change between phases.
1194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    AllowDeferredHandleDereference allow_handle_dereference;
1195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    data->SetSharedFunctionInfo(*info_->shared_info());
1196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    data->SetSharedFunctionInfo(Smi::FromInt(0));
1198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<FixedArray> literals =
1201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
1202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  { AllowDeferredHandleDereference copy_handles;
1203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; i < deoptimization_literals_.length(); i++) {
1204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      literals->set(i, *deoptimization_literals_[i]);
1205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    data->SetLiteralArray(*literals);
1207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
1210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
1211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Populate the deoptimization entries.
1213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < length; i++) {
1214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LEnvironment* env = deoptimizations_[i];
1215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    data->SetAstId(i, env->ast_id());
1216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
1217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    data->SetArgumentsStackHeight(i,
1218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  Smi::FromInt(env->arguments_stack_height()));
1219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    data->SetPc(i, Smi::FromInt(env->pc_offset()));
1220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  code->set_deoptimization_data(*data);
1222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgint LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
1226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int result = deoptimization_literals_.length();
1227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < deoptimization_literals_.length(); ++i) {
1228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (deoptimization_literals_[i].is_identical_to(literal)) return i;
1229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  deoptimization_literals_.Add(literal, zone());
1231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return result;
1232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
1236e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(deoptimization_literals_.length() == 0);
1237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const ZoneList<Handle<JSFunction> >* inlined_closures =
1239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      chunk()->inlined_closures();
1240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0, length = inlined_closures->length();
1242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       i < length;
1243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       i++) {
1244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DefineDeoptimizationLiteral(inlined_closures->at(i));
1245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  inlined_function_count_ = deoptimization_literals_.length();
1248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::RecordSafepointWithLazyDeopt(
1252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LInstruction* instr, SafepointMode safepoint_mode) {
1253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
1254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
1255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1256e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
1257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordSafepointWithRegisters(
1258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
1259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::RecordSafepoint(
1264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LPointerMap* pointers,
1265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Safepoint::Kind kind,
1266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int arguments,
1267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Safepoint::DeoptMode deopt_mode) {
1268e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(kind == expected_safepoint_kind_);
1269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
1270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Safepoint safepoint =
1271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode);
1272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < operands->length(); i++) {
1273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LOperand* pointer = operands->at(i);
1274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (pointer->IsStackSlot()) {
1275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      safepoint.DefinePointerSlot(pointer->index(), zone());
1276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
1277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      safepoint.DefinePointerRegister(ToRegister(pointer), zone());
1278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::RecordSafepoint(LPointerMap* pointers,
1284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Safepoint::DeoptMode mode) {
1285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepoint(pointers, Safepoint::kSimple, 0, mode);
1286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) {
1290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LPointerMap empty_pointers(zone());
1291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepoint(&empty_pointers, mode);
1292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
1296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            int arguments,
1297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                            Safepoint::DeoptMode mode) {
1298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode);
1299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::RecordAndWritePosition(int position) {
1303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (position == RelocInfo::kNoPosition) return;
1304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  masm()->positions_recorder()->RecordPosition(position);
1305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  masm()->positions_recorder()->WriteRecordedPositions();
1306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic const char* LabelType(LLabel* label) {
1310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (label->is_loop_header()) return " (loop header)";
1311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (label->is_osr_entry()) return " (OSR entry)";
1312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return "";
1313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLabel(LLabel* label) {
1317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------",
1318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          current_instruction_,
1319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          label->hydrogen_value()->id(),
1320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          label->block_id(),
1321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          LabelType(label));
1322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(label->label());
1323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  current_block_ = label->block_id();
132406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (label->block()->predecessors()->length() > 1) {
132506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // A join block's x87 stack is that of its last visited predecessor.
132606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // If the last visited predecessor block is unreachable, the stack state
132706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // will be wrong. In such case, use the x87 stack of reachable predecessor.
132806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87StackMap::const_iterator it = x87_stack_map_.find(current_block_);
132906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Restore x87 stack.
133006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    if (it != x87_stack_map_.end()) {
133106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      x87_stack_ = *(it->second);
133206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    }
133306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
1334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DoGap(label);
1335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoParallelMove(LParallelMove* move) {
1339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  resolver_.Resolve(move);
1340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoGap(LGap* gap) {
1344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = LGap::FIRST_INNER_POSITION;
1345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       i <= LGap::LAST_INNER_POSITION;
1346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org       i++) {
1347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
1348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LParallelMove* move = gap->GetParallelMove(inner_pos);
1349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (move != NULL) DoParallelMove(move);
1350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoInstructionGap(LInstructionGap* instr) {
1355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DoGap(instr);
1356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoParameter(LParameter* instr) {
1360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Nothing to do.
1361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCallStub(LCallStub* instr) {
1365e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
1366e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
1367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (instr->hydrogen()->major_key()) {
1368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CodeStub::RegExpExec: {
1369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      RegExpExecStub stub(isolate());
1370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CodeStub::SubString: {
1374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      SubStringStub stub(isolate());
1375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case CodeStub::StringCompare: {
1379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      StringCompareStub stub(isolate());
1380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
1382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
1384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
1385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  GenerateOsrPrologue();
1391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
1395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dividend = ToRegister(instr->dividend());
1396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t divisor = instr->divisor();
1397e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(dividend.is(ToRegister(instr->result())));
1398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Theoretically, a variation of the branch-free code for integer division by
1400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // a power of 2 (calculating the remainder via an additional multiplication
1401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // (which gets simplified to an 'and') and subtraction) should be faster, and
1402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
1403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // indicate that positive dividends are heavily favored, so the branching
1404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // version performs better.
1405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HMod* hmod = instr->hydrogen();
1406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label dividend_is_not_negative, done;
1408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(dividend, dividend);
1410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Note that this is correct even for kMinInt operands.
1412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ neg(dividend);
1413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ and_(dividend, mask);
1414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ neg(dividend);
1415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1416b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(zero, instr, "minus zero");
1417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&done, Label::kNear);
1419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&dividend_is_not_negative);
1422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(dividend, mask);
1423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
1424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoModByConstI(LModByConstI* instr) {
1428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dividend = ToRegister(instr->dividend());
1429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t divisor = instr->divisor();
1430e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
1431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor == 0) {
1433b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(no_condition, instr, "division by zero");
1434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TruncatingDiv(dividend, Abs(divisor));
1438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ imul(edx, edx, Abs(divisor));
1439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, dividend);
1440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(eax, edx);
1441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for negative zero.
1443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HMod* hmod = instr->hydrogen();
1444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label remainder_not_zero;
1446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &remainder_not_zero, Label::kNear);
1447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(dividend, Immediate(0));
1448b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(less, instr, "minus zero");
1449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&remainder_not_zero);
1450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoModI(LModI* instr) {
1455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HMod* hmod = instr->hydrogen();
1456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register left_reg = ToRegister(instr->left());
1458e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(left_reg.is(eax));
1459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register right_reg = ToRegister(instr->right());
1460e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!right_reg.is(eax));
1461e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!right_reg.is(edx));
1462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result_reg = ToRegister(instr->result());
1463e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result_reg.is(edx));
1464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
1466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for x % 0, idiv would signal a divide error. We have to
1467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // deopt in this case because we can't return a NaN.
1468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(right_reg, Operand(right_reg));
1470b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "division by zero");
1471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for kMinInt % -1, idiv would signal a divide error. We
1474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // have to deopt if we care about -0, because we can't return that.
1475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hmod->CheckFlag(HValue::kCanOverflow)) {
1476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label no_overflow_possible;
1477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(left_reg, kMinInt);
1478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &no_overflow_possible, Label::kNear);
1479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(right_reg, -1);
1480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1481b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(equal, instr, "minus zero");
1482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
1483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &no_overflow_possible, Label::kNear);
1484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Move(result_reg, Immediate(0));
1485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&done, Label::kNear);
1486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&no_overflow_possible);
1488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Sign extend dividend in eax into edx:eax.
1491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cdq();
1492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If we care about -0, test if the dividend is <0 and the result is 0.
1494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label positive_left;
1496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(left_reg, Operand(left_reg));
1497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_sign, &positive_left, Label::kNear);
1498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ idiv(right_reg);
1499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(result_reg, Operand(result_reg));
1500b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "minus zero");
1501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&done, Label::kNear);
1502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&positive_left);
1503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ idiv(right_reg);
1505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
1506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dividend = ToRegister(instr->dividend());
1511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t divisor = instr->divisor();
1512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
15139aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1514e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!result.is(dividend));
1515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for (0 / -x) that will produce negative zero.
1517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HDiv* hdiv = instr->hydrogen();
1518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(dividend, dividend);
1520b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "minus zero");
1521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for (kMinInt / -1).
1523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(dividend, kMinInt);
1525b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "overflow");
1526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Deoptimize if remainder will not be 0.
1528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      divisor != 1 && divisor != -1) {
1530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(dividend, Immediate(mask));
1532b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_zero, instr, "lost precision");
1533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, dividend);
1535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t shift = WhichPowerOf2Abs(divisor);
1536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (shift > 0) {
1537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The arithmetic shift is always OK, the 'if' is an optimization only.
1538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (shift > 1) __ sar(result, 31);
1539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ shr(result, 32 - shift);
1540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ add(result, dividend);
1541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sar(result, shift);
1542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor < 0) __ neg(result);
1544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dividend = ToRegister(instr->dividend());
1549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t divisor = instr->divisor();
1550e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(edx));
1551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor == 0) {
1553b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(no_condition, instr, "division by zero");
1554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for (0 / -x) that will produce negative zero.
1558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HDiv* hdiv = instr->hydrogen();
1559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(dividend, dividend);
1561b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "minus zero");
1562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TruncatingDiv(dividend, Abs(divisor));
1565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor < 0) __ neg(edx);
1566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, edx);
1569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ imul(eax, eax, divisor);
1570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sub(eax, dividend);
1571b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_equal, instr, "lost precision");
1572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDivI(LDivI* instr) {
1578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HBinaryOperation* hdiv = instr->hydrogen();
1579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dividend = ToRegister(instr->dividend());
1580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register divisor = ToRegister(instr->divisor());
1581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register remainder = ToRegister(instr->temp());
1582e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(dividend.is(eax));
1583e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(remainder.is(edx));
1584e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
1585e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!divisor.is(eax));
1586e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!divisor.is(edx));
1587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for x / 0.
1589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(divisor, divisor);
1591b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "division by zero");
1592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for (0 / -x) that will produce negative zero.
1595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label dividend_not_zero;
1597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(dividend, dividend);
1598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &dividend_not_zero, Label::kNear);
1599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(divisor, divisor);
1600b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(sign, instr, "minus zero");
1601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&dividend_not_zero);
1602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for (kMinInt / -1).
1605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label dividend_not_min_int;
1607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(dividend, kMinInt);
1608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &dividend_not_min_int, Label::kNear);
1609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(divisor, -1);
1610b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "overflow");
1611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&dividend_not_min_int);
1612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Sign extend to edx (= remainder).
1615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cdq();
1616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ idiv(divisor);
1617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Deoptimize if remainder is not 0.
1620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(remainder, remainder);
1621b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_zero, instr, "lost precision");
1622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dividend = ToRegister(instr->dividend());
1628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t divisor = instr->divisor();
1629e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(dividend.is(ToRegister(instr->result())));
1630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the divisor is positive, things are easy: There can be no deopts and we
1632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // can simply do an arithmetic right shift.
1633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor == 1) return;
1634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t shift = WhichPowerOf2Abs(divisor);
1635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor > 1) {
1636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sar(dividend, shift);
1637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the divisor is negative, we have to negate and handle edge cases.
1641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ neg(dividend);
1642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1643b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "minus zero");
1644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
164670d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org  // Dividing by -1 is basically negation, unless we overflow.
164770d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org  if (divisor == -1) {
164870d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org    if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1649b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(overflow, instr, "overflow");
165070d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org    }
1651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
165470d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org  // If the negation could not overflow, simply shifting is OK.
165570d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org  if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
165670d11c79c7833b9ab1ee185625fcf707b9480a40machenbach@chromium.org    __ sar(dividend, shift);
1657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label not_kmin_int, done;
1661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(no_overflow, &not_kmin_int, Label::kNear);
1662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(dividend, Immediate(kMinInt / divisor));
1663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
1664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&not_kmin_int);
1665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sar(dividend, shift);
1666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
1667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dividend = ToRegister(instr->dividend());
1672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t divisor = instr->divisor();
1673e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(edx));
1674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor == 0) {
1676b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(no_condition, instr, "division by zero");
1677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for (0 / -x) that will produce negative zero.
1681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HMathFloorOfDiv* hdiv = instr->hydrogen();
1682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(dividend, dividend);
1684b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "minus zero");
1685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Easy case: We need no dynamic check for the dividend and the flooring
1688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // division is the same as the truncating division.
1689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ TruncatingDiv(dividend, Abs(divisor));
1692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (divisor < 0) __ neg(edx);
1693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
1694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // In the general case we may need to adjust before and after the truncating
1697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // division to get a flooring division.
1698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp3());
1699e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!temp.is(dividend) && !temp.is(eax) && !temp.is(edx));
1700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label needs_adjustment, done;
1701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(dividend, Immediate(0));
1702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear);
1703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TruncatingDiv(dividend, Abs(divisor));
1704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor < 0) __ neg(edx);
1705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
1706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&needs_adjustment);
1707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(temp, Operand(dividend, divisor > 0 ? 1 : -1));
1708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TruncatingDiv(temp, Abs(divisor));
1709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (divisor < 0) __ neg(edx);
1710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ dec(edx);
1711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
1712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
1716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
1717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HBinaryOperation* hdiv = instr->hydrogen();
1718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register dividend = ToRegister(instr->dividend());
1719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register divisor = ToRegister(instr->divisor());
1720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register remainder = ToRegister(instr->temp());
1721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
1722e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(dividend.is(eax));
1723e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(remainder.is(edx));
1724e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result.is(eax));
1725e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!divisor.is(eax));
1726e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!divisor.is(edx));
1727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for x / 0.
1729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(divisor, divisor);
1731b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "division by zero");
1732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for (0 / -x) that will produce negative zero.
1735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label dividend_not_zero;
1737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(dividend, dividend);
1738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &dividend_not_zero, Label::kNear);
1739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(divisor, divisor);
1740b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(sign, instr, "minus zero");
1741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&dividend_not_zero);
1742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for (kMinInt / -1).
1745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label dividend_not_min_int;
1747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(dividend, kMinInt);
1748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &dividend_not_min_int, Label::kNear);
1749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(divisor, -1);
1750b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "overflow");
1751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&dividend_not_min_int);
1752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Sign extend to edx (= remainder).
1755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cdq();
1756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ idiv(divisor);
1757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
1759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(remainder, remainder);
1760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(zero, &done, Label::kNear);
1761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ xor_(remainder, divisor);
1762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sar(remainder, 31);
1763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(result, remainder);
1764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
1765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMulI(LMulI* instr) {
1769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register left = ToRegister(instr->left());
1770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* right = instr->right();
1771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ToRegister(instr->temp()), left);
1774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (right->IsConstantOperand()) {
1777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Try strength reductions on the multiplication.
1778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // All replacement instructions are at most as long as the imul
1779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // and have better latency.
1780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int constant = ToInteger32(LConstantOperand::cast(right));
1781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (constant == -1) {
1782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ neg(left);
1783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (constant == 0) {
1784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ xor_(left, Operand(left));
1785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (constant == 2) {
1786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ add(left, Operand(left));
1787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // If we know that the multiplication can't overflow, it's safe to
1789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // use instructions that don't set the overflow flag for the
1790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // multiplication.
1791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      switch (constant) {
1792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case 1:
1793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // Do nothing.
1794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case 3:
1796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ lea(left, Operand(left, left, times_2, 0));
1797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case 4:
1799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ shl(left, 2);
1800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case 5:
1802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ lea(left, Operand(left, left, times_4, 0));
1803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case 8:
1805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ shl(left, 3);
1806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case 9:
1808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ lea(left, Operand(left, left, times_8, 0));
1809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        case 16:
1811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ shl(left, 4);
1812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        default:
1814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ imul(left, left, constant);
1815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          break;
1816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
1818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ imul(left, left, constant);
1819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->hydrogen()->representation().IsSmi()) {
1822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ SmiUntag(left);
1823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ imul(left, ToOperand(right));
1825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1828b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(overflow, instr, "overflow");
1829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Bail out if the result is supposed to be negative zero.
1833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done;
1834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(left, Operand(left));
183506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ j(not_zero, &done);
1836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (right->IsConstantOperand()) {
1837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1838b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org        DeoptimizeIf(no_condition, instr, "minus zero");
1839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(ToRegister(instr->temp()), Immediate(0));
1841b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org        DeoptimizeIf(less, instr, "minus zero");
1842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
1843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
1844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Test the non-zero operand for negative sign.
1845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ or_(ToRegister(instr->temp()), ToOperand(right));
1846b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(sign, instr, "minus zero");
1847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
1849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoBitI(LBitI* instr) {
1854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* left = instr->left();
1855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* right = instr->right();
1856e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(left->Equals(instr->result()));
1857e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(left->IsRegister());
1858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (right->IsConstantOperand()) {
1860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int32_t right_operand =
1861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ToRepresentation(LConstantOperand::cast(right),
1862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         instr->hydrogen()->representation());
1863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    switch (instr->op()) {
1864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::BIT_AND:
1865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ and_(ToRegister(left), right_operand);
1866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::BIT_OR:
1868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ or_(ToRegister(left), right_operand);
1869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::BIT_XOR:
1871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (right_operand == int32_t(~0)) {
1872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ not_(ToRegister(left));
1873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
1874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ xor_(ToRegister(left), right_operand);
1875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      default:
1878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        UNREACHABLE();
1879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    switch (instr->op()) {
1883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::BIT_AND:
1884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ and_(ToRegister(left), ToOperand(right));
1885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::BIT_OR:
1887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ or_(ToRegister(left), ToOperand(right));
1888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::BIT_XOR:
1890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ xor_(ToRegister(left), ToOperand(right));
1891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      default:
1893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        UNREACHABLE();
1894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoShiftI(LShiftI* instr) {
1901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* left = instr->left();
1902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* right = instr->right();
1903e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(left->Equals(instr->result()));
1904e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(left->IsRegister());
1905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (right->IsRegister()) {
1906e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(ToRegister(right).is(ecx));
1907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    switch (instr->op()) {
1909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::ROR:
1910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ ror_cl(ToRegister(left));
1911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::SAR:
1913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ sar_cl(ToRegister(left));
1914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::SHR:
1916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ shr_cl(ToRegister(left));
1917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (instr->can_deopt()) {
1918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ test(ToRegister(left), ToRegister(left));
1919b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org          DeoptimizeIf(sign, instr, "negative value");
1920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::SHL:
1923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ shl_cl(ToRegister(left));
1924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      default:
1926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        UNREACHABLE();
1927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int value = ToInteger32(LConstantOperand::cast(right));
1931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    switch (instr->op()) {
1933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::ROR:
1934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (shift_count == 0 && instr->can_deopt()) {
1935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ test(ToRegister(left), ToRegister(left));
1936b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org          DeoptimizeIf(sign, instr, "negative value");
1937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else {
1938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ ror(ToRegister(left), shift_count);
1939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::SAR:
1942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (shift_count != 0) {
1943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ sar(ToRegister(left), shift_count);
1944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::SHR:
1947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (shift_count != 0) {
1948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ shr(ToRegister(left), shift_count);
1949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        } else if (instr->can_deopt()) {
1950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ test(ToRegister(left), ToRegister(left));
1951b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org          DeoptimizeIf(sign, instr, "negative value");
1952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case Token::SHL:
1955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (shift_count != 0) {
1956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          if (instr->hydrogen_value()->representation().IsSmi() &&
1957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              instr->can_deopt()) {
1958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            if (shift_count != 1) {
1959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              __ shl(ToRegister(left), shift_count - 1);
1960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            }
1961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            __ SmiTag(ToRegister(left));
1962b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org            DeoptimizeIf(overflow, instr, "overflow");
1963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          } else {
1964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            __ shl(ToRegister(left), shift_count);
1965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          }
1966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
1967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      default:
1969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        UNREACHABLE();
1970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
1971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
1972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoSubI(LSubI* instr) {
1977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* left = instr->left();
1978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* right = instr->right();
1979e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(left->Equals(instr->result()));
1980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (right->IsConstantOperand()) {
1982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sub(ToOperand(left),
1983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           ToImmediate(right, instr->hydrogen()->representation()));
1984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
1985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sub(ToRegister(left), ToOperand(right));
1986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1988b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(overflow, instr, "overflow");
1989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
1990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoConstantI(LConstantI* instr) {
1994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
1996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
1998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoConstantS(LConstantS* instr) {
1999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(ToRegister(instr->result()), Immediate(instr->value()));
2000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoConstantD(LConstantD* instr) {
2004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  double v = instr->value();
2005e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org  uint64_t int_val = bit_cast<uint64_t, double>(v);
2006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t lower = static_cast<int32_t>(int_val);
2007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
2008e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->result()->IsDoubleRegister());
2009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(upper));
2011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(lower));
2012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register reg = ToX87Register(instr->result());
2013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Mov(reg, Operand(esp, 0));
2014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(Operand(esp), Immediate(kDoubleSize));
2015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoConstantE(LConstantE* instr) {
2019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value()));
2020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoConstantT(LConstantT* instr) {
2024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(instr->result());
2025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Object> object = instr->value(isolate());
2026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AllowDeferredHandleDereference smi_check;
2027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadObject(reg, object);
2028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMapEnumLength(LMapEnumLength* instr) {
2032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
2033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register map = ToRegister(instr->value());
2034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ EnumLength(result, map);
2035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDateField(LDateField* instr) {
2039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ToRegister(instr->date());
2040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
2041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = ToRegister(instr->temp());
2042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Smi* index = instr->index();
2043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label runtime, done;
2044e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(object.is(result));
2045e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(object.is(eax));
2046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(object, Immediate(kSmiTagMask));
2048b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(zero, instr, "Smi");
2049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
2050b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(not_equal, instr, "not a date object");
2051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (index->value() == 0) {
2053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, FieldOperand(object, JSDate::kValueOffset));
2054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (index->value() < JSDate::kFirstUncachedField) {
2056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
2057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(scratch, Operand::StaticVariable(stamp));
2058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
2059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &runtime, Label::kNear);
2060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(result, FieldOperand(object, JSDate::kValueOffset +
2061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                          kPointerSize * index->value()));
2062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&done, Label::kNear);
2063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&runtime);
2065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ PrepareCallCFunction(2, scratch);
2066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(esp, 0), object);
2067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
2068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
2069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
2070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgOperand LCodeGen::BuildSeqStringOperand(Register string,
2075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        LOperand* index,
2076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        String::Encoding encoding) {
2077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (index->IsConstantOperand()) {
2078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int offset = ToRepresentation(LConstantOperand::cast(index),
2079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  Representation::Integer32());
2080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (encoding == String::TWO_BYTE_ENCODING) {
2081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      offset *= kUC16Size;
2082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(kCharSize == 1);
2084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return FieldOperand(string, SeqString::kHeaderSize + offset);
2085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return FieldOperand(
2087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      string, ToRegister(index),
2088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2,
2089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      SeqString::kHeaderSize);
2090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
2094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  String::Encoding encoding = instr->hydrogen()->encoding();
2095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
2096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register string = ToRegister(instr->string());
2097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_debug_code) {
2099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(string);
2100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
2101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
2102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
2104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
2105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
2106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
2107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                             ? one_byte_seq_type : two_byte_seq_type));
2108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Check(equal, kUnexpectedStringType);
2109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(string);
2110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
2113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (encoding == String::ONE_BYTE_ENCODING) {
2114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ movzx_b(result, operand);
2115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ movzx_w(result, operand);
2117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
2122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  String::Encoding encoding = instr->hydrogen()->encoding();
2123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register string = ToRegister(instr->string());
2124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_debug_code) {
2126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register value = ToRegister(instr->value());
2127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register index = ToRegister(instr->index());
2128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
2129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
2130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int encoding_mask =
2131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
2132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ? one_byte_seq_type : two_byte_seq_type;
2133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
2134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
2137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->value()->IsConstantOperand()) {
2138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int value = ToRepresentation(LConstantOperand::cast(instr->value()),
2139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Representation::Integer32());
2140e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_LE(0, value);
2141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (encoding == String::ONE_BYTE_ENCODING) {
2142e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_LE(value, String::kMaxOneByteCharCode);
2143864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov_b(operand, static_cast<int8_t>(value));
2144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2145e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK_LE(value, String::kMaxUtf16CodeUnit);
2146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov_w(operand, static_cast<int16_t>(value));
2147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register value = ToRegister(instr->value());
2150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (encoding == String::ONE_BYTE_ENCODING) {
2151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov_b(operand, value);
2152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov_w(operand, value);
2154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoAddI(LAddI* instr) {
2160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* left = instr->left();
2161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* right = instr->right();
2162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
2164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (right->IsConstantOperand()) {
2165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int32_t offset = ToRepresentation(LConstantOperand::cast(right),
2166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        instr->hydrogen()->representation());
2167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset));
2168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Operand address(ToRegister(left), ToRegister(right), times_1, 0);
2170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ lea(ToRegister(instr->result()), address);
2171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (right->IsConstantOperand()) {
2174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ add(ToOperand(left),
2175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             ToImmediate(right, instr->hydrogen()->representation()));
2176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ add(ToRegister(left), ToOperand(right));
2178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
2180b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(overflow, instr, "overflow");
2181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathMinMax(LMathMinMax* instr) {
2187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* left = instr->left();
2188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* right = instr->right();
2189e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(left->Equals(instr->result()));
2190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HMathMinMax::Operation operation = instr->hydrogen()->operation();
2191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
2192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label return_left;
2193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Condition condition = (operation == HMathMinMax::kMathMin)
2194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ? less_equal
2195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : greater_equal;
2196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (right->IsConstantOperand()) {
2197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Operand left_op = ToOperand(left);
2198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate immediate = ToImmediate(LConstantOperand::cast(instr->right()),
2199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                        instr->hydrogen()->representation());
2200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(left_op, immediate);
2201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(condition, &return_left, Label::kNear);
2202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(left_op, immediate);
2203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Register left_reg = ToRegister(left);
2205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Operand right_op = ToOperand(right);
2206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(left_reg, right_op);
2207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(condition, &return_left, Label::kNear);
2208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(left_reg, right_op);
2209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&return_left);
2211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
221206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    DCHECK(instr->hydrogen()->representation().IsDouble());
221306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Label check_nan_left, check_zero, return_left, return_right;
221406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
221506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Register left_reg = ToX87Register(left);
221606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Register right_reg = ToX87Register(right);
221706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
221806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87PrepareBinaryOp(left_reg, right_reg, ToX87Register(instr->result()));
221906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(1);
222006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(1);
222106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ FCmp();
222206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ j(parity_even, &check_nan_left, Label::kNear);  // At least one NaN.
222306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ j(equal, &check_zero, Label::kNear);            // left == right.
222406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ j(condition, &return_left, Label::kNear);
222506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ jmp(&return_right, Label::kNear);
222606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
222706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ bind(&check_zero);
222806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(0);
222906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fldz();
223006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ FCmp();
223106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ j(not_equal, &return_left, Label::kNear);  // left == right != 0.
223206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // At this point, both left and right are either 0 or -0.
223306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    if (operation == HMathMinMax::kMathMin) {
223406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      // Push st0 and st1 to stack, then pop them to temp registers and OR them,
223506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      // load it to left.
223606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      Register scratch_reg = ToRegister(instr->temp());
223706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ fld(1);
223806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ fld(1);
223906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ sub(esp, Immediate(2 * kPointerSize));
224006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ fstp_s(MemOperand(esp, 0));
224106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ fstp_s(MemOperand(esp, kPointerSize));
224206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ pop(scratch_reg);
224306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ xor_(MemOperand(esp, 0), scratch_reg);
224406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      X87Mov(left_reg, MemOperand(esp, 0), kX87FloatOperand);
224506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ pop(scratch_reg);  // restore esp
224606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    } else {
224706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      // Since we operate on +0 and/or -0, addsd and andsd have the same effect.
224806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      X87Fxch(left_reg);
224906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ fadd(1);
225006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    }
225106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ jmp(&return_left, Label::kNear);
225206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
225306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ bind(&check_nan_left);
225406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(0);
225506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(0);
225606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ FCmp();                                      // NaN check.
225706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ j(parity_even, &return_left, Label::kNear);  // left == NaN.
225806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
225906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ bind(&return_right);
226006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Fxch(left_reg);
226106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Mov(left_reg, right_reg);
226206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
226306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ bind(&return_left);
2264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoArithmeticD(LArithmeticD* instr) {
2269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register left = ToX87Register(instr->left());
2270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register right = ToX87Register(instr->right());
2271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register result = ToX87Register(instr->result());
2272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->op() != Token::MOD) {
2273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87PrepareBinaryOp(left, right, result);
2274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
227579390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com  // Set the precision control to double-precision.
227679390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com  __ X87SetFPUCW(0x027F);
2277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (instr->op()) {
2278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::ADD:
2279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fadd_i(1);
2280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::SUB:
2282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fsub_i(1);
2283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::MUL:
2285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fmul_i(1);
2286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::DIV:
2288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fdiv_i(1);
2289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::MOD: {
2291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Pass two doubles as arguments on the stack.
2292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ PrepareCallCFunction(4, eax);
2293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87Mov(Operand(esp, 1 * kDoubleSize), right);
2294864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87Mov(Operand(esp, 0), left);
2295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87Free(right);
2296e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(left.is(result));
2297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87PrepareToWrite(result);
2298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallCFunction(
2299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          ExternalReference::mod_two_doubles_operation(isolate()),
2300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          4);
2301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Return value is in st(0) on ia32.
2303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87CommitWrite(result);
2304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
2307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
2308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
231006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
231179390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com  // Restore the default value of control word.
231279390123903f4a8b6e973f2d4e3743948b97aeb8weiliang.lin@intel.com  __ X87SetFPUCW(0x037F);
2313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoArithmeticT(LArithmeticT* instr) {
2317e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
2318e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->left()).is(edx));
2319e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->right()).is(eax));
2320e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
2321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2322b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> code =
2323b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      CodeFactory::BinaryOpIC(isolate(), instr->op(), NO_OVERWRITE).code();
2324b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  CallCode(code, RelocInfo::CODE_TARGET, instr);
2325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgtemplate<class InstrType>
2329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitBranch(InstrType instr, Condition cc) {
2330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int left_block = instr->TrueDestination(chunk_);
2331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int right_block = instr->FalseDestination(chunk_);
2332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int next_block = GetNextEmittedBlock();
2334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (right_block == left_block || cc == no_condition) {
2336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitGoto(left_block);
2337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (left_block == next_block) {
2338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
2339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (right_block == next_block) {
2340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(cc, chunk_->GetAssemblyLabel(left_block));
2341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(cc, chunk_->GetAssemblyLabel(left_block));
2343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(chunk_->GetAssemblyLabel(right_block));
2344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgtemplate<class InstrType>
2349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
2350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int false_block = instr->FalseDestination(chunk_);
2351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (cc == no_condition) {
2352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(chunk_->GetAssemblyLabel(false_block));
2353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(cc, chunk_->GetAssemblyLabel(false_block));
2355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoBranch(LBranch* instr) {
2360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Representation r = instr->hydrogen()->value()->representation();
2361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (r.IsSmiOrInteger32()) {
2362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register reg = ToRegister(instr->value());
2363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(reg, Operand(reg));
2364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitBranch(instr, not_zero);
2365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (r.IsDouble()) {
236606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Register reg = ToX87Register(instr->value());
236706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87LoadForUsage(reg);
236806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fldz();
236906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ FCmp();
237006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    EmitBranch(instr, not_zero);
2371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2372e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(r.IsTagged());
2373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register reg = ToRegister(instr->value());
2374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    HType type = instr->hydrogen()->value()->type();
2375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (type.IsBoolean()) {
2376e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!info()->IsStub());
2377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(reg, factory()->true_value());
2378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitBranch(instr, equal);
2379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (type.IsSmi()) {
2380e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!info()->IsStub());
2381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(reg, Operand(reg));
2382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitBranch(instr, not_equal);
2383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (type.IsJSArray()) {
2384e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!info()->IsStub());
2385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitBranch(instr, no_condition);
2386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (type.IsHeapNumber()) {
2387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
2388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (type.IsString()) {
2389e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!info()->IsStub());
2390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      EmitBranch(instr, not_equal);
2392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // undefined -> false.
2398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(reg, factory()->undefined_value());
2399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(equal, instr->FalseLabel(chunk_));
2400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.Contains(ToBooleanStub::BOOLEAN)) {
2402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // true -> true.
2403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(reg, factory()->true_value());
2404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(equal, instr->TrueLabel(chunk_));
2405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // false -> false.
2406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(reg, factory()->false_value());
2407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(equal, instr->FalseLabel(chunk_));
2408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
2410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // 'null' -> false.
2411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(reg, factory()->null_value());
2412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(equal, instr->FalseLabel(chunk_));
2413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.Contains(ToBooleanStub::SMI)) {
2416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Smis: 0 -> false, all other -> true.
2417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ test(reg, Operand(reg));
2418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(equal, instr->FalseLabel(chunk_));
2419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else if (expected.NeedsMap()) {
2421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // If we need a map later and have a Smi -> deopt.
2422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ test(reg, Immediate(kSmiTagMask));
2423b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org        DeoptimizeIf(zero, instr, "Smi");
2424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Register map = no_reg;  // Keep the compiler happy.
2427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.NeedsMap()) {
2428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        map = ToRegister(instr->temp());
2429e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org        DCHECK(!map.is(reg));
2430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
2431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (expected.CanBeUndetectable()) {
2433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          // Undetectable -> false.
2434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ test_b(FieldOperand(map, Map::kBitFieldOffset),
2435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                    1 << Map::kIsUndetectable);
2436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ j(not_zero, instr->FalseLabel(chunk_));
2437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
2438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
2441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // spec object -> true.
2442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
2443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(above_equal, instr->TrueLabel(chunk_));
2444864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.Contains(ToBooleanStub::STRING)) {
2447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // String value -> false iff empty.
2448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Label not_string;
2449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
2450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(above_equal, &not_string, Label::kNear);
2451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(not_zero, instr->TrueLabel(chunk_));
2453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ jmp(instr->FalseLabel(chunk_));
2454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&not_string);
2455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.Contains(ToBooleanStub::SYMBOL)) {
2458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // Symbol value -> true.
2459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ CmpInstanceType(map, SYMBOL_TYPE);
2460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(equal, instr->TrueLabel(chunk_));
2461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // heap number -> false iff +0, -0, or NaN.
2465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        Label not_heap_number;
2466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
2467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               factory()->heap_number_map());
2468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(not_equal, &not_heap_number, Label::kNear);
2469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ fldz();
2470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
2471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ FCmp();
2472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ j(zero, instr->FalseLabel(chunk_));
2473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ jmp(instr->TrueLabel(chunk_));
2474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ bind(&not_heap_number);
2475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (!expected.IsGeneric()) {
2478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // We've seen something for the first time -> deopt.
2479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        // This can only happen if we are not generic already.
2480b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org        DeoptimizeIf(no_condition, instr, "unexpected object");
2481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitGoto(int block) {
2488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!IsNextEmittedBlock(block)) {
2489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoClobberDoubles(LClobberDoubles* instr) {
2495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoGoto(LGoto* instr) {
2499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitGoto(instr->block_id());
2500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2501864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgCondition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
2504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition cond = no_condition;
2505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (op) {
2506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::EQ:
2507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::EQ_STRICT:
2508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cond = equal;
2509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::NE:
2511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::NE_STRICT:
2512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cond = not_equal;
2513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::LT:
2515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cond = is_unsigned ? below : less;
2516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::GT:
2518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cond = is_unsigned ? above : greater;
2519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::LTE:
2521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cond = is_unsigned ? below_equal : less_equal;
2522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::GTE:
2524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      cond = is_unsigned ? above_equal : greater_equal;
2525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      break;
2526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::IN:
2527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::INSTANCEOF:
2528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
2529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
2530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return cond;
2532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
2536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* left = instr->left();
2537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* right = instr->right();
2538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool is_unsigned =
25398ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org      instr->is_double() ||
25408ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org      instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
25418ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org      instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
2542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition cc = TokenToCondition(instr->op(), is_unsigned);
2543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (left->IsConstantOperand() && right->IsConstantOperand()) {
2545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // We can statically evaluate the comparison.
2546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    double left_val = ToDouble(LConstantOperand::cast(left));
2547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    double right_val = ToDouble(LConstantOperand::cast(right));
2548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int next_block = EvalComparison(instr->op(), left_val, right_val) ?
2549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
2550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitGoto(next_block);
2551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->is_double()) {
2553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      X87LoadForUsage(ToX87Register(right), ToX87Register(left));
2554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ FCmp();
2555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Don't base result on EFLAGS when a NaN is involved. Instead
2556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // jump to the false block.
2557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(parity_even, instr->FalseLabel(chunk_));
2558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
2559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (right->IsConstantOperand()) {
2560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(ToOperand(left),
2561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               ToImmediate(right, instr->hydrogen()->representation()));
2562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else if (left->IsConstantOperand()) {
2563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(ToOperand(right),
2564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org               ToImmediate(left, instr->hydrogen()->representation()));
256538de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org        // We commuted the operands, so commute the condition.
256638de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org        cc = CommuteCondition(cc);
2567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      } else {
2568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmp(ToRegister(left), ToOperand(right));
2569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
2570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitBranch(instr, cc);
2572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register left = ToRegister(instr->left());
2578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->right()->IsConstantOperand()) {
2580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
2581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObject(left, right);
2582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand right = ToOperand(instr->right());
2584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(left, right);
2585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, equal);
2587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->representation().IsTagged()) {
2592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register input_reg = ToRegister(instr->object());
2593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(input_reg, factory()->the_hole_value());
2594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitBranch(instr, equal);
2595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
2596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put the value to the top of stack
2599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register src = ToX87Register(instr->object());
2600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87LoadForUsage(src);
2601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ fld(0);
2602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ fld(0);
2603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ FCmp();
2604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label ok;
2605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(parity_even, &ok, Label::kNear);
2606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ fstp(0);
2607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitFalseBranch(instr, no_condition);
2608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&ok);
2609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(esp, Immediate(kDoubleSize));
2612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ fstp_d(MemOperand(esp, 0));
2613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(esp, Immediate(kDoubleSize));
2615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int offset = sizeof(kHoleNanUpper32);
2616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
2617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, equal);
2618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Representation rep = instr->hydrogen()->value()->representation();
2623e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!rep.IsInteger32());
2624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (rep.IsDouble()) {
262606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Register input = ToX87Register(instr->value());
262706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87LoadForUsage(input);
262806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ FXamMinusZero();
262906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    EmitBranch(instr, equal);
2630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register value = ToRegister(instr->value());
2632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
2633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
2634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(FieldOperand(value, HeapNumber::kExponentOffset),
2635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           Immediate(0x1));
2636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitFalseBranch(instr, no_overflow);
2637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(FieldOperand(value, HeapNumber::kMantissaOffset),
2638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           Immediate(0x00000000));
2639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitBranch(instr, equal);
2640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgCondition LCodeGen::EmitIsObject(Register input,
2645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Register temp1,
2646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Label* is_not_object,
2647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Label* is_object) {
2648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(input, is_not_object);
2649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(input, isolate()->factory()->null_value());
2651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, is_object);
2652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
2654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Undetectable objects behave like undefined.
2655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test_b(FieldOperand(temp1, Map::kBitFieldOffset),
2656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            1 << Map::kIsUndetectable);
2657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, is_not_object);
2658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset));
2660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
2661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(below, is_not_object);
2662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
2663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return below_equal;
2664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
2668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(instr->value());
2669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
2670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition true_cond = EmitIsObject(
2672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
2673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, true_cond);
2675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgCondition LCodeGen::EmitIsString(Register input,
2679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Register temp1,
2680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 Label* is_not_string,
2681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 SmiCheck check_needed = INLINE_SMI_CHECK) {
2682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (check_needed == INLINE_SMI_CHECK) {
2683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, is_not_string);
2684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition cond = masm_->IsObjectStringType(input, temp1, temp1);
2687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return cond;
2689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(instr->value());
2694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
2695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SmiCheck check_needed =
2697eac65cd57a2d5f018fc440eed1b69d0fe80fe336machenbach@chromium.org      instr->hydrogen()->value()->type().IsHeapObject()
2698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition true_cond = EmitIsString(
2701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      reg, temp, instr->FalseLabel(chunk_), check_needed);
2702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, true_cond);
2704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand input = ToOperand(instr->value());
2709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(input, Immediate(kSmiTagMask));
2711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, zero);
2712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input = ToRegister(instr->value());
2717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
2718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2719eac65cd57a2d5f018fc440eed1b69d0fe80fe336machenbach@chromium.org  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(kSmiTag == 0);
2721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
2724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
2725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            1 << Map::kIsUndetectable);
2726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, not_zero);
2727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic Condition ComputeCompareCondition(Token::Value op) {
2731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  switch (op) {
2732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::EQ_STRICT:
2733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::EQ:
2734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return equal;
2735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::LT:
2736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return less;
2737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::GT:
2738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return greater;
2739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::LTE:
2740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return less_equal;
2741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    case Token::GTE:
2742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return greater_equal;
2743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    default:
2744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      UNREACHABLE();
2745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return no_condition;
2746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Token::Value op = instr->op();
2752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2753b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
2754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(ic, RelocInfo::CODE_TARGET, instr);
2755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition condition = ComputeCompareCondition(op);
2757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(eax, Operand(eax));
2758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, condition);
2760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InstanceType from = instr->from();
2765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InstanceType to = instr->to();
2766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (from == FIRST_TYPE) return to;
2767e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(from == to || to == LAST_TYPE);
2768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return from;
2769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgstatic Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InstanceType from = instr->from();
2774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InstanceType to = instr->to();
2775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (from == to) return equal;
2776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (to == LAST_TYPE) return above_equal;
2777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (from == FIRST_TYPE) return below_equal;
2778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  UNREACHABLE();
2779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return equal;
2780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input = ToRegister(instr->value());
2785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
2786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2787eac65cd57a2d5f018fc440eed1b69d0fe80fe336machenbach@chromium.org  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(input, TestType(instr->hydrogen()), temp);
2792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, BranchCondition(instr->hydrogen()));
2793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
2797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input = ToRegister(instr->value());
2798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
2799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ AssertString(input);
2801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, FieldOperand(input, String::kHashFieldOffset));
2803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ IndexFromHash(result, result);
2804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoHasCachedArrayIndexAndBranch(
2808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LHasCachedArrayIndexAndBranch* instr) {
2809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input = ToRegister(instr->value());
2810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(FieldOperand(input, String::kHashFieldOffset),
2812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          Immediate(String::kContainsCachedArrayIndexMask));
2813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, equal);
2814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// Branches to a label or falls through with the answer in the z flag.  Trashes
2818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org// the temp registers, but not the input.
2819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitClassOfTest(Label* is_true,
2820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Label* is_false,
2821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Handle<String>class_name,
2822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register input,
2823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register temp,
2824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               Register temp2) {
2825e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!input.is(temp));
2826e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!input.is(temp2));
2827e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!temp.is(temp2));
2828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(input, is_false);
2829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
28305e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
2831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Assuming the following assertions, we can use the same compares to test
2832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // for both being a function type and being in the object type range.
2833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                  FIRST_SPEC_OBJECT_TYPE + 1);
2836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                  LAST_SPEC_OBJECT_TYPE - 1);
2838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
2839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
2840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(below, is_false);
2841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, is_true);
2842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE);
2843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, is_true);
2844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Faster code path to avoid two compares: subtract lower bound from the
2846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // actual type and do a signed compare with the width of the type range.
2847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
2848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
2849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
2851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(above, is_false);
2853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
2856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check if the constructor in the map is a function.
2857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp, FieldOperand(temp, Map::kConstructorOffset));
2858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Objects with a non-function constructor have class 'Object'.
2859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2);
28605e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org  if (String::Equals(class_name, isolate()->factory()->Object_string())) {
2861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, is_true);
2862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
2863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, is_false);
2864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
2865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // temp now contains the constructor function. Grab the
2867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // instance class name from there.
2868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
2869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp, FieldOperand(temp,
2870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                            SharedFunctionInfo::kInstanceClassNameOffset));
2871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The class name we are testing against is internalized since it's a literal.
2872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The name in the constructor is internalized because of the way the context
2873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // is booted.  This routine isn't expected to work for random API-created
2874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // classes and it doesn't have to because you can't access it with natives
2875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // syntax.  Since both sides are internalized it is sufficient to use an
2876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // identity comparison.
2877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(temp, class_name);
2878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // End with the answer in the z flag.
2879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input = ToRegister(instr->value());
2884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
2885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp2 = ToRegister(instr->temp2());
2886864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<String> class_name = instr->hydrogen()->class_name();
2888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      class_name, input, temp, temp2);
2891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, equal);
2893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(instr->value());
2898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
2899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, equal);
2900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Object and function are in fixed registers defined by the stub.
2905e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
2906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters);
2907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label true_value, done;
2910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(eax, Operand(eax));
2911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(zero, &true_value, Label::kNear);
2912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ToRegister(instr->result()), factory()->false_value());
2913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
2914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&true_value);
2915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ToRegister(instr->result()), factory()->true_value());
2916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
2917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2921ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredInstanceOfKnownGlobal FINAL : public LDeferredCode {
2922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
2923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  LInstanceOfKnownGlobal* instr,
2925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  const X87Stack& x87_stack)
2926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
2927ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
2928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
2929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
2930ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
2931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* map_check() { return &map_check_; }
2932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
2933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LInstanceOfKnownGlobal* instr_;
2934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label map_check_;
2935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
2936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredInstanceOfKnownGlobal* deferred;
2938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_);
2939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done, false_result;
2941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ToRegister(instr->value());
2942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
2943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // A Smi is not an instance of anything.
2945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(object, &false_result, Label::kNear);
2946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // This is the inlined call site instanceof cache. The two occurences of the
2948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // hole value will be patched to the last map/result pair generated by the
2949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // instanceof stub.
2950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label cache_miss;
2951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register map = ToRegister(instr->temp());
2952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
2953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->map_check());  // Label for calculating code patching.
2954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
2955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(map, Operand::ForCell(cache_cell));  // Patched to cached map.
2956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &cache_miss, Label::kNear);
2957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, factory()->the_hole_value());  // Patched to either true or false.
2958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
2959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The inlined call site cache did not match. Check for null and string
2961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // before calling the deferred code.
2962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&cache_miss);
2963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Null is not an instance of anything.
2964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(object, factory()->null_value());
2965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &false_result, Label::kNear);
2966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // String values are not instances of anything.
2968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition is_string = masm_->IsObjectStringType(object, temp, temp);
2969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(is_string, &false_result, Label::kNear);
2970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Go to the deferred code.
2972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(deferred->entry());
2973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&false_result);
2975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ToRegister(instr->result()), factory()->false_value());
2976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Here result has either true or false. Deferred code also produces true or
2978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // false object.
2979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->exit());
2980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
2981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
2982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
2985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                               Label* map_check) {
2986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushSafepointRegistersScope scope(this);
2987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
2989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  flags = static_cast<InstanceofStub::Flags>(
2990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      flags | InstanceofStub::kArgsInRegisters);
2991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  flags = static_cast<InstanceofStub::Flags>(
2992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      flags | InstanceofStub::kCallSiteInlineCheck);
2993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  flags = static_cast<InstanceofStub::Flags>(
2994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      flags | InstanceofStub::kReturnTrueFalseObject);
2995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  InstanceofStub stub(isolate(), flags);
2996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
2997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the temp register reserved by the instruction. This needs to be a
2998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // register which is pushed last by PushSafepointRegisters as top of the
2999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // stack is used to pass the offset to the location of the map check to
3000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the stub.
3001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
3002e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(MacroAssembler::SafepointRegisterStackIndex(temp) == 0);
3003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadHeapObject(InstanceofStub::right(), instr->function());
3004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  static const int kAdditionalDelta = 13;
3005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
3006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp, Immediate(delta));
3007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ StoreToSafepointRegisterSlot(temp, temp);
3008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCodeGeneric(stub.GetCode(),
3009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                  RelocInfo::CODE_TARGET,
3010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                  instr,
3011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                  RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
3012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the deoptimization index of the LLazyBailout-environment that
3013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // corresponds to this instruction.
3014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
3015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
3016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put the result value into the eax slot and restore all registers.
3018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ StoreToSafepointRegisterSlot(eax, eax);
3019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCmpT(LCmpT* instr) {
3023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Token::Value op = instr->op();
3024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3025b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
3026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(ic, RelocInfo::CODE_TARGET, instr);
3027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition condition = ComputeCompareCondition(op);
3029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label true_value, done;
3030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(eax, Operand(eax));
3031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(condition, &true_value, Label::kNear);
3032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ToRegister(instr->result()), factory()->false_value());
3033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
3034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&true_value);
3035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ToRegister(instr->result()), factory()->true_value());
3036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) {
3041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int extra_value_count = dynamic_frame_alignment ? 2 : 1;
3042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->has_constant_parameter_count()) {
3044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int parameter_count = ToInteger32(instr->constant_parameter_count());
3045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (dynamic_frame_alignment && FLAG_debug_code) {
3046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(Operand(esp,
3047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     (parameter_count + extra_value_count) * kPointerSize),
3048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             Immediate(kAlignmentZapValue));
3049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Assert(equal, kExpectedAlignmentMarker);
3050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx);
3052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register reg = ToRegister(instr->parameter_count());
3054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The argument count parameter is a smi
3055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(reg);
3056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register return_addr_reg = reg.is(ecx) ? ebx : ecx;
3057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (dynamic_frame_alignment && FLAG_debug_code) {
3058e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(extra_value_count == 2);
3059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(Operand(esp, reg, times_pointer_size,
3060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     extra_value_count * kPointerSize),
3061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             Immediate(kAlignmentZapValue));
3062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Assert(equal, kExpectedAlignmentMarker);
3063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // emit code to restore stack based on instr->parameter_count()
3066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(return_addr_reg);  // save return address
3067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (dynamic_frame_alignment) {
3068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ inc(reg);  // 1 more for alignment
3069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ shl(reg, kPointerSizeLog2);
3071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ add(esp, reg);
3072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(return_addr_reg);
3073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoReturn(LReturn* instr) {
3078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_trace && info()->IsOptimizing()) {
3079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Preserve the return value on the stack and rely on the runtime call
3080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // to return the value in the same register.  We're leaving the code
3081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // managed by the register allocator and tearing down the frame, it's
3082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // safe to write to the context register.
3083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(eax);
3084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallRuntime(Runtime::kTraceExit, 1);
3086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (dynamic_frame_alignment_) {
3088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Fetch the state of the dynamic frame alignment.
3089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, Operand(ebp,
3090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      JavaScriptFrameConstants::kDynamicAlignmentStateOffset));
3091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int no_frame_start = -1;
3093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (NeedsEagerFrame()) {
3094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esp, ebp);
3095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(ebp);
3096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    no_frame_start = masm_->pc_offset();
3097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (dynamic_frame_alignment_) {
3099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label no_padding;
3100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(edx, Immediate(kNoAlignmentPadding));
3101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, &no_padding, Label::kNear);
3102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitReturn(instr, true);
3104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&no_padding);
3105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitReturn(instr, false);
3108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (no_frame_start != -1) {
3109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
3110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
3115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle()));
3117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->RequiresHoleCheck()) {
3118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(result, factory()->the_hole_value());
3119b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(equal, instr, "hole");
3120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3124fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgtemplate <class T>
3125fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.orgvoid LCodeGen::EmitVectorLoadICRegisters(T* instr) {
3126fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  DCHECK(FLAG_vector_ics);
3127fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  Register vector = ToRegister(instr->temp_vector());
312842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
3129fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  __ mov(vector, instr->hydrogen()->feedback_vector());
3130fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org  // No need to allocate this register.
313142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(VectorLoadICDescriptor::SlotRegister().is(eax));
313242ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(VectorLoadICDescriptor::SlotRegister(),
3133fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org         Immediate(Smi::FromInt(instr->hydrogen()->slot())));
3134fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org}
3135fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org
3136fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org
3137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
3138e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
31397b6dc58d68c4315b99f5ec3faf6927db3d0db913machenbach@chromium.org  DCHECK(ToRegister(instr->global_object())
314042ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org             .is(LoadDescriptor::ReceiverRegister()));
3141e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
3142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
314342ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(LoadDescriptor::NameRegister(), instr->name());
31447c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  if (FLAG_vector_ics) {
3145fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
31467c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  }
3147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
3148b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
3149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(ic, RelocInfo::CODE_TARGET, instr);
3150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
3154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register value = ToRegister(instr->value());
3155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle();
3156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the cell we are storing to contains the hole it could have
3158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // been deleted from the property dictionary. In that case, we need
3159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // to update the property details in the property dictionary to mark
3160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // it as no longer deleted. We deoptimize in that case.
3161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->RequiresHoleCheck()) {
3162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
3163b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(equal, instr, "hole");
3164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Store the value.
3167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(Operand::ForCell(cell_handle), value);
3168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Cells are always rescanned, so no write barrier here.
3169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register context = ToRegister(instr->context());
3174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, ContextOperand(context, instr->slot_index()));
3176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->RequiresHoleCheck()) {
3178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(result, factory()->the_hole_value());
3179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->hydrogen()->DeoptimizesOnHole()) {
3180b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(equal, instr, "hole");
3181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
3182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label is_not_hole;
3183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &is_not_hole, Label::kNear);
3184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(result, factory()->undefined_value());
3185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&is_not_hole);
3186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register context = ToRegister(instr->context());
3193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register value = ToRegister(instr->value());
3194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label skip_assignment;
3196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand target = ContextOperand(context, instr->slot_index());
3198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->RequiresHoleCheck()) {
3199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(target, factory()->the_hole_value());
3200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->hydrogen()->DeoptimizesOnHole()) {
3201b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(equal, instr, "hole");
3202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
3203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &skip_assignment, Label::kNear);
3204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(target, value);
3208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->NeedsWriteBarrier()) {
3209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SmiCheck check_needed =
3210eac65cd57a2d5f018fc440eed1b69d0fe80fe336machenbach@chromium.org        instr->hydrogen()->value()->type().IsHeapObject()
3211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register temp = ToRegister(instr->temp());
3213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int offset = Context::SlotOffset(instr->slot_index());
321406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ RecordWriteContextSlot(context, offset, value, temp, kSaveFPRegs,
321506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                              EMIT_REMEMBERED_SET, check_needed);
3216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&skip_assignment);
3219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
3223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HObjectAccess access = instr->hydrogen()->access();
3224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int offset = access.offset();
3225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (access.IsExternalMemory()) {
3227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register result = ToRegister(instr->result());
3228864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    MemOperand operand = instr->object()->IsConstantOperand()
3229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ? MemOperand::StaticVariable(ToExternalReference(
3230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                LConstantOperand::cast(instr->object())))
3231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : MemOperand(ToRegister(instr->object()), offset);
3232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Load(result, operand, access.representation());
3233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
3234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ToRegister(instr->object());
3237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->representation().IsDouble()) {
3238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
3239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
3240864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3243864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!access.IsInobject()) {
3244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
3245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    object = result;
3246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Load(result, FieldOperand(object, offset), access.representation());
3248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
3252e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!operand->IsDoubleRegister());
3253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (operand->IsConstantOperand()) {
3254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
3255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    AllowDeferredHandleDereference smi_check;
3256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (object->IsSmi()) {
3257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Push(Handle<Smi>::cast(object));
3258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
3259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ PushHeapObject(Handle<HeapObject>::cast(object));
3260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (operand->IsRegister()) {
3262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(ToRegister(operand));
3263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(ToOperand(operand));
3265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
3270e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
327142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3272e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
3273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
327442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(LoadDescriptor::NameRegister(), instr->name());
32757c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  if (FLAG_vector_ics) {
3276fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
32777c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  }
3278b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
3279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(ic, RelocInfo::CODE_TARGET, instr);
3280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
3284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register function = ToRegister(instr->function());
3285864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
3286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the prototype or initial map from the function.
3289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result,
3290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3291864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check that the function has a prototype or an initial map.
3293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
3294b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(equal, instr, "hole");
3295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the function does not have an initial map, we're done.
3297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
3298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(result, MAP_TYPE, temp);
3299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &done, Label::kNear);
3300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the prototype from the initial map.
3302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
3303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // All done.
3305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadRoot(LLoadRoot* instr) {
3310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadRoot(result, instr->index());
3312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
3316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register arguments = ToRegister(instr->arguments());
3317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->length()->IsConstantOperand() &&
3319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->index()->IsConstantOperand()) {
3320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
3322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int index = (const_length - const_index) + 1;
3323864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, Operand(arguments, index * kPointerSize));
3324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register length = ToRegister(instr->length());
3326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand index = ToOperand(instr->index());
3327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // There are two words between the frame pointer and the last argument.
3328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Subtracting from length accounts for one of them add one more.
3329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ sub(length, index);
3330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, Operand(arguments, length, times_4, kPointerSize));
3331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
3336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ElementsKind elements_kind = instr->elements_kind();
3337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* key = instr->key();
3338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!key->IsConstantOperand() &&
3339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
3340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  elements_kind)) {
3341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(ToRegister(key));
3342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand operand(BuildFastArrayOperand(
3344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->elements(),
3345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      key,
3346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->hydrogen()->key()->representation(),
3347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      elements_kind,
3348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->base_offset()));
3349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
3350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      elements_kind == FLOAT32_ELEMENTS) {
3351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
3352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
3353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             elements_kind == FLOAT64_ELEMENTS) {
3354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Mov(ToX87Register(instr->result()), operand);
3355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register result(ToRegister(instr->result()));
3357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    switch (elements_kind) {
3358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_INT8_ELEMENTS:
3359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case INT8_ELEMENTS:
3360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ movsx_b(result, operand);
3361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
3362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
3363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_UINT8_ELEMENTS:
3364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case UINT8_ELEMENTS:
3365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case UINT8_CLAMPED_ELEMENTS:
3366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ movzx_b(result, operand);
3367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
3368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_INT16_ELEMENTS:
3369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case INT16_ELEMENTS:
3370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ movsx_w(result, operand);
3371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
3372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_UINT16_ELEMENTS:
3373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case UINT16_ELEMENTS:
3374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ movzx_w(result, operand);
3375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
3376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_INT32_ELEMENTS:
3377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case INT32_ELEMENTS:
3378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(result, operand);
3379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
3380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_UINT32_ELEMENTS:
3381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case UINT32_ELEMENTS:
3382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(result, operand);
3383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          __ test(result, Operand(result));
3385b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org          DeoptimizeIf(negative, instr, "negative value");
3386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        }
3387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
3388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_FLOAT32_ELEMENTS:
3389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_FLOAT64_ELEMENTS:
3390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FLOAT32_ELEMENTS:
3391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FLOAT64_ELEMENTS:
3392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_SMI_ELEMENTS:
3393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_ELEMENTS:
3394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_DOUBLE_ELEMENTS:
3395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_HOLEY_SMI_ELEMENTS:
3396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_HOLEY_ELEMENTS:
3397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_HOLEY_DOUBLE_ELEMENTS:
3398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case DICTIONARY_ELEMENTS:
3399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case SLOPPY_ARGUMENTS_ELEMENTS:
3400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        UNREACHABLE();
3401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
3402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->RequiresHoleCheck()) {
3409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand hole_check_operand = BuildFastArrayOperand(
3410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->elements(), instr->key(),
3411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->hydrogen()->key()->representation(),
3412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        FAST_DOUBLE_ELEMENTS,
3413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->base_offset() + sizeof(kHoleNanLower32));
3414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
3415b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(equal, instr, "hole");
3416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand double_load_operand = BuildFastArrayOperand(
3419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->elements(),
3420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->key(),
3421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->hydrogen()->key()->representation(),
3422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FAST_DOUBLE_ELEMENTS,
3423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->base_offset());
3424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Mov(ToX87Register(instr->result()), double_load_operand);
3425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Load the result.
3432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result,
3433b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org         BuildFastArrayOperand(instr->elements(), instr->key(),
3434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               instr->hydrogen()->key()->representation(),
3435b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                               FAST_ELEMENTS, instr->base_offset()));
3436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for the hole value.
3438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->RequiresHoleCheck()) {
3439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(result, Immediate(kSmiTagMask));
3441b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(not_equal, instr, "not a Smi");
3442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
3443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(result, factory()->the_hole_value());
3444b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(equal, instr, "hole");
3445864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3447864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->is_typed_elements()) {
3452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DoLoadKeyedExternalArray(instr);
3453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (instr->hydrogen()->representation().IsDouble()) {
3454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DoLoadKeyedFixedDoubleArray(instr);
3455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DoLoadKeyedFixedArray(instr);
3457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgOperand LCodeGen::BuildFastArrayOperand(
3462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LOperand* elements_pointer,
3463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LOperand* key,
3464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Representation key_representation,
3465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ElementsKind elements_kind,
3466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    uint32_t base_offset) {
3467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register elements_pointer_reg = ToRegister(elements_pointer);
3468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int element_shift_size = ElementsKindToShiftSize(elements_kind);
3469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int shift_size = element_shift_size;
3470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (key->IsConstantOperand()) {
3471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int constant_value = ToInteger32(LConstantOperand::cast(key));
3472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (constant_value & 0xF0000000) {
3473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Abort(kArrayIndexConstantValueTooBig);
3474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return Operand(elements_pointer_reg,
3476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   ((constant_value) << shift_size)
3477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       + base_offset);
3478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Take the tag bit into account while computing the shift size.
3480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (key_representation.IsSmi() && (shift_size >= 1)) {
3481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      shift_size -= kSmiTagSize;
3482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
3484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return Operand(elements_pointer_reg,
3485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   ToRegister(key),
3486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   scale_factor,
3487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                   base_offset);
3488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
3493e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
349442ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
349542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
3496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
34977c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  if (FLAG_vector_ics) {
3498fa7f914e3bacba481b13da5cf2bc4c935567ebc4machenbach@chromium.org    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
34997c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org  }
35007c0666e15d1f68f0fef5db9e5c409fab010ed816machenbach@chromium.org
3501b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
3502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(ic, RelocInfo::CODE_TARGET, instr);
3503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
3507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->from_inlined()) {
3510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ lea(result, Operand(esp, -2 * kPointerSize));
3511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check for arguments adapter frame.
3513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done, adapted;
3514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, Operand(result, StandardFrameConstants::kContextOffset));
3516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(Operand(result),
3517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, &adapted, Label::kNear);
3519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // No arguments adaptor frame.
3521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, Operand(ebp));
3522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&done, Label::kNear);
3523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Arguments adaptor frame present.
3525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&adapted);
3526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Result is the frame pointer for the frame if not adapted and for the real
3529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // frame below the adaptor frame if adapted.
3530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
3531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
3536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand elem = ToOperand(instr->elements());
3537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done;
3540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If no arguments adaptor frame the number of arguments is fixed.
3542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ebp, elem);
3543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, Immediate(scope()->num_parameters()));
3544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &done, Label::kNear);
3545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Arguments adaptor frame present. Get argument length from there.
3547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, Operand(result,
3549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         ArgumentsAdaptorFrameConstants::kLengthOffset));
3550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(result);
3551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Argument length is in result register.
3553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register receiver = ToRegister(instr->receiver());
3559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register function = ToRegister(instr->function());
3560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the receiver is null or undefined, we have to pass the global
3562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // object as a receiver to normal functions. Values have to be
3563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // passed unchanged to builtins and strict-mode functions.
3564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label receiver_ok, global_object;
3565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = ToRegister(instr->temp());
3567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!instr->hydrogen()->known_function()) {
3569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Do not transform the receiver to object for strict mode
3570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // functions.
3571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(scratch,
3572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
3574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              1 << SharedFunctionInfo::kStrictModeBitWithinByte);
3575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &receiver_ok, dist);
3576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Do not transform the receiver to object for builtins.
3578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
3579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              1 << SharedFunctionInfo::kNativeBitWithinByte);
3580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &receiver_ok, dist);
3581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Normal function. Replace undefined or null with global receiver.
3584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(receiver, factory()->null_value());
3585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &global_object, Label::kNear);
3586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(receiver, factory()->undefined_value());
3587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &global_object, Label::kNear);
3588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The receiver should be a JS object.
3590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(receiver, Immediate(kSmiTagMask));
3591b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(equal, instr, "Smi");
3592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
3593b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(below, instr, "not a JavaScript object");
3594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&receiver_ok, Label::kNear);
3596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&global_object);
3597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
3598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
3599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(receiver, Operand(receiver, global_offset));
3600d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  const int proxy_offset = GlobalObject::kGlobalProxyOffset;
3601d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  __ mov(receiver, FieldOperand(receiver, proxy_offset));
3602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&receiver_ok);
3603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register receiver = ToRegister(instr->receiver());
3608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register function = ToRegister(instr->function());
3609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register length = ToRegister(instr->length());
3610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register elements = ToRegister(instr->elements());
3611e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(receiver.is(eax));  // Used for parameter count.
3612e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(function.is(edi));  // Required by InvokeFunction.
3613e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
3614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Copy the arguments to this function possibly from the
3616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // adaptor frame below it.
3617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const uint32_t kArgumentsLimit = 1 * KB;
3618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(length, kArgumentsLimit);
3619b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(above, instr, "too many arguments");
3620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(receiver);
3622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(receiver, length);
3623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Loop through the arguments pushing them onto the execution
3625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // stack.
3626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label invoke, loop;
3627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // length is a small non-negative integer, due to the test above.
3628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(length, Operand(length));
3629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(zero, &invoke, Label::kNear);
3630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&loop);
3631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
3632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ dec(length);
3633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, &loop);
3634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Invoke the function.
3636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&invoke);
3637e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->HasPointerMap());
3638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LPointerMap* pointers = instr->pointer_map();
3639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SafepointGenerator safepoint_generator(
3640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      this, pointers, Safepoint::kLazyDeopt);
3641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ParameterCount actual(eax);
3642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
3643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDebugBreak(LDebugBreak* instr) {
3647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ int3();
3648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoPushArgument(LPushArgument* instr) {
3652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* argument = instr->value();
3653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitPushTaggedOperand(argument);
3654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDrop(LDrop* instr) {
3658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Drop(instr->count());
3659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoThisFunction(LThisFunction* instr) {
3663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
3665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoContext(LContext* instr) {
3669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
3670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (info()->IsOptimizing()) {
3671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
3672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If there is no frame, the context must be in esi.
3674e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(result.is(esi));
3675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3680e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
3681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(esi);  // The context is the first argument.
3682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(instr->hydrogen()->pairs()));
3683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags())));
368447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  CallRuntime(Runtime::kDeclareGlobals, 3, instr);
3685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3686864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3688864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 int formal_parameter_count,
3690864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 int arity,
3691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 LInstruction* instr,
3692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                 EDIState edi_state) {
3693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool dont_adapt_arguments =
3694864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool can_invoke_directly =
3696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      dont_adapt_arguments || formal_parameter_count == arity;
3697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (can_invoke_directly) {
3699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (edi_state == EDI_UNINITIALIZED) {
3700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ LoadHeapObject(edi, function);
3701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Change context.
3704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
3705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Set eax to arguments count if adaption is not needed. Assumes that eax
3707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // is available to write to at this point.
3708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (dont_adapt_arguments) {
3709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(eax, arity);
3710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Invoke function directly.
3713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (function.is_identical_to(info()->closure())) {
3714864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ CallSelf();
3715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
3716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
3717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3720864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // We need to adapt arguments.
3721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LPointerMap* pointers = instr->pointer_map();
3722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SafepointGenerator generator(
3723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        this, pointers, Safepoint::kLazyDeopt);
3724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ParameterCount count(arity);
3725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ParameterCount expected(formal_parameter_count);
3726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator);
3727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3731b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.orgvoid LCodeGen::DoTailCallThroughMegamorphicCache(
3732b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org    LTailCallThroughMegamorphicCache* instr) {
3733b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Register receiver = ToRegister(instr->receiver());
3734b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Register name = ToRegister(instr->name());
3735b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
3736b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK(name.is(LoadDescriptor::NameRegister()));
3737b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
3738b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Register scratch = ebx;
3739b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Register extra = eax;
3740b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK(!scratch.is(receiver) && !scratch.is(name));
3741b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  DCHECK(!extra.is(receiver) && !extra.is(name));
3742b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
3743b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Important for the tail-call.
3744b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  bool must_teardown_frame = NeedsEagerFrame();
3745b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
3746b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // The probe will tail call to a handler if found.
3747b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
3748b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                         must_teardown_frame, receiver, name,
3749b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org                                         scratch, extra);
3750b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
3751b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  // Tail call to miss if we ended up here.
3752b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  if (must_teardown_frame) __ leave();
3753b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  LoadIC::GenerateMiss(masm());
3754b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org}
3755b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
3756b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org
3757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
3758e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
3759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LPointerMap* pointers = instr->pointer_map();
3761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->target()->IsConstantOperand()) {
3764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LConstantOperand* target = LConstantOperand::cast(instr->target());
3765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
3767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ call(code, RelocInfo::CODE_TARGET);
3768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3769e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->target()->IsRegister());
3770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register target = ToRegister(instr->target());
3771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    generator.BeforeCall(__ CallSize(Operand(target)));
3772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
3773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ call(target);
3774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  generator.AfterCall();
3776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
3780e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->function()).is(edi));
3781e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
3782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->pass_argument_count()) {
3784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(eax, instr->arity());
3785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Change context.
3788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
3789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool is_self_call = false;
3791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->function()->IsConstant()) {
3792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    HConstant* fun_const = HConstant::cast(instr->hydrogen()->function());
3793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<JSFunction> jsfun =
3794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Handle<JSFunction>::cast(fun_const->handle(isolate()));
3795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    is_self_call = jsfun.is_identical_to(info()->closure());
3796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (is_self_call) {
3799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallSelf();
3800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
3801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
3802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input_reg = ToRegister(instr->value());
3810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         factory()->heap_number_map());
3812b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(not_equal, instr, "not a heap number");
3813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label slow, allocated, done;
3815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register tmp = input_reg.is(eax) ? ecx : eax;
3816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
3817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Preserve the value of all registers.
3819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushSafepointRegistersScope scope(this);
3820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check the sign of the argument. If the argument is positive, just
3823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // return it. We do not need to patch the stack since |input| and
3824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // |result| are the same register and |input| will be restored
3825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // unchanged by popping safepoint registers.
3826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(tmp, Immediate(HeapNumber::kSignMask));
3827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(zero, &done, Label::kNear);
3828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
3830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&allocated, Label::kNear);
3831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Slow case: Call the runtime system to do the number allocation.
3833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&slow);
383447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
3835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                          instr, instr->context());
3836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Set the pointer to the new heap number in tmp.
3837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!tmp.is(eax)) __ mov(tmp, eax);
3838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Restore input_reg after call to runtime.
3839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
3840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&allocated);
3842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(tmp2, ~HeapNumber::kSignMask);
3844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
3845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
3846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
3847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ StoreToSafepointRegisterSlot(input_reg, tmp);
3848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
3850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input_reg = ToRegister(instr->value());
3855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(input_reg, Operand(input_reg));
3856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label is_positive;
3857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_sign, &is_positive, Label::kNear);
3858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ neg(input_reg);  // Sets flags.
3859b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(negative, instr, "overflow");
3860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&is_positive);
3861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathAbs(LMathAbs* instr) {
3865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Class for deferred case.
3866ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
3868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    LMathAbs* instr,
3870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    const X87Stack& x87_stack)
3871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
3872ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
3873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
3875ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
3876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
3877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LMathAbs* instr_;
3878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
3879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3880e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->value()->Equals(instr->result()));
3881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Representation r = instr->hydrogen()->value()->representation();
3882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (r.IsDouble()) {
388406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Register value = ToX87Register(instr->value());
388506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Fxch(value);
388606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fabs();
3887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (r.IsSmiOrInteger32()) {
3888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitIntegerMathAbs(instr);
3889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {  // Tagged case.
3890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredMathAbsTaggedHeapNumber* deferred =
3891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_);
3892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register input_reg = ToRegister(instr->value());
3893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Smi check.
3894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfNotSmi(input_reg, deferred->entry());
3895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitIntegerMathAbs(instr);
3896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(deferred->exit());
3897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
3898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathFloor(LMathFloor* instr) {
390206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register output_reg = ToRegister(instr->result());
390306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register input_reg = ToX87Register(instr->value());
390406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fxch(input_reg);
390506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
390606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Label not_minus_zero, done;
390706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Deoptimize on unordered.
390806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fldz();
390906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld(1);
391006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ FCmp();
3911b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(parity_even, instr, "NaN");
391206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(below, &not_minus_zero, Label::kNear);
391306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
391406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
391506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Check for negative zero.
391606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ j(not_equal, &not_minus_zero, Label::kNear);
391706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // +- 0.0.
391806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(0);
391906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ FXamSign();
3920b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_zero, instr, "minus zero");
392106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ Move(output_reg, Immediate(0));
392206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ jmp(&done, Label::kFar);
392306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
392406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
392506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Positive input.
392606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // rc=01B, round down.
392706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&not_minus_zero);
392806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fnclex();
392906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87SetRC(0x0400);
393006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ sub(esp, Immediate(kPointerSize));
393106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fist_s(Operand(esp, 0));
393206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ pop(output_reg);
393306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87CheckIA();
3934b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(equal, instr, "overflow");
393506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fnclex();
393606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87SetRC(0x0000);
393706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&done);
3938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
3939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
3941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathRound(LMathRound* instr) {
394206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register input_reg = ToX87Register(instr->value());
394306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register result = ToRegister(instr->result());
394406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fxch(input_reg);
394506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Label below_one_half, below_minus_one_half, done;
394606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
394706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  ExternalReference one_half = ExternalReference::address_of_one_half();
394806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  ExternalReference minus_one_half =
394906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      ExternalReference::address_of_minus_one_half();
395006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
395106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld_d(Operand::StaticVariable(one_half));
395206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld(1);
395306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ FCmp();
395406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(carry, &below_one_half);
395506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
395606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Use rounds towards zero, since 0.5 <= x, we use floor(0.5 + x)
395706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld(0);
395806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fadd_d(Operand::StaticVariable(one_half));
395906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // rc=11B, round toward zero.
396006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87SetRC(0x0c00);
396106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ sub(esp, Immediate(kPointerSize));
396206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Clear exception bits.
396306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fnclex();
396406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fistp_s(MemOperand(esp, 0));
396506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Check overflow.
396606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87CheckIA();
396706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ pop(result);
396806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  DeoptimizeIf(equal, instr, "conversion overflow");
396906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fnclex();
397006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Restore round mode.
397106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87SetRC(0x0000);
397206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ jmp(&done);
397306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
397406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&below_one_half);
397506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld_d(Operand::StaticVariable(minus_one_half));
397606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld(1);
397706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ FCmp();
397806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(carry, &below_minus_one_half);
397906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
398006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // we can ignore the difference between a result of -0 and +0.
398106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
398206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // If the sign is positive, we return +0.
398306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld(0);
398406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ FXamSign();
398506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    DeoptimizeIf(not_zero, instr, "minus zero");
398606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
398706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ Move(result, Immediate(0));
398806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ jmp(&done);
398906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
399006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&below_minus_one_half);
399106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld(0);
399206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fadd_d(Operand::StaticVariable(one_half));
399306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // rc=01B, round down.
399406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87SetRC(0x0400);
399506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ sub(esp, Immediate(kPointerSize));
399606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Clear exception bits.
399706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fnclex();
399806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fistp_s(MemOperand(esp, 0));
399906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Check overflow.
400006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87CheckIA();
400106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ pop(result);
400206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  DeoptimizeIf(equal, instr, "conversion overflow");
400306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fnclex();
400406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Restore round mode.
400506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ X87SetRC(0x0000);
400606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
400706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&done);
4008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4011f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.orgvoid LCodeGen::DoMathFround(LMathFround* instr) {
401206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register input_reg = ToX87Register(instr->value());
401306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fxch(input_reg);
401406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ sub(esp, Immediate(kPointerSize));
401506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fstp_s(MemOperand(esp, 0));
401606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fld(MemOperand(esp, 0), kX87FloatOperand);
401706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ add(esp, Immediate(kPointerSize));
4018f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org}
4019f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org
4020f116736e5fdd9974b8a15b5832b7022fe2e96634machenbach@chromium.org
4021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathSqrt(LMathSqrt* instr) {
402234ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  X87Register input = ToX87Register(instr->value());
402334ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  X87Register result_reg = ToX87Register(instr->result());
402434ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  Register temp_result = ToRegister(instr->temp1());
402534ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  Register temp = ToRegister(instr->temp2());
402634ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  Label slow, done, smi, finish;
402734ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  DCHECK(result_reg.is(input));
402834ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com
402934ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  // Store input into Heap number and call runtime function kMathExpRT.
403034ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  if (FLAG_inline_new) {
403134ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ AllocateHeapNumber(temp_result, temp, no_reg, &slow);
403234ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ jmp(&done, Label::kNear);
403334ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  }
403434ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com
403534ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  // Slow case: Call the runtime system to do the number allocation.
403634ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ bind(&slow);
403734ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  {
403834ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    // TODO(3095996): Put a valid pointer value in the stack slot where the
403934ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    // result register is stored, as this register is in the pointer map, but
404034ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    // contains an integer value.
404134ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ Move(temp_result, Immediate(0));
404234ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com
404334ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    // Preserve the value of all registers.
404434ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    PushSafepointRegistersScope scope(this);
404534ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com
404634ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
404734ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
404834ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    RecordSafepointWithRegisters(
404934ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
405034ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ StoreToSafepointRegisterSlot(temp_result, eax);
405134ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  }
405234ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ bind(&done);
405334ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  X87LoadForUsage(input);
405434ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
405534ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com
405634ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  {
405734ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    // Preserve the value of all registers.
405834ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    PushSafepointRegistersScope scope(this);
405934ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com
406034ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
406134ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ push(temp_result);
406234ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ CallRuntimeSaveDoubles(Runtime::kMathSqrtRT);
4063ae4728945755838c8d6450f0a344eb4b583c4dd5weiliang.lin@intel.com    RecordSafepointWithRegisters(instr->pointer_map(), 1,
4064ae4728945755838c8d6450f0a344eb4b583c4dd5weiliang.lin@intel.com                                 Safepoint::kNoLazyDeopt);
406534ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ StoreToSafepointRegisterSlot(temp_result, eax);
406634ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  }
406734ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  X87PrepareToWrite(result_reg);
406834ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  // return value of MathExpRT is Smi or Heap Number.
406934ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ JumpIfSmi(temp_result, &smi);
407034ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  // Heap number(double)
407134ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
407234ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ jmp(&finish);
407334ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  // SMI
407434ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ bind(&smi);
407534ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ SmiUntag(temp_result);
407634ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ push(temp_result);
407734ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ fild_s(MemOperand(esp, 0));
407834ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ pop(temp_result);
407934ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ bind(&finish);
408034ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  X87CommitWrite(result_reg);
4081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
408506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register input_reg = ToX87Register(instr->value());
408606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  DCHECK(ToX87Register(instr->result()).is(input_reg));
408706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fxch(input_reg);
408806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Note that according to ECMA-262 15.8.2.13:
408906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Math.pow(-Infinity, 0.5) == Infinity
409006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Math.sqrt(-Infinity) == NaN
409106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Label done, sqrt;
409206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Check base for -Infinity. C3 == 0, C2 == 1, C1 == 1 and C0 == 1
409306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fxam();
409406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ push(eax);
409506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fnstsw_ax();
409606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ and_(eax, Immediate(0x4700));
409706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ cmp(eax, Immediate(0x0700));
409806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(not_equal, &sqrt, Label::kNear);
409906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // If input is -Infinity, return Infinity.
410006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fchs();
410106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ jmp(&done, Label::kNear);
410206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
410306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Square root.
410406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&sqrt);
410506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fldz();
410606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ faddp();  // Convert -0 to +0.
410706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fsqrt();
410806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&done);
410906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ pop(eax);
4110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoPower(LPower* instr) {
411406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Representation exponent_type = instr->hydrogen()->right()->representation();
411506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register result = ToX87Register(instr->result());
411606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Having marked this as a call, we can use any registers.
411706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register base = ToX87Register(instr->left());
411806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  ExternalReference one_half = ExternalReference::address_of_one_half();
411906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
412006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (exponent_type.IsSmi()) {
412106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Register exponent = ToRegister(instr->right());
412206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87LoadForUsage(base);
412306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ SmiUntag(exponent);
412406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ push(exponent);
412506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fild_s(MemOperand(esp, 0));
412606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ pop(exponent);
412706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  } else if (exponent_type.IsTagged()) {
412806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Register exponent = ToRegister(instr->right());
412906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Register temp = exponent.is(ecx) ? eax : ecx;
413006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Label no_deopt, done;
413106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87LoadForUsage(base);
413206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ JumpIfSmi(exponent, &no_deopt);
413306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp);
4134b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_equal, instr, "not a heap number");
413506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Heap number(double)
413606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset));
413706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ jmp(&done);
413806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // SMI
413906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ bind(&no_deopt);
414006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ SmiUntag(exponent);
414106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ push(exponent);
414206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fild_s(MemOperand(esp, 0));
414306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ pop(exponent);
414406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ bind(&done);
414506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  } else if (exponent_type.IsInteger32()) {
414606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    Register exponent = ToRegister(instr->right());
414706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87LoadForUsage(base);
414806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ push(exponent);
414906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fild_s(MemOperand(esp, 0));
415006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ pop(exponent);
415106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  } else {
415206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    DCHECK(exponent_type.IsDouble());
415306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Register exponent_double = ToX87Register(instr->right());
415406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87LoadForUsage(base, exponent_double);
415506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
415606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
415706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // FP data stack {base, exponent(TOS)}.
415806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Handle (exponent==+-0.5 && base == -0).
415906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Label not_plus_0;
416006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld(0);
416106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fabs();
416206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fld(Operand::StaticVariable(one_half), kX87DoubleOperand);
416306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ FCmp();
416406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(parity_even, &not_plus_0, Label::kNear);  // NaN.
416506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(not_equal, &not_plus_0, Label::kNear);
416606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fldz();
416706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // FP data stack {base, exponent(TOS), zero}.
416806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ faddp(2);
416906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&not_plus_0);
417006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
417106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  {
417206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ PrepareCallCFunction(4, eax);
417306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fstp_d(MemOperand(esp, kDoubleSize));  // Exponent value.
417406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ fstp_d(MemOperand(esp, 0));            // Base value.
417506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87PrepareToWrite(result);
417606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
417706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                     4);
417806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Return value is in st(0) on ia32.
417906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87CommitWrite(result);
418006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
4181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathLog(LMathLog* instr) {
418506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  DCHECK(instr->value()->Equals(instr->result()));
418606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register input_reg = ToX87Register(instr->value());
418706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fxch(input_reg);
418806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
418906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Label positive, done, zero, nan_result;
419006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fldz();
419106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld(1);
419206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ FCmp();
419306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(below, &nan_result, Label::kNear);
419406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(equal, &zero, Label::kNear);
419506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Positive input.
419606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // {input, ln2}.
419706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fldln2();
419806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // {ln2, input}.
419906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fxch();
420006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // {result}.
420106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fyl2x();
420206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ jmp(&done, Label::kNear);
420306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
420406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&nan_result);
420506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  ExternalReference nan =
420606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      ExternalReference::address_of_canonical_non_hole_nan();
420706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87PrepareToWrite(input_reg);
420806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld_d(Operand::StaticVariable(nan));
420906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87CommitWrite(input_reg);
421006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ jmp(&done, Label::kNear);
421106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
421206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&zero);
421306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  ExternalReference ninf = ExternalReference::address_of_negative_infinity();
421406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87PrepareToWrite(input_reg);
421506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld_d(Operand::StaticVariable(ninf));
421606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87CommitWrite(input_reg);
421706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
421806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&done);
4219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathClz32(LMathClz32* instr) {
422306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register input = ToRegister(instr->value());
422406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register result = ToRegister(instr->result());
422506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Label not_zero_input;
422606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bsr(result, input);
422706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
422806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ j(not_zero, &not_zero_input);
422906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ Move(result, Immediate(63));  // 63^31 == 32
423006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
423106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&not_zero_input);
423206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ xor_(result, Immediate(31));  // for x in [0..31], 31^x == 31-x.
4233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoMathExp(LMathExp* instr) {
423706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register input = ToX87Register(instr->value());
423806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register result_reg = ToX87Register(instr->result());
423906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register temp_result = ToRegister(instr->temp1());
424006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register temp = ToRegister(instr->temp2());
424106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Label slow, done, smi, finish;
424206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  DCHECK(result_reg.is(input));
424306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
424406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Store input into Heap number and call runtime function kMathExpRT.
424506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (FLAG_inline_new) {
424606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ AllocateHeapNumber(temp_result, temp, no_reg, &slow);
424706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ jmp(&done, Label::kNear);
424806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
424906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
425006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Slow case: Call the runtime system to do the number allocation.
425106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&slow);
425206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  {
425306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // TODO(3095996): Put a valid pointer value in the stack slot where the
425406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // result register is stored, as this register is in the pointer map, but
425506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // contains an integer value.
425606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ Move(temp_result, Immediate(0));
425706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
425806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Preserve the value of all registers.
425906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    PushSafepointRegistersScope scope(this);
426006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
426106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
426206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
426306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    RecordSafepointWithRegisters(instr->pointer_map(), 0,
426406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                 Safepoint::kNoLazyDeopt);
426506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ StoreToSafepointRegisterSlot(temp_result, eax);
426606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
426706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&done);
426806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87LoadForUsage(input);
426906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
427006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
427106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  {
427206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    // Preserve the value of all registers.
427306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    PushSafepointRegistersScope scope(this);
427406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org
427506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
427606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ push(temp_result);
427706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ CallRuntimeSaveDoubles(Runtime::kMathExpRT);
4278ae4728945755838c8d6450f0a344eb4b583c4dd5weiliang.lin@intel.com    RecordSafepointWithRegisters(instr->pointer_map(), 1,
427906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                                 Safepoint::kNoLazyDeopt);
428006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ StoreToSafepointRegisterSlot(temp_result, eax);
428106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
428206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87PrepareToWrite(result_reg);
428306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // return value of MathExpRT is Smi or Heap Number.
428406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ JumpIfSmi(temp_result, &smi);
428506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Heap number(double)
428606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
428706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ jmp(&finish);
428806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // SMI
428906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&smi);
429006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ SmiUntag(temp_result);
429106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ push(temp_result);
429206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fild_s(MemOperand(esp, 0));
429306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ pop(temp_result);
429406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ bind(&finish);
429506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87CommitWrite(result_reg);
4296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
4300e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
4301e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->function()).is(edi));
4302e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->HasPointerMap());
4303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<JSFunction> known_function = instr->hydrogen()->known_function();
4305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (known_function.is_null()) {
4306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LPointerMap* pointers = instr->pointer_map();
4307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SafepointGenerator generator(
4308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        this, pointers, Safepoint::kLazyDeopt);
4309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ParameterCount count(instr->arity());
4310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ InvokeFunction(edi, count, CALL_FUNCTION, generator);
4311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallKnownFunction(known_function,
4313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      instr->hydrogen()->formal_parameter_count(),
4314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      instr->arity(),
4315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      instr,
4316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      EDI_CONTAINS_TARGET);
4317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCallFunction(LCallFunction* instr) {
4322e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
4323e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->function()).is(edi));
4324e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
4325864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int arity = instr->arity();
4327864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags());
4328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCallNew(LCallNew* instr) {
4333e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
4334e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->constructor()).is(edi));
4335e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
4336864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // No cell in ebx for construct type feedback in optimized code
4338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, isolate()->factory()->undefined_value());
4339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
4340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(eax, Immediate(instr->arity()));
4341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4343864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4345864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4346e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
4347e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->constructor()).is(edi));
4348e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->result()).is(eax));
4349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(eax, Immediate(instr->arity()));
4351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, isolate()->factory()->undefined_value());
4352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ElementsKind kind = instr->hydrogen()->elements_kind();
4353864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AllocationSiteOverrideMode override_mode =
4354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
4355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          ? DISABLE_ALLOCATION_SITES
4356864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          : DONT_OVERRIDE;
4357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4358864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->arity() == 0) {
4359864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
4360864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4361864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (instr->arity() == 1) {
4362864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done;
4363864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (IsFastPackedElementsKind(kind)) {
4364864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label packed_case;
4365864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // We might need a change here
4366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // look at the first argument
4367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(ecx, Operand(esp, 0));
4368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(ecx, ecx);
4369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(zero, &packed_case, Label::kNear);
4370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ElementsKind holey_kind = GetHoleyElementsKind(kind);
4372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ArraySingleArgumentConstructorStub stub(isolate(),
4373864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              holey_kind,
4374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                              override_mode);
4375864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&done, Label::kNear);
4377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&packed_case);
4378864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
4381864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
4383864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4384864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
4385864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4386864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4387864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4388864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4389864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4390864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCallRuntime(LCallRuntime* instr) {
4391e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
439206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
4393864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
4397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register function = ToRegister(instr->function());
4398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register code_object = ToRegister(instr->code_object());
4399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
4400864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
4401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
4405864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
4406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register base = ToRegister(instr->base_object());
4407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->offset()->IsConstantOperand()) {
4408864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LConstantOperand* offset = LConstantOperand::cast(instr->offset());
4409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ lea(result, Operand(base, ToInteger32(offset)));
4410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register offset = ToRegister(instr->offset());
4412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ lea(result, Operand(base, offset, times_1, 0));
4413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
4418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Representation representation = instr->hydrogen()->field_representation();
4419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HObjectAccess access = instr->hydrogen()->access();
4421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int offset = access.offset();
4422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (access.IsExternalMemory()) {
4424e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    MemOperand operand = instr->object()->IsConstantOperand()
4426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ? MemOperand::StaticVariable(
4427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            ToExternalReference(LConstantOperand::cast(instr->object())))
4428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : MemOperand(ToRegister(instr->object()), offset);
4429864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->value()->IsConstantOperand()) {
4430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4431864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(operand, Immediate(ToInteger32(operand_value)));
4432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
4433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Register value = ToRegister(instr->value());
4434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Store(value, operand, representation);
4435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4436864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
4437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ToRegister(instr->object());
4440e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  __ AssertNotSmi(object);
4441e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!representation.IsSmi() ||
4442e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org         !instr->value()->IsConstantOperand() ||
4443e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org         IsSmi(LConstantOperand::cast(instr->value())));
4444e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org  if (representation.IsDouble()) {
4445e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(access.IsInobject());
4446e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->has_transition());
4447e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Register value = ToX87Register(instr->value());
4449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Mov(FieldOperand(object, offset), value);
4450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
4451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4452864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->has_transition()) {
4454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Map> transition = instr->hydrogen()->transition_map();
4455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    AddDeprecationDependency(transition);
445638de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org    __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
445738de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org    if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
4458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Register temp = ToRegister(instr->temp());
4459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Register temp_map = ToRegister(instr->temp_map());
4460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(temp_map, transition);
4461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map);
4462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Update the write barrier for the map field.
446306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ RecordWriteForMap(object, transition, temp_map, temp, kSaveFPRegs);
4464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Do the store.
4468864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register write_register = object;
4469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!access.IsInobject()) {
4470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    write_register = ToRegister(instr->temp());
4471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
4472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  MemOperand operand = FieldOperand(write_register, offset);
4475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->value()->IsConstantOperand()) {
4476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4477864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (operand_value->IsRegister()) {
4478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Register value = ToRegister(operand_value);
4479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Store(value, operand, representation);
4480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else if (representation.IsInteger32()) {
4481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate immediate = ToImmediate(operand_value, representation);
4482e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4483864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(operand, immediate);
4484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
4485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Handle<Object> handle_value = ToHandle(operand_value);
4486e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(operand, handle_value);
4488864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register value = ToRegister(instr->value());
4491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Store(value, operand, representation);
4492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->NeedsWriteBarrier()) {
4495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register value = ToRegister(instr->value());
4496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
4497864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Update the write barrier for the object for in-object properties.
449806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ RecordWriteField(write_register, offset, value, temp, kSaveFPRegs,
4499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                        EMIT_REMEMBERED_SET,
450038de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                        instr->hydrogen()->SmiCheckForWriteBarrier(),
450138de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                        instr->hydrogen()->PointersToHereCheckForValue());
4502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4507e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
450842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
450942ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
451142ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  __ mov(StoreDescriptor::NameRegister(), instr->name());
4512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
4513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(ic, RelocInfo::CODE_TARGET, instr);
4514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4517864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
4518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition cc = instr->hydrogen()->allow_equality() ? above : above_equal;
4519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->index()->IsConstantOperand()) {
4520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(ToOperand(instr->length()),
4521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           ToImmediate(LConstantOperand::cast(instr->index()),
4522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       instr->hydrogen()->length()->representation()));
452338de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org    cc = CommuteCondition(cc);
4524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (instr->length()->IsConstantOperand()) {
4525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(ToOperand(instr->index()),
4526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           ToImmediate(LConstantOperand::cast(instr->length()),
4527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       instr->hydrogen()->index()->representation()));
4528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
4530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done;
4533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(NegateCondition(cc), &done, Label::kNear);
4534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ int3();
4535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
4536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4537b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(cc, instr, "out of bounds");
4538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4539864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ElementsKind elements_kind = instr->elements_kind();
4544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* key = instr->key();
4545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!key->IsConstantOperand() &&
4546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
4547864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                  elements_kind)) {
4548864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(ToRegister(key));
4549864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4550864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand operand(BuildFastArrayOperand(
4551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->elements(),
4552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      key,
4553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->hydrogen()->key()->representation(),
4554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      elements_kind,
4555864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->base_offset()));
4556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
4557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      elements_kind == FLOAT32_ELEMENTS) {
455806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    X87Mov(operand, ToX87Register(instr->value()), kX87FloatOperand);
4559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
4560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             elements_kind == FLOAT64_ELEMENTS) {
4561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Mov(operand, ToX87Register(instr->value()));
4562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register value = ToRegister(instr->value());
4564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    switch (elements_kind) {
4565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
4566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_UINT8_ELEMENTS:
4567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_INT8_ELEMENTS:
4568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case UINT8_ELEMENTS:
4569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case INT8_ELEMENTS:
4570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case UINT8_CLAMPED_ELEMENTS:
4571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov_b(operand, value);
4572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
4573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_INT16_ELEMENTS:
4574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_UINT16_ELEMENTS:
4575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case UINT16_ELEMENTS:
4576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case INT16_ELEMENTS:
4577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov_w(operand, value);
4578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
4579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_INT32_ELEMENTS:
4580864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_UINT32_ELEMENTS:
4581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case UINT32_ELEMENTS:
4582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case INT32_ELEMENTS:
4583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ mov(operand, value);
4584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
4585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_FLOAT32_ELEMENTS:
4586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case EXTERNAL_FLOAT64_ELEMENTS:
4587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FLOAT32_ELEMENTS:
4588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FLOAT64_ELEMENTS:
4589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_SMI_ELEMENTS:
4590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_ELEMENTS:
4591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_DOUBLE_ELEMENTS:
4592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_HOLEY_SMI_ELEMENTS:
4593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_HOLEY_ELEMENTS:
4594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case FAST_HOLEY_DOUBLE_ELEMENTS:
4595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case DICTIONARY_ELEMENTS:
4596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      case SLOPPY_ARGUMENTS_ELEMENTS:
4597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        UNREACHABLE();
4598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        break;
4599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ExternalReference canonical_nan_reference =
4606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference::address_of_canonical_non_hole_nan();
4607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand double_store_operand = BuildFastArrayOperand(
4608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->elements(),
4609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->key(),
4610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->hydrogen()->key()->representation(),
4611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FAST_DOUBLE_ELEMENTS,
4612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->base_offset());
4613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Can't use SSE2 in the serializer
4615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->IsConstantHoleStore()) {
4616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // This means we should store the (double) hole. No floating point
4617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // registers required.
4618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    double nan_double = FixedDoubleArray::hole_nan_as_double();
4619e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    uint64_t int_val = bit_cast<uint64_t, double>(nan_double);
4620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int32_t lower = static_cast<int32_t>(int_val);
4621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
4622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(double_store_operand, Immediate(lower));
4624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand double_store_operand2 = BuildFastArrayOperand(
4625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->elements(),
4626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->key(),
4627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->hydrogen()->key()->representation(),
4628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        FAST_DOUBLE_ELEMENTS,
4629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->base_offset() + kPointerSize);
4630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(double_store_operand2, Immediate(upper));
4631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label no_special_nan_handling;
4633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Register value = ToX87Register(instr->value());
4634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Fxch(value);
4635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->NeedsCanonicalization()) {
4637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fld(0);
4638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fld(0);
4639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ FCmp();
4640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(parity_odd, &no_special_nan_handling, Label::kNear);
4642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ sub(esp, Immediate(kDoubleSize));
4643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fst_d(MemOperand(esp, 0));
4644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
4645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             Immediate(kHoleNanUpper32));
4646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ add(esp, Immediate(kDoubleSize));
4647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label canonicalize;
4648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_equal, &canonicalize, Label::kNear);
4649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&no_special_nan_handling, Label::kNear);
4650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&canonicalize);
4651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fstp(0);
4652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fld_d(Operand::StaticVariable(canonical_nan_reference));
4653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&no_special_nan_handling);
4656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ fst_d(double_store_operand);
4657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register elements = ToRegister(instr->elements());
4663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
4664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Operand operand = BuildFastArrayOperand(
4666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->elements(),
4667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->key(),
4668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->hydrogen()->key()->representation(),
4669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FAST_ELEMENTS,
4670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->base_offset());
4671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->value()->IsRegister()) {
4672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(operand, ToRegister(instr->value()));
4673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (IsSmi(operand_value)) {
4676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Immediate immediate = ToImmediate(operand_value, Representation::Smi());
4677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(operand, immediate);
4678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
4679e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(!IsInteger32(operand_value));
4680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Handle<Object> handle_value = ToHandle(operand_value);
4681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(operand, handle_value);
4682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4684864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4685864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->NeedsWriteBarrier()) {
4686e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->value()->IsRegister());
4687864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register value = ToRegister(instr->value());
4688e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->key()->IsConstantOperand());
4689864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    SmiCheck check_needed =
4690eac65cd57a2d5f018fc440eed1b69d0fe80fe336machenbach@chromium.org        instr->hydrogen()->value()->type().IsHeapObject()
4691864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4692864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Compute address of modified element and store it into key register.
4693864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ lea(key, operand);
469406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ RecordWrite(elements, key, value, kSaveFPRegs, EMIT_REMEMBERED_SET,
469538de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                   check_needed,
469638de99aae2d4efc5796aa6935c1648447ec32fc8machenbach@chromium.org                   instr->hydrogen()->PointersToHereCheckForValue());
4697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4699864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4700864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4701864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4702864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // By cases...external, fast-double, fast
4703864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->is_typed_elements()) {
4704864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DoStoreKeyedExternalArray(instr);
4705864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
4706864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DoStoreKeyedFixedDoubleArray(instr);
4707864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4708864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DoStoreKeyedFixedArray(instr);
4709864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4714e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
471542ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
471642ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
471742ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org  DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4719b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org  Handle<Code> ic =
4720b376fed08cb9d90a3f67f655adf63c4b35feb106machenbach@chromium.org      CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code();
4721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(ic, RelocInfo::CODE_TARGET, instr);
4722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4723864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ToRegister(instr->object());
4727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
4728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label no_memento_found;
4729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4730b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(equal, instr, "memento found");
4731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&no_memento_found);
4732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object_reg = ToRegister(instr->object());
4737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Map> from_map = instr->original_map();
4739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Map> to_map = instr->transitioned_map();
4740864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ElementsKind from_kind = instr->from_kind();
4741864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  ElementsKind to_kind = instr->to_kind();
4742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label not_applicable;
4744864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool is_simple_map_transition =
4745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      IsSimpleMapChangeTransition(from_kind, to_kind);
4746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label::Distance branch_distance =
4747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      is_simple_map_transition ? Label::kNear : Label::kFar;
4748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
4749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &not_applicable, branch_distance);
4750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (is_simple_map_transition) {
4751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register new_map_reg = ToRegister(instr->new_map_temp());
4752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(object_reg, HeapObject::kMapOffset),
4753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           Immediate(to_map));
4754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Write barrier.
4755e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_NE(instr->temp(), NULL);
4756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ RecordWriteForMap(object_reg, to_map, new_map_reg,
475706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org                         ToRegister(instr->temp()), kDontSaveFPRegs);
4758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4759e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(ToRegister(instr->context()).is(esi));
4760e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(object_reg.is(eax));
4761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PushSafepointRegistersScope scope(this);
4762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, to_map);
4763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
4764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
4765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CallStub(&stub);
4766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordSafepointWithLazyDeopt(instr,
4767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&not_applicable);
4770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4774ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredStringCharCodeAt FINAL : public LDeferredCode {
4775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
4776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredStringCharCodeAt(LCodeGen* codegen,
4777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                             LStringCharCodeAt* instr,
4778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                             const X87Stack& x87_stack)
4779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4780ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
4781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredStringCharCodeAt(instr_);
4782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4783ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
4784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
4785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LStringCharCodeAt* instr_;
4786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
4787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredStringCharCodeAt* deferred =
4789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_);
4790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  StringCharLoadGenerator::Generate(masm(),
4792864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    factory(),
4793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    ToRegister(instr->string()),
4794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    ToRegister(instr->index()),
4795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    ToRegister(instr->result()),
4796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                    deferred->entry());
4797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->exit());
4798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
4802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register string = ToRegister(instr->string());
4803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
4804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(3095996): Get rid of this. For now, we need to make the
4806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // result register contain a valid pointer because it is already
4807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // contained in the register pointer map.
4808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, Immediate(0));
4809864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4810864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushSafepointRegistersScope scope(this);
4811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(string);
4812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Push the index as a smi. This is safe because of the checks in
4813864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // DoStringCharCodeAt above.
4814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
4815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->index()->IsConstantOperand()) {
4816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()),
4817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      Representation::Smi());
4818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(immediate);
4819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register index = ToRegister(instr->index());
4821864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiTag(index);
4822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(index);
4823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
482447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2,
4825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                          instr, instr->context());
4826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ AssertSmi(eax);
4827864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(eax);
4828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ StoreToSafepointRegisterSlot(result, eax);
4829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4833ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredStringCharFromCode FINAL : public LDeferredCode {
4834864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
4835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredStringCharFromCode(LCodeGen* codegen,
4836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               LStringCharFromCode* instr,
4837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                               const X87Stack& x87_stack)
4838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4839ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
4840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredStringCharFromCode(instr_);
4841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4842ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
4843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
4844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LStringCharFromCode* instr_;
4845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
4846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredStringCharFromCode* deferred =
4848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_);
4849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4850e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
4851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register char_code = ToRegister(instr->char_code());
4852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
4853e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!char_code.is(result));
4854864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(char_code, String::kMaxOneByteCharCode);
4856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(above, deferred->entry());
4857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, Immediate(factory()->single_character_string_cache()));
4858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, FieldOperand(result,
4859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              char_code, times_pointer_size,
4860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              FixedArray::kHeaderSize));
4861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(result, factory()->undefined_value());
4862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, deferred->entry());
4863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->exit());
4864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4866864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register char_code = ToRegister(instr->char_code());
4869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
4870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(3095996): Get rid of this. For now, we need to make the
4872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // result register contain a valid pointer because it is already
4873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // contained in the register pointer map.
4874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, Immediate(0));
4875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushSafepointRegistersScope scope(this);
4877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiTag(char_code);
4878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(char_code);
4879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
4880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ StoreToSafepointRegisterSlot(result, eax);
4881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStringAdd(LStringAdd* instr) {
4885e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
4886e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->left()).is(edx));
4887e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->right()).is(eax));
4888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  StringAddStub stub(isolate(),
4889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     instr->hydrogen()->flags(),
4890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     instr->hydrogen()->pretenure_flag());
4891864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4892864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
4897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* output = instr->result();
4898e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsRegister() || input->IsStackSlot());
4899e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(output->IsDoubleRegister());
4900864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (input->IsRegister()) {
4901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register input_reg = ToRegister(input);
4902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(input_reg);
4903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand);
4904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(input_reg);
4905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4906864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
4907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
4908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
4913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* output = instr->result();
4914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register res = ToX87Register(output);
4915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87PrepareToWrite(res);
4916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadUint32NoSSE2(ToRegister(input));
4917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87CommitWrite(res);
4918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4922ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredNumberTagI FINAL : public LDeferredCode {
4923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
4924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredNumberTagI(LCodeGen* codegen,
4925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       LNumberTagI* instr,
4926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       const X87Stack& x87_stack)
4927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4928ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
4929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       SIGNED_INT32);
4931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4932ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
4933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
4934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LNumberTagI* instr_;
4935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
4936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
4938e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsRegister() && input->Equals(instr->result()));
4939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(input);
4940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredNumberTagI* deferred =
4942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      new(zone()) DeferredNumberTagI(this, instr, x87_stack_);
4943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiTag(reg);
4944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(overflow, deferred->entry());
4945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->exit());
4946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4950ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredNumberTagU FINAL : public LDeferredCode {
4951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
4952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredNumberTagU(LCodeGen* codegen,
4953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       LNumberTagU* instr,
4954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       const X87Stack& x87_stack)
4955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4956ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
4957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                       UNSIGNED_INT32);
4959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
4960ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
4961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
4962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LNumberTagU* instr_;
4963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
4964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
4966e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsRegister() && input->Equals(instr->result()));
4967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(input);
4968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredNumberTagU* deferred =
4970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      new(zone()) DeferredNumberTagU(this, instr, x87_stack_);
4971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(reg, Immediate(Smi::kMaxValue));
4972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(above, deferred->entry());
4973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiTag(reg);
4974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->exit());
4975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
4976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     LOperand* value,
4980864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     LOperand* temp,
4981864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                     IntegerSignedness signedness) {
4982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label done, slow;
4983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(value);
4984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register tmp = ToRegister(temp);
4985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
4986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (signedness == SIGNED_INT32) {
4987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // There was overflow, so bits 30 and 31 of the original integer
4988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // disagree. Try to allocate a heap number in new space and store
4989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // the value in there. If that fails, call the runtime system.
4990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(reg);
4991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ xor_(reg, 0x80000000);
4992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(reg);
4993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ fild_s(Operand(esp, 0));
4994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(reg);
4995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
4996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // There's no fild variant for unsigned values, so zero-extend to a 64-bit
4997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // int manually.
4998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(0));
4999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(reg);
5000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ fild_d(Operand(esp, 0));
5001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(reg);
5002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ pop(reg);
5003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_inline_new) {
5006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
5007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&done, Label::kNear);
5008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Slow case: Call the runtime system to do the number allocation.
5011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&slow);
5012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  {
5013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // TODO(3095996): Put a valid pointer value in the stack slot where the
5014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // result register is stored, as this register is in the pointer map, but
5015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // contains an integer value.
5016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Move(reg, Immediate(0));
5017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Preserve the value of all registers.
5019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PushSafepointRegistersScope scope(this);
5020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // NumberTagI and NumberTagD use the context from the frame, rather than
5022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // the environment's HContext or HInlinedContext value.
502347390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    // They only call Runtime::kAllocateHeapNumber.
5024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The corresponding HChange instructions are added in a phase that does
5025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // not have easy access to the local context.
5026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
502706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
5028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordSafepointWithRegisters(
5029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ StoreToSafepointRegisterSlot(reg, eax);
5031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
5034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
5035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoNumberTagD(LNumberTagD* instr) {
5039ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredNumberTagD FINAL : public LDeferredCode {
5040864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
5041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredNumberTagD(LCodeGen* codegen,
5042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       LNumberTagD* instr,
5043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       const X87Stack& x87_stack)
5044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5045ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
5046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredNumberTagD(instr_);
5047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5048ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
5049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
5050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LNumberTagD* instr_;
5051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
5052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(instr->result());
5054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put the value to the top of stack
5056864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register src = ToX87Register(instr->value());
505706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Don't use X87LoadForUsage here, which is only used by Instruction which
505806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // clobbers fp registers.
505906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  x87_stack_.Fxch(src);
5060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredNumberTagD* deferred =
5062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      new(zone()) DeferredNumberTagD(this, instr, x87_stack_);
5063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (FLAG_inline_new) {
5064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register tmp = ToRegister(instr->temp());
5065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
5066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(deferred->entry());
5068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->exit());
507006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset));
5071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5073864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
5075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(3095996): Get rid of this. For now, we need to make the
5076864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // result register contain a valid pointer because it is already
5077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // contained in the register pointer map.
5078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(instr->result());
5079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(reg, Immediate(0));
5080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushSafepointRegistersScope scope(this);
5082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // NumberTagI and NumberTagD use the context from the frame, rather than
5083864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the environment's HContext or HInlinedContext value.
508447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  // They only call Runtime::kAllocateHeapNumber.
5085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The corresponding HChange instructions are added in a phase that does
5086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // not have easy access to the local context.
5087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
508806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
5089864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepointWithRegisters(
5090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ StoreToSafepointRegisterSlot(reg, eax);
5092864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoSmiTag(LSmiTag* instr) {
5096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HChange* hchange = instr->hydrogen();
5097864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input = ToRegister(instr->value());
5098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hchange->CheckFlag(HValue::kCanOverflow) &&
5099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      hchange->value()->CheckFlag(HValue::kUint32)) {
5100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(input, Immediate(0xc0000000));
5101b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_zero, instr, "overflow");
5102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiTag(input);
5104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (hchange->CheckFlag(HValue::kCanOverflow) &&
5105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      !hchange->value()->CheckFlag(HValue::kUint32)) {
5106b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(overflow, instr, "overflow");
5107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5109864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5110864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoSmiUntag(LSmiUntag* instr) {
5112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
5113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(input);
5114e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsRegister() && input->Equals(instr->result()));
5115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->needs_check()) {
5116864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(result, Immediate(kSmiTagMask));
5117b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_zero, instr, "not a Smi");
5118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ AssertSmi(result);
5120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(result);
5122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5125a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.orgvoid LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
5126a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org                                      Register temp_reg, X87Register res_reg,
5127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                      NumberUntagDMode mode) {
5128a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  bool can_convert_undefined_to_nan =
5129a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      instr->hydrogen()->can_convert_undefined_to_nan();
5130a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
5131a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
5132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label load_smi, done;
5133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87PrepareToWrite(res_reg);
5135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Smi check.
513706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ JumpIfSmi(input_reg, &load_smi);
5138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Heap number map check.
5140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           factory()->heap_number_map());
5142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (!can_convert_undefined_to_nan) {
5143b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(not_equal, instr, "not a heap number");
5144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
5145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      Label heap_number, convert;
514606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      __ j(equal, &heap_number);
5147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Convert undefined (or hole) to NaN.
5149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(input_reg, factory()->undefined_value());
5150b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5151864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&convert);
5153864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ExternalReference nan =
5154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          ExternalReference::address_of_canonical_non_hole_nan();
5155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fld_d(Operand::StaticVariable(nan));
5156864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(&done, Label::kNear);
5157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ bind(&heap_number);
5159864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Heap number to x87 conversion.
5161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (deoptimize_on_minus_zero) {
5163864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fldz();
5164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ FCmp();
5165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(not_zero, &done, Label::kNear);
5167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Use general purpose registers to check if we have -0.0
5169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test(temp_reg, Immediate(HeapNumber::kSignMask));
5171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ j(zero, &done, Label::kNear);
5172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Pop FPU stack before deoptimizing.
5174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ fstp(0);
5175b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(not_zero, instr, "minus zero");
5176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(&done, Label::kNear);
5178864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5179e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
5180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&load_smi);
5183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Clobbering a temp is faster than re-tagging the
5184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // input register since we avoid dependencies.
5185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp_reg, input_reg);
5186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(temp_reg);  // Untag smi before converting to float.
5187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(temp_reg);
5188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ fild_s(Operand(esp, 0));
5189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(esp, Immediate(kPointerSize));
5190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
5191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87CommitWrite(res_reg);
5192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
5196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input_reg = ToRegister(instr->value());
5197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // The input was optimistically untagged; revert it.
5199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(kSmiTagSize == 1);
5200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag));
5201864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->truncating()) {
5203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label no_heap_number, check_bools, check_false;
5204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Heap number map check.
5206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           factory()->heap_number_map());
5208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &no_heap_number, Label::kNear);
5209864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ TruncateHeapNumberToI(input_reg, input_reg);
5210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(done);
5211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&no_heap_number);
5213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check for Oddballs. Undefined/False is converted to zero and True to one
5214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // for truncating conversions.
5215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(input_reg, factory()->undefined_value());
5216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &check_bools, Label::kNear);
5217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Move(input_reg, Immediate(0));
5218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(done);
5219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5220864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&check_bools);
5221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(input_reg, factory()->true_value());
5222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, &check_false, Label::kNear);
5223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Move(input_reg, Immediate(1));
5224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(done);
5225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&check_false);
5227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(input_reg, factory()->false_value());
5228b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
5229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Move(input_reg, Immediate(0));
5230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5231a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    // TODO(olivf) Converting a number on the fpu is actually quite slow. We
5232a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    // should first try a fast conversion and then bailout to this slow case.
5233a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5234a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org           isolate()->factory()->heap_number_map());
523506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    DeoptimizeIf(not_equal, instr, "not a heap number");
5236a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
5237a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    __ sub(esp, Immediate(kPointerSize));
5238a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5239a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
5240a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
5241a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      Label no_precision_lost, not_nan, zero_check;
5242a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fld(0);
5243a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
5244a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fist_s(MemOperand(esp, 0));
5245a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fild_s(MemOperand(esp, 0));
5246a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ FCmp();
5247a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ pop(input_reg);
5248a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
5249a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ j(equal, &no_precision_lost, Label::kNear);
5250a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fstp(0);
525106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      DeoptimizeIf(no_condition, instr, "lost precision");
5252a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ bind(&no_precision_lost);
5253a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
5254a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ j(parity_odd, &not_nan);
5255a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fstp(0);
525606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      DeoptimizeIf(no_condition, instr, "NaN");
5257a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ bind(&not_nan);
5258a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
5259a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ test(input_reg, Operand(input_reg));
5260a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ j(zero, &zero_check, Label::kNear);
5261a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fstp(0);
5262a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ jmp(done);
5263a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org
5264a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ bind(&zero_check);
5265a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      // To check for minus zero, we load the value again as float, and check
5266a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      // if that is still 0.
5267a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ sub(esp, Immediate(kPointerSize));
5268a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fstp_s(Operand(esp, 0));
5269a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ pop(input_reg);
5270a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ test(input_reg, Operand(input_reg));
527106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      DeoptimizeIf(not_zero, instr, "minus zero");
5272a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    } else {
5273a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fist_s(MemOperand(esp, 0));
5274a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ fild_s(MemOperand(esp, 0));
5275a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ FCmp();
5276a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org      __ pop(input_reg);
527706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      DeoptimizeIf(not_equal, instr, "lost precision");
527806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org      DeoptimizeIf(parity_even, instr, "NaN");
5279a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org    }
5280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5284864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5285ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredTaggedToI FINAL : public LDeferredCode {
5286864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
5287864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredTaggedToI(LCodeGen* codegen,
5288864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      LTaggedToI* instr,
5289864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      const X87Stack& x87_stack)
5290864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5291ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
5292864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredTaggedToI(instr_, done());
5293864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5294ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
5295864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
5296864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LTaggedToI* instr_;
5297864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
5298864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
5300e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsRegister());
5301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input_reg = ToRegister(input);
5302e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input_reg.is(ToRegister(instr->result())));
5303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5304864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->value()->representation().IsSmi()) {
5305864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(input_reg);
5306864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5307864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredTaggedToI* deferred =
5308864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        new(zone()) DeferredTaggedToI(this, instr, x87_stack_);
5309864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Optimistically untag the input.
5310864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If the input is a HeapObject, SmiUntag will set the carry flag.
5311864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
5312864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiUntag(input_reg);
5313864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Branch to deferred code if the input was tagged.
5314864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // The deferred code will take care of restoring the tag.
5315864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(carry, deferred->entry());
5316864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(deferred->exit());
5317864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5318864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5319864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5320864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5321864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
5322864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
5323e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsRegister());
5324864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* temp = instr->temp();
5325e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(temp->IsRegister());
5326864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* result = instr->result();
5327e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result->IsDoubleRegister());
5328864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5329864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input_reg = ToRegister(input);
5330864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp_reg = ToRegister(temp);
5331864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5332864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  HValue* value = instr->hydrogen()->value();
5333864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  NumberUntagDMode mode = value->representation().IsSmi()
5334864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5335864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5336a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  EmitNumberUntagDNoSSE2(instr, input_reg, temp_reg, ToX87Register(result),
5337864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                         mode);
5338864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5339864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5340864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5341864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5342864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
5343e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsDoubleRegister());
5344864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* result = instr->result();
5345e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result->IsRegister());
5346864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result_reg = ToRegister(result);
5347864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5348864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->truncating()) {
5349864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Register input_reg = ToX87Register(input);
5350864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Fxch(input_reg);
5351864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ TruncateX87TOSToI(result_reg);
5352864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5353b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    Label lost_precision, is_nan, minus_zero, done;
5354864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Register input_reg = ToX87Register(input);
5355864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    X87Fxch(input_reg);
535634ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
5357864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
535834ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com                 &lost_precision, &is_nan, &minus_zero, dist);
535934ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com    __ jmp(&done);
5360b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    __ bind(&lost_precision);
5361b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(no_condition, instr, "lost precision");
5362b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    __ bind(&is_nan);
5363b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(no_condition, instr, "NaN");
5364b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    __ bind(&minus_zero);
5365b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(no_condition, instr, "minus zero");
5366864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
5367864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5368864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5369864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5370864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5371864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5372864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
5373e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsDoubleRegister());
5374864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* result = instr->result();
5375e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(result->IsRegister());
5376864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result_reg = ToRegister(result);
5377864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5378b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  Label lost_precision, is_nan, minus_zero, done;
5379864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Register input_reg = ToX87Register(input);
5380864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  X87Fxch(input_reg);
538134ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
5382864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
538334ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com               &lost_precision, &is_nan, &minus_zero, dist);
538434ce5fb5d3a71d1683724530e1cfca983c659ae7weiliang.lin@intel.com  __ jmp(&done);
5385b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  __ bind(&lost_precision);
5386b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(no_condition, instr, "lost precision");
5387b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  __ bind(&is_nan);
5388b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(no_condition, instr, "NaN");
5389b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  __ bind(&minus_zero);
5390b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(no_condition, instr, "minus zero");
5391864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
5392864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiTag(result_reg);
5393b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(overflow, instr, "overflow");
5394864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5395864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5396864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5397864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5398864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
5399864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(ToOperand(input), Immediate(kSmiTagMask));
5400b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(not_zero, instr, "not a Smi");
5401864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5402864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5403864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5404864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5405eac65cd57a2d5f018fc440eed1b69d0fe80fe336machenbach@chromium.org  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5406864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LOperand* input = instr->value();
5407864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(ToOperand(input), Immediate(kSmiTagMask));
5408b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(zero, instr, "Smi");
5409864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5410864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5411864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5412864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5413864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5414864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input = ToRegister(instr->value());
5415864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
5416864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5417864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
5418864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5419864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->is_interval_check()) {
5420864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    InstanceType first;
5421864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    InstanceType last;
5422864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    instr->hydrogen()->GetCheckInterval(&first, &last);
5423864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5424864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5425864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org            static_cast<int8_t>(first));
5426864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5427864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // If there is only one type in the interval check for equality.
5428864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (first == last) {
5429b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(not_equal, instr, "wrong instance type");
5430864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
5431b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(below, instr, "wrong instance type");
5432864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // Omit check for the last type.
5433864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      if (last != LAST_TYPE) {
5434864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5435864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                static_cast<int8_t>(last));
5436b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org        DeoptimizeIf(above, instr, "wrong instance type");
5437864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      }
5438864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5439864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5440864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    uint8_t mask;
5441864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    uint8_t tag;
5442864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5443864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
54449aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org    if (base::bits::IsPowerOfTwo32(mask)) {
54459aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org      DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5446864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
5447b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
5448864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
5449864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
5450864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ and_(temp, mask);
5451864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ cmp(temp, tag);
5452b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org      DeoptimizeIf(not_equal, instr, "wrong instance type");
5453864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5454864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5455864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5456864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5457864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5458864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCheckValue(LCheckValue* instr) {
5459864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<HeapObject> object = instr->hydrogen()->object().handle();
5460864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->object_in_new_space()) {
5461864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register reg = ToRegister(instr->value());
5462864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Cell> cell = isolate()->factory()->NewCell(object);
5463864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(reg, Operand::ForCell(cell));
5464864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5465864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Operand operand = ToOperand(instr->value());
5466864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(operand, object);
5467864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5468b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(not_equal, instr, "value mismatch");
5469864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5470864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5471864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5472864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5473864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  {
5474864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    PushSafepointRegistersScope scope(this);
5475864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(object);
5476864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ xor_(esi, esi);
547706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5478864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RecordSafepointWithRegisters(
5479864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5480864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5481864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test(eax, Immediate(kSmiTagMask));
5482864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5483b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(zero, instr, "instance migration failed");
5484864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5485864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5486864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5487864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5488ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredCheckMaps FINAL : public LDeferredCode {
5489864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
5490864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredCheckMaps(LCodeGen* codegen,
5491864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      LCheckMaps* instr,
5492864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      Register object,
5493864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                      const X87Stack& x87_stack)
5494864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) {
5495864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      SetExit(check_maps());
5496864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5497ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
5498864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredInstanceMigration(instr_, object_);
5499864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5500864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label* check_maps() { return &check_maps_; }
5501ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
5502864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
5503864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LCheckMaps* instr_;
5504864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label check_maps_;
5505864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register object_;
5506864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
5507864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5508864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->IsStabilityCheck()) {
5509864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5510864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    for (int i = 0; i < maps->size(); ++i) {
5511864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      AddStabilityDependency(maps->at(i).handle());
5512864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5513864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    return;
5514864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5515864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5516864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
5517e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(input->IsRegister());
5518864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register reg = ToRegister(input);
5519864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5520864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredCheckMaps* deferred = NULL;
5521864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->HasMigrationTarget()) {
5522864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
5523864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(deferred->check_maps());
5524864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5525864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5526864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5527864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label success;
5528864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < maps->size() - 1; i++) {
5529864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Handle<Map> map = maps->at(i).handle();
5530864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CompareMap(reg, map);
5531864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, &success, Label::kNear);
5532864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5533864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5534864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<Map> map = maps->at(maps->size() - 1).handle();
5535864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CompareMap(reg, map);
5536864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->HasMigrationTarget()) {
5537864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_equal, deferred->entry());
5538864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5539b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org    DeoptimizeIf(not_equal, instr, "wrong map");
5540864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5541864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5542864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&success);
5543864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5544864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5545864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5546864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
554706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register value_reg = ToX87Register(instr->unclamped());
554806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register result_reg = ToRegister(instr->result());
554906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fxch(value_reg);
555006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ ClampTOSToUint8(result_reg);
5551864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5552864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5553864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5554864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5555e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->unclamped()->Equals(instr->result()));
5556864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register value_reg = ToRegister(instr->result());
5557864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ClampUint8(value_reg);
5558864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5559864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5560864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5561864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
5562864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input_reg = ToRegister(instr->unclamped());
5563864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result_reg = ToRegister(instr->result());
5564864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch = ToRegister(instr->scratch());
5565864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch2 = ToRegister(instr->scratch2());
5566864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register scratch3 = ToRegister(instr->scratch3());
5567864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label is_smi, done, heap_number, valid_exponent,
5568864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      largest_value, zero_result, maybe_nan_or_infinity;
5569864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5570864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ JumpIfSmi(input_reg, &is_smi);
5571864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5572864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for heap number
5573864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5574864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         factory()->heap_number_map());
5575864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(equal, &heap_number, Label::kNear);
5576864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5577864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for undefined. Undefined is converted to zero for clamping
5578864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // conversions.
5579864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(input_reg, factory()->undefined_value());
5580b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5581864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&zero_result, Label::kNear);
5582864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5583864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Heap number
5584864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&heap_number);
5585864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5586864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Surprisingly, all of the hand-crafted bit-manipulations below are much
5587864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // faster than the x86 FPU built-in instruction, especially since "banker's
5588864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // rounding" would be additionally very expensive
5589864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5590864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get exponent word.
5591864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5592864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5593864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5594864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Test for negative values --> clamp to zero
5595864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(scratch, scratch);
5596864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(negative, &zero_result, Label::kNear);
5597864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5598864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get exponent alone in scratch2.
5599864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch2, scratch);
5600864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(scratch2, HeapNumber::kExponentMask);
5601864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shr(scratch2, HeapNumber::kExponentShift);
5602864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(zero, &zero_result, Label::kNear);
5603864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
5604864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(negative, &zero_result, Label::kNear);
5605864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5606864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const uint32_t non_int8_exponent = 7;
5607864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(scratch2, Immediate(non_int8_exponent + 1));
5608864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the exponent is too big, check for special values.
5609864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(greater, &maybe_nan_or_infinity, Label::kNear);
5610864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5611864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&valid_exponent);
5612864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
5613864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // < 7. The shift bias is the number of bits to shift the mantissa such that
5614864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // with an exponent of 7 such the that top-most one is in bit 30, allowing
5615864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to
5616864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // 1).
5617864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1;
5618864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ lea(result_reg, MemOperand(scratch2, shift_bias));
5619864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Here result_reg (ecx) is the shift, scratch is the exponent word.  Get the
5620864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // top bits of the mantissa.
5621864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(scratch, HeapNumber::kMantissaMask);
5622864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Put back the implicit 1 of the mantissa
5623864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ or_(scratch, 1 << HeapNumber::kExponentShift);
5624864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Shift up to round
5625864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shl_cl(scratch);
5626864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
5627864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // use the bit in the "ones" place and add it to the "halves" place, which has
5628864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the effect of rounding to even.
5629864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch2, scratch);
5630864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
5631864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  const uint32_t one_bit_shift = one_half_bit_shift + 1;
5632864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
5633864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
5634864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label no_round;
5635864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(less, &no_round, Label::kNear);
5636864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label round_up;
5637864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch2, Immediate(1 << one_half_bit_shift));
5638864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(greater, &round_up, Label::kNear);
5639864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(scratch3, scratch3);
5640864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, &round_up, Label::kNear);
5641864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(scratch2, scratch);
5642864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(scratch2, Immediate(1 << one_bit_shift));
5643864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shr(scratch2, 1);
5644864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&round_up);
5645864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ add(scratch, scratch2);
5646864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(overflow, &largest_value, Label::kNear);
5647864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&no_round);
5648864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ shr(scratch, 23);
5649864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_reg, scratch);
5650864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
5651864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5652864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&maybe_nan_or_infinity);
5653864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for NaN/Infinity, all other values map to 255
5654864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
5655864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &largest_value, Label::kNear);
5656864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5657864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check for NaN, which differs from Infinity in that at least one mantissa
5658864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // bit is set.
5659864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ and_(scratch, HeapNumber::kMantissaMask);
5660864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5661864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, &zero_result, Label::kNear);  // M!=0 --> NaN
5662864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Infinity -> Fall through to map to 255.
5663864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5664864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&largest_value);
5665864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result_reg, Immediate(255));
5666864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
5667864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5668864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&zero_result);
5669864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ xor_(result_reg, result_reg);
5670864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
5671864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5672864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // smi
5673864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&is_smi);
5674864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!input_reg.is(result_reg)) {
5675864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(result_reg, input_reg);
5676864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5677864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ SmiUntag(result_reg);
5678864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ ClampUint8(result_reg);
5679864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
5680864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5681864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5682864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5683864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDoubleBits(LDoubleBits* instr) {
568406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register value_reg = ToX87Register(instr->value());
568506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register result_reg = ToRegister(instr->result());
568606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Fxch(value_reg);
568706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ sub(esp, Immediate(kDoubleSize));
568806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fst_d(Operand(esp, 0));
568906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
569006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ mov(result_reg, Operand(esp, kPointerSize));
569106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  } else {
569206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org    __ mov(result_reg, Operand(esp, 0));
569306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  }
569406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ add(esp, Immediate(kDoubleSize));
5695864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5696864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5697864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5698864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoConstructDouble(LConstructDouble* instr) {
569906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register hi_reg = ToRegister(instr->hi());
570006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  Register lo_reg = ToRegister(instr->lo());
570106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87Register result_reg = ToX87Register(instr->result());
570206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  // Follow below pattern to write a x87 fp register.
570306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87PrepareToWrite(result_reg);
570406b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ sub(esp, Immediate(kDoubleSize));
570506b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ mov(Operand(esp, 0), lo_reg);
570606b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ mov(Operand(esp, kPointerSize), hi_reg);
570706b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ fld_d(Operand(esp, 0));
570806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ add(esp, Immediate(kDoubleSize));
570906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  X87CommitWrite(result_reg);
5710864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5711864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5712864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5713864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoAllocate(LAllocate* instr) {
5714ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredAllocate FINAL : public LDeferredCode {
5715864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
5716864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredAllocate(LCodeGen* codegen,
5717864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     LAllocate* instr,
5718864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                     const X87Stack& x87_stack)
5719864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5720ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
5721864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredAllocate(instr_);
5722864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5723ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
5724864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
5725864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LAllocate* instr_;
5726864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
5727864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5728864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredAllocate* deferred =
5729864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      new(zone()) DeferredAllocate(this, instr, x87_stack_);
5730864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5731864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
5732864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
5733864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5734864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Allocate memory for the object.
5735864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  AllocationFlags flags = TAG_OBJECT;
5736864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5737864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5738864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5739864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
5740e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation());
5741e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5742864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
5743864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
5744e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5745864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
5746864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5747864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5748864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->size()->IsConstantOperand()) {
5749864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5750864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (size <= Page::kMaxRegularHeapObjectSize) {
5751864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
5752864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
5753864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ jmp(deferred->entry());
5754864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5755864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5756864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register size = ToRegister(instr->size());
5757864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
5758864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5759864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5760864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->exit());
5761864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5762864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->MustPrefillWithFiller()) {
5763864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (instr->size()->IsConstantOperand()) {
5764864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5765864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ mov(temp, (size / kPointerSize) - 1);
5766864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
5767864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      temp = ToRegister(instr->size());
5768864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ shr(temp, kPointerSizeLog2);
5769864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ dec(temp);
5770864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5771864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label loop;
5772864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&loop);
5773864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(result, temp, times_pointer_size, 0),
5774864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        isolate()->factory()->one_pointer_filler_map());
5775864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ dec(temp);
5776864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(not_zero, &loop);
5777864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5778864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5779864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5780864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5781864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredAllocate(LAllocate* instr) {
5782864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
5783864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5784864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(3095996): Get rid of this. For now, we need to make the
5785864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // result register contain a valid pointer because it is already
5786864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // contained in the register pointer map.
5787864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Move(result, Immediate(Smi::FromInt(0)));
5788864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5789864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushSafepointRegistersScope scope(this);
5790864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->size()->IsRegister()) {
5791864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register size = ToRegister(instr->size());
5792e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!size.is(result));
5793864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ SmiTag(ToRegister(instr->size()));
5794864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(size);
5795864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5796864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5797864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (size >= 0 && size <= Smi::kMaxValue) {
5798864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ push(Immediate(Smi::FromInt(size)));
5799864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    } else {
5800864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      // We should never get here at runtime => abort
5801864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ int3();
5802864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      return;
5803864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
5804864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5805864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5806864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int flags = AllocateDoubleAlignFlag::encode(
5807864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->hydrogen()->MustAllocateDoubleAligned());
5808864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
5809e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation());
5810e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5811864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE);
5812864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
5813e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5814864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE);
5815864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5816864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    flags = AllocateTargetSpace::update(flags, NEW_SPACE);
5817864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5818864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(flags)));
5819864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5820864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallRuntimeFromDeferred(
582147390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
5822864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ StoreToSafepointRegisterSlot(result, eax);
5823864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5824864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5825864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5826864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoToFastProperties(LToFastProperties* instr) {
5827e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->value()).is(eax));
5828864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);
5829864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallRuntime(Runtime::kToFastProperties, 1, instr);
5830864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5831864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5832864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5833864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
5834e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
5835864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label materialized;
5836864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Registers will be used as follows:
5837864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ecx = literals array.
5838864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // ebx = regexp literal.
5839864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // eax = regexp literal clone.
5840864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // esi = context.
5841864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int literal_offset =
5842864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
5843864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadHeapObject(ecx, instr->hydrogen()->literals());
5844864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, FieldOperand(ecx, literal_offset));
5845864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ebx, factory()->undefined_value());
5846864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &materialized, Label::kNear);
5847864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5848864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Create regexp literal using runtime function
5849864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Result will be in eax.
5850864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ecx);
5851864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
5852864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(instr->hydrogen()->pattern()));
5853864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(instr->hydrogen()->flags()));
585447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
5855864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(ebx, eax);
5856864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5857864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&materialized);
5858864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
5859864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label allocated, runtime_allocate;
5860864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
5861864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&allocated, Label::kNear);
5862864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5863864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&runtime_allocate);
5864864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(ebx);
5865864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(Immediate(Smi::FromInt(size)));
586647390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5867864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ pop(ebx);
5868864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5869864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&allocated);
5870864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Copy the content into the newly allocated memory.
5871864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // (Unroll copy loop once for better throughput).
5872864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
5873864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, FieldOperand(ebx, i));
5874864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
5875864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(eax, i), edx);
5876864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(eax, i + kPointerSize), ecx);
5877864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5878864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if ((size % (2 * kPointerSize)) != 0) {
5879864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(edx, FieldOperand(ebx, size - kPointerSize));
5880864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(FieldOperand(eax, size - kPointerSize), edx);
5881864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5882864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5883864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5884864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5885864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
5886e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
5887864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Use the fast case closure allocation code that allocates in new
5888864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // space for nested functions that don't need literals cloning.
5889864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  bool pretenure = instr->hydrogen()->pretenure();
5890864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!pretenure && instr->hydrogen()->has_no_literals()) {
58912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
58922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                            instr->hydrogen()->kind());
5893864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
5894864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5895864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5896864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(esi);
5897864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(instr->hydrogen()->shared_info()));
5898864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ push(Immediate(pretenure ? factory()->true_value()
5899864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                : factory()->false_value()));
590047390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org    CallRuntime(Runtime::kNewClosure, 3, instr);
5901864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5902864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5903864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5904864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5905864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoTypeof(LTypeof* instr) {
5906e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
5907864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LOperand* input = instr->value();
5908864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitPushTaggedOperand(input);
5909864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallRuntime(Runtime::kTypeof, 1, instr);
5910864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5911864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5912864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5913864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5914864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register input = ToRegister(instr->value());
5915864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition final_branch_condition = EmitTypeofIs(instr, input);
5916864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (final_branch_condition != no_condition) {
5917864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EmitBranch(instr, final_branch_condition);
5918864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5919864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5920864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5921864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5922864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgCondition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
5923864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* true_label = instr->TrueLabel(chunk_);
5924864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label* false_label = instr->FalseLabel(chunk_);
5925864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Handle<String> type_name = instr->type_literal();
5926864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int left_block = instr->TrueDestination(chunk_);
5927864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int right_block = instr->FalseDestination(chunk_);
5928864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  int next_block = GetNextEmittedBlock();
5929864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5930864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label::Distance true_distance = left_block == next_block ? Label::kNear
5931864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                           : Label::kFar;
5932864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label::Distance false_distance = right_block == next_block ? Label::kNear
5933864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                                             : Label::kFar;
5934864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Condition final_branch_condition = no_condition;
5935864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (String::Equals(type_name, factory()->number_string())) {
5936864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, true_label, true_distance);
5937864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(FieldOperand(input, HeapObject::kMapOffset),
5938864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org           factory()->heap_number_map());
5939864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    final_branch_condition = equal;
5940864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5941864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(type_name, factory()->string_string())) {
5942864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, false_label, false_distance);
5943864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
5944864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(above_equal, false_label, false_distance);
5945864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5946864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              1 << Map::kIsUndetectable);
5947864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    final_branch_condition = zero;
5948864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5949864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(type_name, factory()->symbol_string())) {
5950864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, false_label, false_distance);
5951864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(input, SYMBOL_TYPE, input);
5952864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    final_branch_condition = equal;
5953864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5954864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(type_name, factory()->boolean_string())) {
5955864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(input, factory()->true_value());
5956864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, true_label, true_distance);
5957864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(input, factory()->false_value());
5958864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    final_branch_condition = equal;
5959864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5960864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(type_name, factory()->undefined_string())) {
5961864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(input, factory()->undefined_value());
5962864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, true_label, true_distance);
5963864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, false_label, false_distance);
5964864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check for undetectable objects => true.
5965864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
5966864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5967864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              1 << Map::kIsUndetectable);
5968864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    final_branch_condition = not_zero;
5969864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5970864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(type_name, factory()->function_string())) {
5971864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
5972864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, false_label, false_distance);
5973864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
5974864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(equal, true_label, true_distance);
5975864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
5976864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    final_branch_condition = equal;
5977864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5978864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else if (String::Equals(type_name, factory()->object_string())) {
5979864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ JumpIfSmi(input, false_label, false_distance);
59809d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org    __ cmp(input, factory()->null_value());
59819d1a7a8cdb664730cf5703185e85a4716748c564machenbach@chromium.org    __ j(equal, true_label, true_distance);
5982864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
5983864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(below, false_label, false_distance);
5984864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
5985864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(above, false_label, false_distance);
5986864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Check for undetectable objects => false.
5987864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5988864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org              1 << Map::kIsUndetectable);
5989864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    final_branch_condition = zero;
5990864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5991864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
5992864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ jmp(false_label, false_distance);
5993864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
5994864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  return final_branch_condition;
5995864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
5996864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5997864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
5998864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5999864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register temp = ToRegister(instr->temp());
6000864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6001864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitIsConstructCall(temp);
6002864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  EmitBranch(instr, equal);
6003864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6004864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6005864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6006864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EmitIsConstructCall(Register temp) {
6007864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the frame pointer for the calling frame.
6008864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
6009864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6010864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Skip the arguments adaptor frame if it exists.
6011864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label check_frame_marker;
6012864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
6013864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
6014864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &check_frame_marker, Label::kNear);
6015864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));
6016864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6017864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Check the marker in the calling frame.
6018864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&check_frame_marker);
6019864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
6020864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
6021864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6022864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6023864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6024864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
6025864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (!info()->IsStub()) {
6026864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Ensure that we have enough space after the previous lazy-bailout
6027864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // instruction for patching the code here.
6028864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    int current_pc = masm()->pc_offset();
6029864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    if (current_pc < last_lazy_deopt_pc_ + space_needed) {
6030864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
6031864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      __ Nop(padding_size);
6032864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
6033864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
6034864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  last_lazy_deopt_pc_ = masm()->pc_offset();
6035864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6036864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6037864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6038864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLazyBailout(LLazyBailout* instr) {
6039864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  last_lazy_deopt_pc_ = masm()->pc_offset();
6040e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->HasEnvironment());
6041864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LEnvironment* env = instr->environment();
6042864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6043864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6044864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6045864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6046864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6047864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeoptimize(LDeoptimize* instr) {
6048864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Deoptimizer::BailoutType type = instr->hydrogen()->type();
6049864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
6050864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // needed return address), even though the implementation of LAZY and EAGER is
6051864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // now identical. When LAZY is eventually completely folded into EAGER, remove
6052864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // the special case below.
6053864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (info()->IsStub() && type == Deoptimizer::EAGER) {
6054864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    type = Deoptimizer::LAZY;
6055864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
6056a2c0c1516848536a514b3178d2c040b7df0ceb5bmachenbach@chromium.org  DeoptimizeIf(no_condition, instr, instr->hydrogen()->reason(), type);
6057864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6058864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6059864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6060864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDummy(LDummy* instr) {
6061864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Nothing to see here, move on!
6062864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6063864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6064864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6065864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDummyUse(LDummyUse* instr) {
6066864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Nothing to see here, move on!
6067864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6068864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6069864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6070864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
6071864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushSafepointRegistersScope scope(this);
6072864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
607306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
6074864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepointWithLazyDeopt(
6075864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
6076e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->HasEnvironment());
6077864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LEnvironment* env = instr->environment();
6078864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6079864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6080864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6081864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6082864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoStackCheck(LStackCheck* instr) {
6083ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredStackCheck FINAL : public LDeferredCode {
6084864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
6085864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredStackCheck(LCodeGen* codegen,
6086864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       LStackCheck* instr,
6087864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                       const X87Stack& x87_stack)
6088864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
6089ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
6090864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredStackCheck(instr_);
6091864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
6092ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
6093864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
6094864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LStackCheck* instr_;
6095864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
6096864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6097e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(instr->HasEnvironment());
6098864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LEnvironment* env = instr->environment();
6099864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // There is no LLazyBailout instruction for stack-checks. We have to
6100864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // prepare for lazy deoptimization explicitly here.
6101864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  if (instr->hydrogen()->is_function_entry()) {
6102864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Perform stack overflow check.
6103864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Label done;
6104864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ExternalReference stack_limit =
6105864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ExternalReference::address_of_stack_limit(isolate());
6106864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(esp, Operand::StaticVariable(stack_limit));
6107864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(above_equal, &done, Label::kNear);
6108864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6109e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->context()->IsRegister());
6110e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(ToRegister(instr->context()).is(esi));
6111864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    CallCode(isolate()->builtins()->StackCheck(),
6112864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             RelocInfo::CODE_TARGET,
6113864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org             instr);
6114864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(&done);
6115864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  } else {
6116e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(instr->hydrogen()->is_backwards_branch());
6117864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Perform stack overflow check if this goto needs it before jumping.
6118864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredStackCheck* deferred_stack_check =
6119864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        new(zone()) DeferredStackCheck(this, instr, x87_stack_);
6120864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    ExternalReference stack_limit =
6121864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        ExternalReference::address_of_stack_limit(isolate());
6122864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ cmp(esp, Operand::StaticVariable(stack_limit));
6123864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ j(below, deferred_stack_check->entry());
6124864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
6125864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    __ bind(instr->done_label());
6126864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    deferred_stack_check->SetExit(instr->done_label());
6127864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6128864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // Don't record a deoptimization index for the safepoint here.
6129864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // This will be done explicitly when emitting call and the safepoint in
6130864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    // the deferred code.
6131864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  }
6132864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6133864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6134864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6135864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoOsrEntry(LOsrEntry* instr) {
6136864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // This is a pseudo-instruction that ensures that the environment here is
6137864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // properly registered for deoptimization and records the assembler's PC
6138864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // offset.
6139864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  LEnvironment* environment = instr->environment();
6140864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6141864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // If the environment were already registered, we would have no way of
6142864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // backpatching it with the spill slot operands.
6143e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!environment->HasBeenRegistered());
6144864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6145864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6146864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  GenerateOsrPrologue();
6147864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6148864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6149864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6150864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
6151e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ToRegister(instr->context()).is(esi));
6152864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(eax, isolate()->factory()->undefined_value());
6153b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(equal, instr, "undefined");
6154864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6155864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(eax, isolate()->factory()->null_value());
6156b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(equal, instr, "null");
6157864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6158864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(eax, Immediate(kSmiTagMask));
6159b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(zero, instr, "Smi");
6160864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6161864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
6162864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
6163b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(below_equal, instr, "wrong instance type");
6164864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6165864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label use_cache, call_runtime;
6166864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ CheckEnumCache(&call_runtime);
6167864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6168864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
6169864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&use_cache, Label::kNear);
6170864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6171864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Get the set of properties to enumerate.
6172864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&call_runtime);
6173864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(eax);
6174864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
6175864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6176864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
6177864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         isolate()->factory()->meta_map());
6178b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(not_equal, instr, "wrong map");
6179864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&use_cache);
6180864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6181864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6182864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6183864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6184864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register map = ToRegister(instr->map());
6185864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register result = ToRegister(instr->result());
6186864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label load_cache, done;
6187864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ EnumLength(result, map);
6188864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(result, Immediate(Smi::FromInt(0)));
6189864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_equal, &load_cache, Label::kNear);
6190864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result, isolate()->factory()->empty_fixed_array());
6191864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
6192864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6193864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&load_cache);
6194864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ LoadInstanceDescriptors(map, result);
6195864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result,
6196864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(result, DescriptorArray::kEnumCacheOffset));
6197864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(result,
6198864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(result, FixedArray::SizeFor(instr->idx())));
6199864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
6200864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(result, result);
6201b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(equal, instr, "no cache");
6202864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6203864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6204864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6205864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6206864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ToRegister(instr->value());
6207864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(ToRegister(instr->map()),
6208864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org         FieldOperand(object, HeapObject::kMapOffset));
6209b4ef18e93b120b995e067ba72707b62a448eeed6machenbach@chromium.org  DeoptimizeIf(not_equal, instr, "wrong map");
6210864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6211864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6212864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6213864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
6214864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register object,
6215864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                                           Register index) {
6216864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  PushSafepointRegistersScope scope(this);
6217864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(object);
6218864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ push(index);
6219864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ xor_(esi, esi);
622006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org  __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
6221864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  RecordSafepointWithRegisters(
6222864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
6223864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ StoreToSafepointRegisterSlot(object, eax);
6224864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6225864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6226864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6227864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.orgvoid LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6228ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org  class DeferredLoadMutableDouble FINAL : public LDeferredCode {
6229864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   public:
6230864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    DeferredLoadMutableDouble(LCodeGen* codegen,
6231864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              LLoadFieldByIndex* instr,
6232864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register object,
6233864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              Register index,
6234864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              const X87Stack& x87_stack)
6235864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org        : LDeferredCode(codegen, x87_stack),
6236864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          instr_(instr),
6237864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          object_(object),
6238864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org          index_(index) {
6239864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
6240ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual void Generate() OVERRIDE {
6241864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
6242864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    }
6243ada3a6017e603965f87fa34f6e2fa60379e8d697machenbach@chromium.org    virtual LInstruction* instr() OVERRIDE { return instr_; }
6244864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org   private:
6245864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    LLoadFieldByIndex* instr_;
6246864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register object_;
6247864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org    Register index_;
6248864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  };
6249864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6250864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register object = ToRegister(instr->object());
6251864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Register index = ToRegister(instr->index());
6252864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6253864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  DeferredLoadMutableDouble* deferred;
6254864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  deferred = new(zone()) DeferredLoadMutableDouble(
6255864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org      this, instr, object, index, x87_stack_);
6256864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6257864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  Label out_of_object, done;
6258864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ test(index, Immediate(Smi::FromInt(1)));
6259864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(not_zero, deferred->entry());
6260864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6261864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ sar(index, 1);
6262864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6263864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ cmp(index, Immediate(0));
6264864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ j(less, &out_of_object, Label::kNear);
6265864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(object, FieldOperand(object,
6266864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              index,
6267864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              times_half_pointer_size,
6268864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              JSObject::kHeaderSize));
6269864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ jmp(&done, Label::kNear);
6270864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6271864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&out_of_object);
6272864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset));
6273864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ neg(index);
6274864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  // Index is now equal to out of object property index plus 1.
6275864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ mov(object, FieldOperand(object,
6276864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              index,
6277864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              times_half_pointer_size,
6278864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org                              FixedArray::kHeaderSize - kPointerSize));
6279864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(deferred->exit());
6280864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org  __ bind(&done);
6281864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org}
6282864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6283864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6284e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.orgvoid LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
6285e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  Register context = ToRegister(instr->context());
6286e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), context);
6287e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org}
6288e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
6289e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
6290e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.orgvoid LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) {
6291e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  Handle<ScopeInfo> scope_info = instr->scope_info();
6292e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  __ Push(scope_info);
6293e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  __ push(ToRegister(instr->function()));
629447390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org  CallRuntime(Runtime::kPushBlockContext, 2, instr);
6295e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  RecordSafepoint(Safepoint::kNoLazyDeopt);
6296e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org}
6297e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
6298e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org
6299864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#undef __
6300864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6301864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org} }  // namespace v8::internal
6302864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org
6303864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#endif  // V8_TARGET_ARCH_X87
6304