1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/v8.h"
6
7#if V8_TARGET_ARCH_X87
8
9#include "src/base/bits.h"
10#include "src/code-factory.h"
11#include "src/code-stubs.h"
12#include "src/codegen.h"
13#include "src/deoptimizer.h"
14#include "src/hydrogen-osr.h"
15#include "src/ic/ic.h"
16#include "src/ic/stub-cache.h"
17#include "src/x87/lithium-codegen-x87.h"
18
19namespace v8 {
20namespace internal {
21
22
23// When invoking builtins, we need to record the safepoint in the middle of
24// the invoke instruction sequence generated by the macro assembler.
25class SafepointGenerator FINAL : public CallWrapper {
26 public:
27  SafepointGenerator(LCodeGen* codegen,
28                     LPointerMap* pointers,
29                     Safepoint::DeoptMode mode)
30      : codegen_(codegen),
31        pointers_(pointers),
32        deopt_mode_(mode) {}
33  virtual ~SafepointGenerator() {}
34
35  virtual void BeforeCall(int call_size) const OVERRIDE {}
36
37  virtual void AfterCall() const OVERRIDE {
38    codegen_->RecordSafepoint(pointers_, deopt_mode_);
39  }
40
41 private:
42  LCodeGen* codegen_;
43  LPointerMap* pointers_;
44  Safepoint::DeoptMode deopt_mode_;
45};
46
47
48#define __ masm()->
49
50bool LCodeGen::GenerateCode() {
51  LPhase phase("Z_Code generation", chunk());
52  DCHECK(is_unused());
53  status_ = GENERATING;
54
55  // Open a frame scope to indicate that there is a frame on the stack.  The
56  // MANUAL indicates that the scope shouldn't actually generate code to set up
57  // the frame (that is done in GeneratePrologue).
58  FrameScope frame_scope(masm_, StackFrame::MANUAL);
59
60  support_aligned_spilled_doubles_ = info()->IsOptimizing();
61
62  dynamic_frame_alignment_ = info()->IsOptimizing() &&
63      ((chunk()->num_double_slots() > 2 &&
64        !chunk()->graph()->is_recursive()) ||
65       !info()->osr_ast_id().IsNone());
66
67  return GeneratePrologue() &&
68      GenerateBody() &&
69      GenerateDeferredCode() &&
70      GenerateJumpTable() &&
71      GenerateSafepointTable();
72}
73
74
75void LCodeGen::FinishCode(Handle<Code> code) {
76  DCHECK(is_done());
77  code->set_stack_slots(GetStackSlotCount());
78  code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
79  if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code);
80  PopulateDeoptimizationData(code);
81  if (!info()->IsStub()) {
82    Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
83  }
84}
85
86
87#ifdef _MSC_VER
88void LCodeGen::MakeSureStackPagesMapped(int offset) {
89  const int kPageSize = 4 * KB;
90  for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
91    __ mov(Operand(esp, offset), eax);
92  }
93}
94#endif
95
96
97bool LCodeGen::GeneratePrologue() {
98  DCHECK(is_generating());
99
100  if (info()->IsOptimizing()) {
101    ProfileEntryHookStub::MaybeCallEntryHook(masm_);
102
103#ifdef DEBUG
104    if (strlen(FLAG_stop_at) > 0 &&
105        info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
106      __ int3();
107    }
108#endif
109
110    // Sloppy mode functions and builtins need to replace the receiver with the
111    // global proxy when called as functions (without an explicit receiver
112    // object).
113    if (info_->this_has_uses() &&
114        info_->strict_mode() == SLOPPY &&
115        !info_->is_native()) {
116      Label ok;
117      // +1 for return address.
118      int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
119      __ mov(ecx, Operand(esp, receiver_offset));
120
121      __ cmp(ecx, isolate()->factory()->undefined_value());
122      __ j(not_equal, &ok, Label::kNear);
123
124      __ mov(ecx, GlobalObjectOperand());
125      __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));
126
127      __ mov(Operand(esp, receiver_offset), ecx);
128
129      __ bind(&ok);
130    }
131
132    if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
133      // Move state of dynamic frame alignment into edx.
134      __ Move(edx, Immediate(kNoAlignmentPadding));
135
136      Label do_not_pad, align_loop;
137      STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
138      // Align esp + 4 to a multiple of 2 * kPointerSize.
139      __ test(esp, Immediate(kPointerSize));
140      __ j(not_zero, &do_not_pad, Label::kNear);
141      __ push(Immediate(0));
142      __ mov(ebx, esp);
143      __ mov(edx, Immediate(kAlignmentPaddingPushed));
144      // Copy arguments, receiver, and return address.
145      __ mov(ecx, Immediate(scope()->num_parameters() + 2));
146
147      __ bind(&align_loop);
148      __ mov(eax, Operand(ebx, 1 * kPointerSize));
149      __ mov(Operand(ebx, 0), eax);
150      __ add(Operand(ebx), Immediate(kPointerSize));
151      __ dec(ecx);
152      __ j(not_zero, &align_loop, Label::kNear);
153      __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue));
154      __ bind(&do_not_pad);
155    }
156  }
157
158  info()->set_prologue_offset(masm_->pc_offset());
159  if (NeedsEagerFrame()) {
160    DCHECK(!frame_is_built_);
161    frame_is_built_ = true;
162    if (info()->IsStub()) {
163      __ StubPrologue();
164    } else {
165      __ Prologue(info()->IsCodePreAgingActive());
166    }
167    info()->AddNoFrameRange(0, masm_->pc_offset());
168  }
169
170  if (info()->IsOptimizing() &&
171      dynamic_frame_alignment_ &&
172      FLAG_debug_code) {
173    __ test(esp, Immediate(kPointerSize));
174    __ Assert(zero, kFrameIsExpectedToBeAligned);
175  }
176
177  // Reserve space for the stack slots needed by the code.
178  int slots = GetStackSlotCount();
179  DCHECK(slots != 0 || !info()->IsOptimizing());
180  if (slots > 0) {
181    if (slots == 1) {
182      if (dynamic_frame_alignment_) {
183        __ push(edx);
184      } else {
185        __ push(Immediate(kNoAlignmentPadding));
186      }
187    } else {
188      if (FLAG_debug_code) {
189        __ sub(Operand(esp), Immediate(slots * kPointerSize));
190#ifdef _MSC_VER
191        MakeSureStackPagesMapped(slots * kPointerSize);
192#endif
193        __ push(eax);
194        __ mov(Operand(eax), Immediate(slots));
195        Label loop;
196        __ bind(&loop);
197        __ mov(MemOperand(esp, eax, times_4, 0),
198               Immediate(kSlotsZapValue));
199        __ dec(eax);
200        __ j(not_zero, &loop);
201        __ pop(eax);
202      } else {
203        __ sub(Operand(esp), Immediate(slots * kPointerSize));
204#ifdef _MSC_VER
205        MakeSureStackPagesMapped(slots * kPointerSize);
206#endif
207      }
208
209      if (support_aligned_spilled_doubles_) {
210        Comment(";;; Store dynamic frame alignment tag for spilled doubles");
211        // Store dynamic frame alignment state in the first local.
212        int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset;
213        if (dynamic_frame_alignment_) {
214          __ mov(Operand(ebp, offset), edx);
215        } else {
216          __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding));
217        }
218      }
219    }
220  }
221
222  // Possibly allocate a local context.
223  int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
224  if (heap_slots > 0) {
225    Comment(";;; Allocate local context");
226    bool need_write_barrier = true;
227    // Argument to NewContext is the function, which is still in edi.
228    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
229      FastNewContextStub stub(isolate(), heap_slots);
230      __ CallStub(&stub);
231      // Result of FastNewContextStub is always in new space.
232      need_write_barrier = false;
233    } else {
234      __ push(edi);
235      __ CallRuntime(Runtime::kNewFunctionContext, 1);
236    }
237    RecordSafepoint(Safepoint::kNoLazyDeopt);
238    // Context is returned in eax.  It replaces the context passed to us.
239    // It's saved in the stack and kept live in esi.
240    __ mov(esi, eax);
241    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
242
243    // Copy parameters into context if necessary.
244    int num_parameters = scope()->num_parameters();
245    for (int i = 0; i < num_parameters; i++) {
246      Variable* var = scope()->parameter(i);
247      if (var->IsContextSlot()) {
248        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
249            (num_parameters - 1 - i) * kPointerSize;
250        // Load parameter from stack.
251        __ mov(eax, Operand(ebp, parameter_offset));
252        // Store it in the context.
253        int context_offset = Context::SlotOffset(var->index());
254        __ mov(Operand(esi, context_offset), eax);
255        // Update the write barrier. This clobbers eax and ebx.
256        if (need_write_barrier) {
257          __ RecordWriteContextSlot(esi, context_offset, eax, ebx,
258                                    kDontSaveFPRegs);
259        } else if (FLAG_debug_code) {
260          Label done;
261          __ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
262          __ Abort(kExpectedNewSpaceObject);
263          __ bind(&done);
264        }
265      }
266    }
267    Comment(";;; End allocate local context");
268  }
269
270  // Initailize FPU state.
271  __ fninit();
272  // Trace the call.
273  if (FLAG_trace && info()->IsOptimizing()) {
274    // We have not executed any compiled code yet, so esi still holds the
275    // incoming context.
276    __ CallRuntime(Runtime::kTraceEnter, 0);
277  }
278  return !is_aborted();
279}
280
281
282void LCodeGen::GenerateOsrPrologue() {
283  // Generate the OSR entry prologue at the first unknown OSR value, or if there
284  // are none, at the OSR entrypoint instruction.
285  if (osr_pc_offset_ >= 0) return;
286
287  osr_pc_offset_ = masm()->pc_offset();
288
289    // Move state of dynamic frame alignment into edx.
290  __ Move(edx, Immediate(kNoAlignmentPadding));
291
292  if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
293    Label do_not_pad, align_loop;
294    // Align ebp + 4 to a multiple of 2 * kPointerSize.
295    __ test(ebp, Immediate(kPointerSize));
296    __ j(zero, &do_not_pad, Label::kNear);
297    __ push(Immediate(0));
298    __ mov(ebx, esp);
299    __ mov(edx, Immediate(kAlignmentPaddingPushed));
300
301    // Move all parts of the frame over one word. The frame consists of:
302    // unoptimized frame slots, alignment state, context, frame pointer, return
303    // address, receiver, and the arguments.
304    __ mov(ecx, Immediate(scope()->num_parameters() +
305           5 + graph()->osr()->UnoptimizedFrameSlots()));
306
307    __ bind(&align_loop);
308    __ mov(eax, Operand(ebx, 1 * kPointerSize));
309    __ mov(Operand(ebx, 0), eax);
310    __ add(Operand(ebx), Immediate(kPointerSize));
311    __ dec(ecx);
312    __ j(not_zero, &align_loop, Label::kNear);
313    __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue));
314    __ sub(Operand(ebp), Immediate(kPointerSize));
315    __ bind(&do_not_pad);
316  }
317
318  // Save the first local, which is overwritten by the alignment state.
319  Operand alignment_loc = MemOperand(ebp, -3 * kPointerSize);
320  __ push(alignment_loc);
321
322  // Set the dynamic frame alignment state.
323  __ mov(alignment_loc, edx);
324
325  // Adjust the frame size, subsuming the unoptimized frame into the
326  // optimized frame.
327  int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
328  DCHECK(slots >= 1);
329  __ sub(esp, Immediate((slots - 1) * kPointerSize));
330
331  // Initailize FPU state.
332  __ fninit();
333}
334
335
336void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
337  if (instr->IsCall()) {
338    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
339  }
340  if (!instr->IsLazyBailout() && !instr->IsGap()) {
341    safepoints_.BumpLastLazySafepointIndex();
342  }
343  FlushX87StackIfNecessary(instr);
344}
345
346
347void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) {
348  // When return from function call, FPU should be initialized again.
349  if (instr->IsCall() && instr->ClobbersDoubleRegisters(isolate())) {
350    bool double_result = instr->HasDoubleRegisterResult();
351    if (double_result) {
352      __ lea(esp, Operand(esp, -kDoubleSize));
353      __ fstp_d(Operand(esp, 0));
354    }
355    __ fninit();
356    if (double_result) {
357      __ fld_d(Operand(esp, 0));
358      __ lea(esp, Operand(esp, kDoubleSize));
359    }
360  }
361  if (instr->IsGoto()) {
362    x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr), this);
363  } else if (FLAG_debug_code && FLAG_enable_slow_asserts &&
364             !instr->IsGap() && !instr->IsReturn()) {
365    if (instr->ClobbersDoubleRegisters(isolate())) {
366      if (instr->HasDoubleRegisterResult()) {
367        DCHECK_EQ(1, x87_stack_.depth());
368      } else {
369        DCHECK_EQ(0, x87_stack_.depth());
370      }
371    }
372    __ VerifyX87StackDepth(x87_stack_.depth());
373  }
374}
375
376
377bool LCodeGen::GenerateJumpTable() {
378  Label needs_frame;
379  if (jump_table_.length() > 0) {
380    Comment(";;; -------------------- Jump table --------------------");
381  }
382  for (int i = 0; i < jump_table_.length(); i++) {
383    Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i];
384    __ bind(&table_entry->label);
385    Address entry = table_entry->address;
386    DeoptComment(table_entry->reason);
387    if (table_entry->needs_frame) {
388      DCHECK(!info()->saves_caller_doubles());
389      __ push(Immediate(ExternalReference::ForDeoptEntry(entry)));
390      if (needs_frame.is_bound()) {
391        __ jmp(&needs_frame);
392      } else {
393        __ bind(&needs_frame);
394        __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset));
395        // This variant of deopt can only be used with stubs. Since we don't
396        // have a function pointer to install in the stack frame that we're
397        // building, install a special marker there instead.
398        DCHECK(info()->IsStub());
399        __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
400        // Push a PC inside the function so that the deopt code can find where
401        // the deopt comes from. It doesn't have to be the precise return
402        // address of a "calling" LAZY deopt, it only has to be somewhere
403        // inside the code body.
404        Label push_approx_pc;
405        __ call(&push_approx_pc);
406        __ bind(&push_approx_pc);
407        // Push the continuation which was stashed were the ebp should
408        // be. Replace it with the saved ebp.
409        __ push(MemOperand(esp, 3 * kPointerSize));
410        __ mov(MemOperand(esp, 4 * kPointerSize), ebp);
411        __ lea(ebp, MemOperand(esp, 4 * kPointerSize));
412        __ ret(0);  // Call the continuation without clobbering registers.
413      }
414    } else {
415      __ call(entry, RelocInfo::RUNTIME_ENTRY);
416    }
417  }
418  return !is_aborted();
419}
420
421
422bool LCodeGen::GenerateDeferredCode() {
423  DCHECK(is_generating());
424  if (deferred_.length() > 0) {
425    for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
426      LDeferredCode* code = deferred_[i];
427      X87Stack copy(code->x87_stack());
428      x87_stack_ = copy;
429
430      HValue* value =
431          instructions_->at(code->instruction_index())->hydrogen_value();
432      RecordAndWritePosition(
433          chunk()->graph()->SourcePositionToScriptPosition(value->position()));
434
435      Comment(";;; <@%d,#%d> "
436              "-------------------- Deferred %s --------------------",
437              code->instruction_index(),
438              code->instr()->hydrogen_value()->id(),
439              code->instr()->Mnemonic());
440      __ bind(code->entry());
441      if (NeedsDeferredFrame()) {
442        Comment(";;; Build frame");
443        DCHECK(!frame_is_built_);
444        DCHECK(info()->IsStub());
445        frame_is_built_ = true;
446        // Build the frame in such a way that esi isn't trashed.
447        __ push(ebp);  // Caller's frame pointer.
448        __ push(Operand(ebp, StandardFrameConstants::kContextOffset));
449        __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
450        __ lea(ebp, Operand(esp, 2 * kPointerSize));
451        Comment(";;; Deferred code");
452      }
453      code->Generate();
454      if (NeedsDeferredFrame()) {
455        __ bind(code->done());
456        Comment(";;; Destroy frame");
457        DCHECK(frame_is_built_);
458        frame_is_built_ = false;
459        __ mov(esp, ebp);
460        __ pop(ebp);
461      }
462      __ jmp(code->exit());
463    }
464  }
465
466  // Deferred code is the last part of the instruction sequence. Mark
467  // the generated code as done unless we bailed out.
468  if (!is_aborted()) status_ = DONE;
469  return !is_aborted();
470}
471
472
473bool LCodeGen::GenerateSafepointTable() {
474  DCHECK(is_done());
475  if (!info()->IsStub()) {
476    // For lazy deoptimization we need space to patch a call after every call.
477    // Ensure there is always space for such patching, even if the code ends
478    // in a call.
479    int target_offset = masm()->pc_offset() + Deoptimizer::patch_size();
480    while (masm()->pc_offset() < target_offset) {
481      masm()->nop();
482    }
483  }
484  safepoints_.Emit(masm(), GetStackSlotCount());
485  return !is_aborted();
486}
487
488
489Register LCodeGen::ToRegister(int index) const {
490  return Register::FromAllocationIndex(index);
491}
492
493
494X87Register LCodeGen::ToX87Register(int index) const {
495  return X87Register::FromAllocationIndex(index);
496}
497
498
499void LCodeGen::X87LoadForUsage(X87Register reg) {
500  DCHECK(x87_stack_.Contains(reg));
501  x87_stack_.Fxch(reg);
502  x87_stack_.pop();
503}
504
505
506void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) {
507  DCHECK(x87_stack_.Contains(reg1));
508  DCHECK(x87_stack_.Contains(reg2));
509  if (reg1.is(reg2) && x87_stack_.depth() == 1) {
510    __ fld(x87_stack_.st(reg1));
511    x87_stack_.push(reg1);
512    x87_stack_.pop();
513    x87_stack_.pop();
514  } else {
515    x87_stack_.Fxch(reg1, 1);
516    x87_stack_.Fxch(reg2);
517    x87_stack_.pop();
518    x87_stack_.pop();
519  }
520}
521
522
523int LCodeGen::X87Stack::GetLayout() {
524  int layout = stack_depth_;
525  for (int i = 0; i < stack_depth_; i++) {
526    layout |= (stack_[stack_depth_ - 1 - i].code() << ((i + 1) * 3));
527  }
528
529  return layout;
530}
531
532
533void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
534  DCHECK(is_mutable_);
535  DCHECK(Contains(reg) && stack_depth_ > other_slot);
536  int i  = ArrayIndex(reg);
537  int st = st2idx(i);
538  if (st != other_slot) {
539    int other_i = st2idx(other_slot);
540    X87Register other = stack_[other_i];
541    stack_[other_i]   = reg;
542    stack_[i]         = other;
543    if (st == 0) {
544      __ fxch(other_slot);
545    } else if (other_slot == 0) {
546      __ fxch(st);
547    } else {
548      __ fxch(st);
549      __ fxch(other_slot);
550      __ fxch(st);
551    }
552  }
553}
554
555
556int LCodeGen::X87Stack::st2idx(int pos) {
557  return stack_depth_ - pos - 1;
558}
559
560
561int LCodeGen::X87Stack::ArrayIndex(X87Register reg) {
562  for (int i = 0; i < stack_depth_; i++) {
563    if (stack_[i].is(reg)) return i;
564  }
565  UNREACHABLE();
566  return -1;
567}
568
569
570bool LCodeGen::X87Stack::Contains(X87Register reg) {
571  for (int i = 0; i < stack_depth_; i++) {
572    if (stack_[i].is(reg)) return true;
573  }
574  return false;
575}
576
577
578void LCodeGen::X87Stack::Free(X87Register reg) {
579  DCHECK(is_mutable_);
580  DCHECK(Contains(reg));
581  int i  = ArrayIndex(reg);
582  int st = st2idx(i);
583  if (st > 0) {
584    // keep track of how fstp(i) changes the order of elements
585    int tos_i = st2idx(0);
586    stack_[i] = stack_[tos_i];
587  }
588  pop();
589  __ fstp(st);
590}
591
592
593void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
594  if (x87_stack_.Contains(dst)) {
595    x87_stack_.Fxch(dst);
596    __ fstp(0);
597  } else {
598    x87_stack_.push(dst);
599  }
600  X87Fld(src, opts);
601}
602
603
604void LCodeGen::X87Mov(X87Register dst, X87Register src, X87OperandType opts) {
605  if (x87_stack_.Contains(dst)) {
606    x87_stack_.Fxch(dst);
607    __ fstp(0);
608    x87_stack_.pop();
609    // Push ST(i) onto the FPU register stack
610    __ fld(x87_stack_.st(src));
611    x87_stack_.push(dst);
612  } else {
613    // Push ST(i) onto the FPU register stack
614    __ fld(x87_stack_.st(src));
615    x87_stack_.push(dst);
616  }
617}
618
619
620void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
621  DCHECK(!src.is_reg_only());
622  switch (opts) {
623    case kX87DoubleOperand:
624      __ fld_d(src);
625      break;
626    case kX87FloatOperand:
627      __ fld_s(src);
628      break;
629    case kX87IntOperand:
630      __ fild_s(src);
631      break;
632    default:
633      UNREACHABLE();
634  }
635}
636
637
638void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
639  DCHECK(!dst.is_reg_only());
640  x87_stack_.Fxch(src);
641  switch (opts) {
642    case kX87DoubleOperand:
643      __ fst_d(dst);
644      break;
645    case kX87FloatOperand:
646      __ fst_s(dst);
647      break;
648    case kX87IntOperand:
649      __ fist_s(dst);
650      break;
651    default:
652      UNREACHABLE();
653  }
654}
655
656
657void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
658  DCHECK(is_mutable_);
659  if (Contains(reg)) {
660    Free(reg);
661  }
662  // Mark this register as the next register to write to
663  stack_[stack_depth_] = reg;
664}
665
666
667void LCodeGen::X87Stack::CommitWrite(X87Register reg) {
668  DCHECK(is_mutable_);
669  // Assert the reg is prepared to write, but not on the virtual stack yet
670  DCHECK(!Contains(reg) && stack_[stack_depth_].is(reg) &&
671      stack_depth_ < X87Register::kMaxNumAllocatableRegisters);
672  stack_depth_++;
673}
674
675
676void LCodeGen::X87PrepareBinaryOp(
677    X87Register left, X87Register right, X87Register result) {
678  // You need to use DefineSameAsFirst for x87 instructions
679  DCHECK(result.is(left));
680  x87_stack_.Fxch(right, 1);
681  x87_stack_.Fxch(left);
682}
683
684
685void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
686  if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters(isolate())) {
687    bool double_inputs = instr->HasDoubleRegisterInput();
688
689    // Flush stack from tos down, since FreeX87() will mess with tos
690    for (int i = stack_depth_-1; i >= 0; i--) {
691      X87Register reg = stack_[i];
692      // Skip registers which contain the inputs for the next instruction
693      // when flushing the stack
694      if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
695        continue;
696      }
697      Free(reg);
698      if (i < stack_depth_-1) i++;
699    }
700  }
701  if (instr->IsReturn()) {
702    while (stack_depth_ > 0) {
703      __ fstp(0);
704      stack_depth_--;
705    }
706    if (FLAG_debug_code && FLAG_enable_slow_asserts) __ VerifyX87StackDepth(0);
707  }
708}
709
710
711void LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr,
712                                      LCodeGen* cgen) {
713  // For going to a joined block, an explicit LClobberDoubles is inserted before
714  // LGoto. Because all used x87 registers are spilled to stack slots. The
715  // ResolvePhis phase of register allocator could guarantee the two input's x87
716  // stacks have the same layout. So don't check stack_depth_ <= 1 here.
717  int goto_block_id = goto_instr->block_id();
718  if (current_block_id + 1 != goto_block_id) {
719    // If we have a value on the x87 stack on leaving a block, it must be a
720    // phi input. If the next block we compile is not the join block, we have
721    // to discard the stack state.
722    // Before discarding the stack state, we need to save it if the "goto block"
723    // has unreachable last predecessor when FLAG_unreachable_code_elimination.
724    if (FLAG_unreachable_code_elimination) {
725      int length = goto_instr->block()->predecessors()->length();
726      bool has_unreachable_last_predecessor = false;
727      for (int i = 0; i < length; i++) {
728        HBasicBlock* block = goto_instr->block()->predecessors()->at(i);
729        if (block->IsUnreachable() &&
730            (block->block_id() + 1) == goto_block_id) {
731          has_unreachable_last_predecessor = true;
732        }
733      }
734      if (has_unreachable_last_predecessor) {
735        if (cgen->x87_stack_map_.find(goto_block_id) ==
736            cgen->x87_stack_map_.end()) {
737          X87Stack* stack = new (cgen->zone()) X87Stack(*this);
738          cgen->x87_stack_map_.insert(std::make_pair(goto_block_id, stack));
739        }
740      }
741    }
742
743    // Discard the stack state.
744    stack_depth_ = 0;
745  }
746}
747
748
749void LCodeGen::EmitFlushX87ForDeopt() {
750  // The deoptimizer does not support X87 Registers. But as long as we
751  // deopt from a stub its not a problem, since we will re-materialize the
752  // original stub inputs, which can't be double registers.
753  // DCHECK(info()->IsStub());
754  if (FLAG_debug_code && FLAG_enable_slow_asserts) {
755    __ pushfd();
756    __ VerifyX87StackDepth(x87_stack_.depth());
757    __ popfd();
758  }
759
760  // Flush X87 stack in the deoptimizer entry.
761}
762
763
764Register LCodeGen::ToRegister(LOperand* op) const {
765  DCHECK(op->IsRegister());
766  return ToRegister(op->index());
767}
768
769
770X87Register LCodeGen::ToX87Register(LOperand* op) const {
771  DCHECK(op->IsDoubleRegister());
772  return ToX87Register(op->index());
773}
774
775
776int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
777  return ToRepresentation(op, Representation::Integer32());
778}
779
780
781int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
782                                   const Representation& r) const {
783  HConstant* constant = chunk_->LookupConstant(op);
784  int32_t value = constant->Integer32Value();
785  if (r.IsInteger32()) return value;
786  DCHECK(r.IsSmiOrTagged());
787  return reinterpret_cast<int32_t>(Smi::FromInt(value));
788}
789
790
791Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
792  HConstant* constant = chunk_->LookupConstant(op);
793  DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
794  return constant->handle(isolate());
795}
796
797
798double LCodeGen::ToDouble(LConstantOperand* op) const {
799  HConstant* constant = chunk_->LookupConstant(op);
800  DCHECK(constant->HasDoubleValue());
801  return constant->DoubleValue();
802}
803
804
805ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const {
806  HConstant* constant = chunk_->LookupConstant(op);
807  DCHECK(constant->HasExternalReferenceValue());
808  return constant->ExternalReferenceValue();
809}
810
811
812bool LCodeGen::IsInteger32(LConstantOperand* op) const {
813  return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
814}
815
816
817bool LCodeGen::IsSmi(LConstantOperand* op) const {
818  return chunk_->LookupLiteralRepresentation(op).IsSmi();
819}
820
821
822static int ArgumentsOffsetWithoutFrame(int index) {
823  DCHECK(index < 0);
824  return -(index + 1) * kPointerSize + kPCOnStackSize;
825}
826
827
828Operand LCodeGen::ToOperand(LOperand* op) const {
829  if (op->IsRegister()) return Operand(ToRegister(op));
830  DCHECK(!op->IsDoubleRegister());
831  DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
832  if (NeedsEagerFrame()) {
833    return Operand(ebp, StackSlotOffset(op->index()));
834  } else {
835    // Retrieve parameter without eager stack-frame relative to the
836    // stack-pointer.
837    return Operand(esp, ArgumentsOffsetWithoutFrame(op->index()));
838  }
839}
840
841
842Operand LCodeGen::HighOperand(LOperand* op) {
843  DCHECK(op->IsDoubleStackSlot());
844  if (NeedsEagerFrame()) {
845    return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize);
846  } else {
847    // Retrieve parameter without eager stack-frame relative to the
848    // stack-pointer.
849    return Operand(
850        esp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
851  }
852}
853
854
855void LCodeGen::WriteTranslation(LEnvironment* environment,
856                                Translation* translation) {
857  if (environment == NULL) return;
858
859  // The translation includes one command per value in the environment.
860  int translation_size = environment->translation_size();
861  // The output frame height does not include the parameters.
862  int height = translation_size - environment->parameter_count();
863
864  WriteTranslation(environment->outer(), translation);
865  bool has_closure_id = !info()->closure().is_null() &&
866      !info()->closure().is_identical_to(environment->closure());
867  int closure_id = has_closure_id
868      ? DefineDeoptimizationLiteral(environment->closure())
869      : Translation::kSelfLiteralId;
870  switch (environment->frame_type()) {
871    case JS_FUNCTION:
872      translation->BeginJSFrame(environment->ast_id(), closure_id, height);
873      break;
874    case JS_CONSTRUCT:
875      translation->BeginConstructStubFrame(closure_id, translation_size);
876      break;
877    case JS_GETTER:
878      DCHECK(translation_size == 1);
879      DCHECK(height == 0);
880      translation->BeginGetterStubFrame(closure_id);
881      break;
882    case JS_SETTER:
883      DCHECK(translation_size == 2);
884      DCHECK(height == 0);
885      translation->BeginSetterStubFrame(closure_id);
886      break;
887    case ARGUMENTS_ADAPTOR:
888      translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
889      break;
890    case STUB:
891      translation->BeginCompiledStubFrame();
892      break;
893    default:
894      UNREACHABLE();
895  }
896
897  int object_index = 0;
898  int dematerialized_index = 0;
899  for (int i = 0; i < translation_size; ++i) {
900    LOperand* value = environment->values()->at(i);
901    AddToTranslation(environment,
902                     translation,
903                     value,
904                     environment->HasTaggedValueAt(i),
905                     environment->HasUint32ValueAt(i),
906                     &object_index,
907                     &dematerialized_index);
908  }
909}
910
911
912void LCodeGen::AddToTranslation(LEnvironment* environment,
913                                Translation* translation,
914                                LOperand* op,
915                                bool is_tagged,
916                                bool is_uint32,
917                                int* object_index_pointer,
918                                int* dematerialized_index_pointer) {
919  if (op == LEnvironment::materialization_marker()) {
920    int object_index = (*object_index_pointer)++;
921    if (environment->ObjectIsDuplicateAt(object_index)) {
922      int dupe_of = environment->ObjectDuplicateOfAt(object_index);
923      translation->DuplicateObject(dupe_of);
924      return;
925    }
926    int object_length = environment->ObjectLengthAt(object_index);
927    if (environment->ObjectIsArgumentsAt(object_index)) {
928      translation->BeginArgumentsObject(object_length);
929    } else {
930      translation->BeginCapturedObject(object_length);
931    }
932    int dematerialized_index = *dematerialized_index_pointer;
933    int env_offset = environment->translation_size() + dematerialized_index;
934    *dematerialized_index_pointer += object_length;
935    for (int i = 0; i < object_length; ++i) {
936      LOperand* value = environment->values()->at(env_offset + i);
937      AddToTranslation(environment,
938                       translation,
939                       value,
940                       environment->HasTaggedValueAt(env_offset + i),
941                       environment->HasUint32ValueAt(env_offset + i),
942                       object_index_pointer,
943                       dematerialized_index_pointer);
944    }
945    return;
946  }
947
948  if (op->IsStackSlot()) {
949    if (is_tagged) {
950      translation->StoreStackSlot(op->index());
951    } else if (is_uint32) {
952      translation->StoreUint32StackSlot(op->index());
953    } else {
954      translation->StoreInt32StackSlot(op->index());
955    }
956  } else if (op->IsDoubleStackSlot()) {
957    translation->StoreDoubleStackSlot(op->index());
958  } else if (op->IsRegister()) {
959    Register reg = ToRegister(op);
960    if (is_tagged) {
961      translation->StoreRegister(reg);
962    } else if (is_uint32) {
963      translation->StoreUint32Register(reg);
964    } else {
965      translation->StoreInt32Register(reg);
966    }
967  } else if (op->IsDoubleRegister()) {
968    X87Register reg = ToX87Register(op);
969    translation->StoreDoubleRegister(reg);
970  } else if (op->IsConstantOperand()) {
971    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
972    int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
973    translation->StoreLiteral(src_index);
974  } else {
975    UNREACHABLE();
976  }
977}
978
979
980void LCodeGen::CallCodeGeneric(Handle<Code> code,
981                               RelocInfo::Mode mode,
982                               LInstruction* instr,
983                               SafepointMode safepoint_mode) {
984  DCHECK(instr != NULL);
985  __ call(code, mode);
986  RecordSafepointWithLazyDeopt(instr, safepoint_mode);
987
988  // Signal that we don't inline smi code before these stubs in the
989  // optimizing code generator.
990  if (code->kind() == Code::BINARY_OP_IC ||
991      code->kind() == Code::COMPARE_IC) {
992    __ nop();
993  }
994}
995
996
997void LCodeGen::CallCode(Handle<Code> code,
998                        RelocInfo::Mode mode,
999                        LInstruction* instr) {
1000  CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
1001}
1002
1003
1004void LCodeGen::CallRuntime(const Runtime::Function* fun, int argc,
1005                           LInstruction* instr, SaveFPRegsMode save_doubles) {
1006  DCHECK(instr != NULL);
1007  DCHECK(instr->HasPointerMap());
1008
1009  __ CallRuntime(fun, argc, save_doubles);
1010
1011  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
1012
1013  DCHECK(info()->is_calling());
1014}
1015
1016
1017void LCodeGen::LoadContextFromDeferred(LOperand* context) {
1018  if (context->IsRegister()) {
1019    if (!ToRegister(context).is(esi)) {
1020      __ mov(esi, ToRegister(context));
1021    }
1022  } else if (context->IsStackSlot()) {
1023    __ mov(esi, ToOperand(context));
1024  } else if (context->IsConstantOperand()) {
1025    HConstant* constant =
1026        chunk_->LookupConstant(LConstantOperand::cast(context));
1027    __ LoadObject(esi, Handle<Object>::cast(constant->handle(isolate())));
1028  } else {
1029    UNREACHABLE();
1030  }
1031}
1032
1033void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
1034                                       int argc,
1035                                       LInstruction* instr,
1036                                       LOperand* context) {
1037  LoadContextFromDeferred(context);
1038
1039  __ CallRuntimeSaveDoubles(id);
1040  RecordSafepointWithRegisters(
1041      instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
1042
1043  DCHECK(info()->is_calling());
1044}
1045
1046
1047void LCodeGen::RegisterEnvironmentForDeoptimization(
1048    LEnvironment* environment, Safepoint::DeoptMode mode) {
1049  environment->set_has_been_used();
1050  if (!environment->HasBeenRegistered()) {
1051    // Physical stack frame layout:
1052    // -x ............. -4  0 ..................................... y
1053    // [incoming arguments] [spill slots] [pushed outgoing arguments]
1054
1055    // Layout of the environment:
1056    // 0 ..................................................... size-1
1057    // [parameters] [locals] [expression stack including arguments]
1058
1059    // Layout of the translation:
1060    // 0 ........................................................ size - 1 + 4
1061    // [expression stack including arguments] [locals] [4 words] [parameters]
1062    // |>------------  translation_size ------------<|
1063
1064    int frame_count = 0;
1065    int jsframe_count = 0;
1066    for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
1067      ++frame_count;
1068      if (e->frame_type() == JS_FUNCTION) {
1069        ++jsframe_count;
1070      }
1071    }
1072    Translation translation(&translations_, frame_count, jsframe_count, zone());
1073    WriteTranslation(environment, &translation);
1074    int deoptimization_index = deoptimizations_.length();
1075    int pc_offset = masm()->pc_offset();
1076    environment->Register(deoptimization_index,
1077                          translation.index(),
1078                          (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
1079    deoptimizations_.Add(environment, zone());
1080  }
1081}
1082
1083
1084void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
1085                            const char* detail,
1086                            Deoptimizer::BailoutType bailout_type) {
1087  LEnvironment* environment = instr->environment();
1088  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
1089  DCHECK(environment->HasBeenRegistered());
1090  int id = environment->deoptimization_index();
1091  DCHECK(info()->IsOptimizing() || info()->IsStub());
1092  Address entry =
1093      Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
1094  if (entry == NULL) {
1095    Abort(kBailoutWasNotPrepared);
1096    return;
1097  }
1098
1099  if (DeoptEveryNTimes()) {
1100    ExternalReference count = ExternalReference::stress_deopt_count(isolate());
1101    Label no_deopt;
1102    __ pushfd();
1103    __ push(eax);
1104    __ mov(eax, Operand::StaticVariable(count));
1105    __ sub(eax, Immediate(1));
1106    __ j(not_zero, &no_deopt, Label::kNear);
1107    if (FLAG_trap_on_deopt) __ int3();
1108    __ mov(eax, Immediate(FLAG_deopt_every_n_times));
1109    __ mov(Operand::StaticVariable(count), eax);
1110    __ pop(eax);
1111    __ popfd();
1112    DCHECK(frame_is_built_);
1113    // Put the x87 stack layout in TOS.
1114    if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
1115    __ push(Immediate(x87_stack_.GetLayout()));
1116    __ fild_s(MemOperand(esp, 0));
1117    // Don't touch eflags.
1118    __ lea(esp, Operand(esp, kPointerSize));
1119    __ call(entry, RelocInfo::RUNTIME_ENTRY);
1120    __ bind(&no_deopt);
1121    __ mov(Operand::StaticVariable(count), eax);
1122    __ pop(eax);
1123    __ popfd();
1124  }
1125
1126  // Put the x87 stack layout in TOS, so that we can save x87 fp registers in
1127  // the correct location.
1128  {
1129    Label done;
1130    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
1131    if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
1132
1133    int x87_stack_layout = x87_stack_.GetLayout();
1134    __ push(Immediate(x87_stack_layout));
1135    __ fild_s(MemOperand(esp, 0));
1136    // Don't touch eflags.
1137    __ lea(esp, Operand(esp, kPointerSize));
1138    __ bind(&done);
1139  }
1140
1141  if (info()->ShouldTrapOnDeopt()) {
1142    Label done;
1143    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
1144    __ int3();
1145    __ bind(&done);
1146  }
1147
1148  Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
1149                             instr->Mnemonic(), detail);
1150  DCHECK(info()->IsStub() || frame_is_built_);
1151  if (cc == no_condition && frame_is_built_) {
1152    DeoptComment(reason);
1153    __ call(entry, RelocInfo::RUNTIME_ENTRY);
1154  } else {
1155    Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type,
1156                                            !frame_is_built_);
1157    // We often have several deopts to the same entry, reuse the last
1158    // jump entry if this is the case.
1159    if (jump_table_.is_empty() ||
1160        !table_entry.IsEquivalentTo(jump_table_.last())) {
1161      jump_table_.Add(table_entry, zone());
1162    }
1163    if (cc == no_condition) {
1164      __ jmp(&jump_table_.last().label);
1165    } else {
1166      __ j(cc, &jump_table_.last().label);
1167    }
1168  }
1169}
1170
1171
1172void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
1173                            const char* detail) {
1174  Deoptimizer::BailoutType bailout_type = info()->IsStub()
1175      ? Deoptimizer::LAZY
1176      : Deoptimizer::EAGER;
1177  DeoptimizeIf(cc, instr, detail, bailout_type);
1178}
1179
1180
1181void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
1182  int length = deoptimizations_.length();
1183  if (length == 0) return;
1184  Handle<DeoptimizationInputData> data =
1185      DeoptimizationInputData::New(isolate(), length, TENURED);
1186
1187  Handle<ByteArray> translations =
1188      translations_.CreateByteArray(isolate()->factory());
1189  data->SetTranslationByteArray(*translations);
1190  data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
1191  data->SetOptimizationId(Smi::FromInt(info_->optimization_id()));
1192  if (info_->IsOptimizing()) {
1193    // Reference to shared function info does not change between phases.
1194    AllowDeferredHandleDereference allow_handle_dereference;
1195    data->SetSharedFunctionInfo(*info_->shared_info());
1196  } else {
1197    data->SetSharedFunctionInfo(Smi::FromInt(0));
1198  }
1199
1200  Handle<FixedArray> literals =
1201      factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
1202  { AllowDeferredHandleDereference copy_handles;
1203    for (int i = 0; i < deoptimization_literals_.length(); i++) {
1204      literals->set(i, *deoptimization_literals_[i]);
1205    }
1206    data->SetLiteralArray(*literals);
1207  }
1208
1209  data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
1210  data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
1211
1212  // Populate the deoptimization entries.
1213  for (int i = 0; i < length; i++) {
1214    LEnvironment* env = deoptimizations_[i];
1215    data->SetAstId(i, env->ast_id());
1216    data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
1217    data->SetArgumentsStackHeight(i,
1218                                  Smi::FromInt(env->arguments_stack_height()));
1219    data->SetPc(i, Smi::FromInt(env->pc_offset()));
1220  }
1221  code->set_deoptimization_data(*data);
1222}
1223
1224
1225int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
1226  int result = deoptimization_literals_.length();
1227  for (int i = 0; i < deoptimization_literals_.length(); ++i) {
1228    if (deoptimization_literals_[i].is_identical_to(literal)) return i;
1229  }
1230  deoptimization_literals_.Add(literal, zone());
1231  return result;
1232}
1233
1234
1235void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
1236  DCHECK(deoptimization_literals_.length() == 0);
1237
1238  const ZoneList<Handle<JSFunction> >* inlined_closures =
1239      chunk()->inlined_closures();
1240
1241  for (int i = 0, length = inlined_closures->length();
1242       i < length;
1243       i++) {
1244    DefineDeoptimizationLiteral(inlined_closures->at(i));
1245  }
1246
1247  inlined_function_count_ = deoptimization_literals_.length();
1248}
1249
1250
1251void LCodeGen::RecordSafepointWithLazyDeopt(
1252    LInstruction* instr, SafepointMode safepoint_mode) {
1253  if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
1254    RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
1255  } else {
1256    DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
1257    RecordSafepointWithRegisters(
1258        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
1259  }
1260}
1261
1262
1263void LCodeGen::RecordSafepoint(
1264    LPointerMap* pointers,
1265    Safepoint::Kind kind,
1266    int arguments,
1267    Safepoint::DeoptMode deopt_mode) {
1268  DCHECK(kind == expected_safepoint_kind_);
1269  const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
1270  Safepoint safepoint =
1271      safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode);
1272  for (int i = 0; i < operands->length(); i++) {
1273    LOperand* pointer = operands->at(i);
1274    if (pointer->IsStackSlot()) {
1275      safepoint.DefinePointerSlot(pointer->index(), zone());
1276    } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
1277      safepoint.DefinePointerRegister(ToRegister(pointer), zone());
1278    }
1279  }
1280}
1281
1282
1283void LCodeGen::RecordSafepoint(LPointerMap* pointers,
1284                               Safepoint::DeoptMode mode) {
1285  RecordSafepoint(pointers, Safepoint::kSimple, 0, mode);
1286}
1287
1288
1289void LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) {
1290  LPointerMap empty_pointers(zone());
1291  RecordSafepoint(&empty_pointers, mode);
1292}
1293
1294
1295void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
1296                                            int arguments,
1297                                            Safepoint::DeoptMode mode) {
1298  RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode);
1299}
1300
1301
1302void LCodeGen::RecordAndWritePosition(int position) {
1303  if (position == RelocInfo::kNoPosition) return;
1304  masm()->positions_recorder()->RecordPosition(position);
1305  masm()->positions_recorder()->WriteRecordedPositions();
1306}
1307
1308
1309static const char* LabelType(LLabel* label) {
1310  if (label->is_loop_header()) return " (loop header)";
1311  if (label->is_osr_entry()) return " (OSR entry)";
1312  return "";
1313}
1314
1315
1316void LCodeGen::DoLabel(LLabel* label) {
1317  Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------",
1318          current_instruction_,
1319          label->hydrogen_value()->id(),
1320          label->block_id(),
1321          LabelType(label));
1322  __ bind(label->label());
1323  current_block_ = label->block_id();
1324  if (label->block()->predecessors()->length() > 1) {
1325    // A join block's x87 stack is that of its last visited predecessor.
1326    // If the last visited predecessor block is unreachable, the stack state
1327    // will be wrong. In such case, use the x87 stack of reachable predecessor.
1328    X87StackMap::const_iterator it = x87_stack_map_.find(current_block_);
1329    // Restore x87 stack.
1330    if (it != x87_stack_map_.end()) {
1331      x87_stack_ = *(it->second);
1332    }
1333  }
1334  DoGap(label);
1335}
1336
1337
1338void LCodeGen::DoParallelMove(LParallelMove* move) {
1339  resolver_.Resolve(move);
1340}
1341
1342
1343void LCodeGen::DoGap(LGap* gap) {
1344  for (int i = LGap::FIRST_INNER_POSITION;
1345       i <= LGap::LAST_INNER_POSITION;
1346       i++) {
1347    LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
1348    LParallelMove* move = gap->GetParallelMove(inner_pos);
1349    if (move != NULL) DoParallelMove(move);
1350  }
1351}
1352
1353
1354void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
1355  DoGap(instr);
1356}
1357
1358
1359void LCodeGen::DoParameter(LParameter* instr) {
1360  // Nothing to do.
1361}
1362
1363
1364void LCodeGen::DoCallStub(LCallStub* instr) {
1365  DCHECK(ToRegister(instr->context()).is(esi));
1366  DCHECK(ToRegister(instr->result()).is(eax));
1367  switch (instr->hydrogen()->major_key()) {
1368    case CodeStub::RegExpExec: {
1369      RegExpExecStub stub(isolate());
1370      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1371      break;
1372    }
1373    case CodeStub::SubString: {
1374      SubStringStub stub(isolate());
1375      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1376      break;
1377    }
1378    case CodeStub::StringCompare: {
1379      StringCompareStub stub(isolate());
1380      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
1381      break;
1382    }
1383    default:
1384      UNREACHABLE();
1385  }
1386}
1387
1388
1389void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
1390  GenerateOsrPrologue();
1391}
1392
1393
1394void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
1395  Register dividend = ToRegister(instr->dividend());
1396  int32_t divisor = instr->divisor();
1397  DCHECK(dividend.is(ToRegister(instr->result())));
1398
1399  // Theoretically, a variation of the branch-free code for integer division by
1400  // a power of 2 (calculating the remainder via an additional multiplication
1401  // (which gets simplified to an 'and') and subtraction) should be faster, and
1402  // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
1403  // indicate that positive dividends are heavily favored, so the branching
1404  // version performs better.
1405  HMod* hmod = instr->hydrogen();
1406  int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1407  Label dividend_is_not_negative, done;
1408  if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1409    __ test(dividend, dividend);
1410    __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1411    // Note that this is correct even for kMinInt operands.
1412    __ neg(dividend);
1413    __ and_(dividend, mask);
1414    __ neg(dividend);
1415    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1416      DeoptimizeIf(zero, instr, "minus zero");
1417    }
1418    __ jmp(&done, Label::kNear);
1419  }
1420
1421  __ bind(&dividend_is_not_negative);
1422  __ and_(dividend, mask);
1423  __ bind(&done);
1424}
1425
1426
1427void LCodeGen::DoModByConstI(LModByConstI* instr) {
1428  Register dividend = ToRegister(instr->dividend());
1429  int32_t divisor = instr->divisor();
1430  DCHECK(ToRegister(instr->result()).is(eax));
1431
1432  if (divisor == 0) {
1433    DeoptimizeIf(no_condition, instr, "division by zero");
1434    return;
1435  }
1436
1437  __ TruncatingDiv(dividend, Abs(divisor));
1438  __ imul(edx, edx, Abs(divisor));
1439  __ mov(eax, dividend);
1440  __ sub(eax, edx);
1441
1442  // Check for negative zero.
1443  HMod* hmod = instr->hydrogen();
1444  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1445    Label remainder_not_zero;
1446    __ j(not_zero, &remainder_not_zero, Label::kNear);
1447    __ cmp(dividend, Immediate(0));
1448    DeoptimizeIf(less, instr, "minus zero");
1449    __ bind(&remainder_not_zero);
1450  }
1451}
1452
1453
1454void LCodeGen::DoModI(LModI* instr) {
1455  HMod* hmod = instr->hydrogen();
1456
1457  Register left_reg = ToRegister(instr->left());
1458  DCHECK(left_reg.is(eax));
1459  Register right_reg = ToRegister(instr->right());
1460  DCHECK(!right_reg.is(eax));
1461  DCHECK(!right_reg.is(edx));
1462  Register result_reg = ToRegister(instr->result());
1463  DCHECK(result_reg.is(edx));
1464
1465  Label done;
1466  // Check for x % 0, idiv would signal a divide error. We have to
1467  // deopt in this case because we can't return a NaN.
1468  if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1469    __ test(right_reg, Operand(right_reg));
1470    DeoptimizeIf(zero, instr, "division by zero");
1471  }
1472
1473  // Check for kMinInt % -1, idiv would signal a divide error. We
1474  // have to deopt if we care about -0, because we can't return that.
1475  if (hmod->CheckFlag(HValue::kCanOverflow)) {
1476    Label no_overflow_possible;
1477    __ cmp(left_reg, kMinInt);
1478    __ j(not_equal, &no_overflow_possible, Label::kNear);
1479    __ cmp(right_reg, -1);
1480    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1481      DeoptimizeIf(equal, instr, "minus zero");
1482    } else {
1483      __ j(not_equal, &no_overflow_possible, Label::kNear);
1484      __ Move(result_reg, Immediate(0));
1485      __ jmp(&done, Label::kNear);
1486    }
1487    __ bind(&no_overflow_possible);
1488  }
1489
1490  // Sign extend dividend in eax into edx:eax.
1491  __ cdq();
1492
1493  // If we care about -0, test if the dividend is <0 and the result is 0.
1494  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1495    Label positive_left;
1496    __ test(left_reg, Operand(left_reg));
1497    __ j(not_sign, &positive_left, Label::kNear);
1498    __ idiv(right_reg);
1499    __ test(result_reg, Operand(result_reg));
1500    DeoptimizeIf(zero, instr, "minus zero");
1501    __ jmp(&done, Label::kNear);
1502    __ bind(&positive_left);
1503  }
1504  __ idiv(right_reg);
1505  __ bind(&done);
1506}
1507
1508
1509void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1510  Register dividend = ToRegister(instr->dividend());
1511  int32_t divisor = instr->divisor();
1512  Register result = ToRegister(instr->result());
1513  DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1514  DCHECK(!result.is(dividend));
1515
1516  // Check for (0 / -x) that will produce negative zero.
1517  HDiv* hdiv = instr->hydrogen();
1518  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1519    __ test(dividend, dividend);
1520    DeoptimizeIf(zero, instr, "minus zero");
1521  }
1522  // Check for (kMinInt / -1).
1523  if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1524    __ cmp(dividend, kMinInt);
1525    DeoptimizeIf(zero, instr, "overflow");
1526  }
1527  // Deoptimize if remainder will not be 0.
1528  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1529      divisor != 1 && divisor != -1) {
1530    int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1531    __ test(dividend, Immediate(mask));
1532    DeoptimizeIf(not_zero, instr, "lost precision");
1533  }
1534  __ Move(result, dividend);
1535  int32_t shift = WhichPowerOf2Abs(divisor);
1536  if (shift > 0) {
1537    // The arithmetic shift is always OK, the 'if' is an optimization only.
1538    if (shift > 1) __ sar(result, 31);
1539    __ shr(result, 32 - shift);
1540    __ add(result, dividend);
1541    __ sar(result, shift);
1542  }
1543  if (divisor < 0) __ neg(result);
1544}
1545
1546
1547void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1548  Register dividend = ToRegister(instr->dividend());
1549  int32_t divisor = instr->divisor();
1550  DCHECK(ToRegister(instr->result()).is(edx));
1551
1552  if (divisor == 0) {
1553    DeoptimizeIf(no_condition, instr, "division by zero");
1554    return;
1555  }
1556
1557  // Check for (0 / -x) that will produce negative zero.
1558  HDiv* hdiv = instr->hydrogen();
1559  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1560    __ test(dividend, dividend);
1561    DeoptimizeIf(zero, instr, "minus zero");
1562  }
1563
1564  __ TruncatingDiv(dividend, Abs(divisor));
1565  if (divisor < 0) __ neg(edx);
1566
1567  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1568    __ mov(eax, edx);
1569    __ imul(eax, eax, divisor);
1570    __ sub(eax, dividend);
1571    DeoptimizeIf(not_equal, instr, "lost precision");
1572  }
1573}
1574
1575
1576// TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1577void LCodeGen::DoDivI(LDivI* instr) {
1578  HBinaryOperation* hdiv = instr->hydrogen();
1579  Register dividend = ToRegister(instr->dividend());
1580  Register divisor = ToRegister(instr->divisor());
1581  Register remainder = ToRegister(instr->temp());
1582  DCHECK(dividend.is(eax));
1583  DCHECK(remainder.is(edx));
1584  DCHECK(ToRegister(instr->result()).is(eax));
1585  DCHECK(!divisor.is(eax));
1586  DCHECK(!divisor.is(edx));
1587
1588  // Check for x / 0.
1589  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1590    __ test(divisor, divisor);
1591    DeoptimizeIf(zero, instr, "division by zero");
1592  }
1593
1594  // Check for (0 / -x) that will produce negative zero.
1595  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1596    Label dividend_not_zero;
1597    __ test(dividend, dividend);
1598    __ j(not_zero, &dividend_not_zero, Label::kNear);
1599    __ test(divisor, divisor);
1600    DeoptimizeIf(sign, instr, "minus zero");
1601    __ bind(&dividend_not_zero);
1602  }
1603
1604  // Check for (kMinInt / -1).
1605  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1606    Label dividend_not_min_int;
1607    __ cmp(dividend, kMinInt);
1608    __ j(not_zero, &dividend_not_min_int, Label::kNear);
1609    __ cmp(divisor, -1);
1610    DeoptimizeIf(zero, instr, "overflow");
1611    __ bind(&dividend_not_min_int);
1612  }
1613
1614  // Sign extend to edx (= remainder).
1615  __ cdq();
1616  __ idiv(divisor);
1617
1618  if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1619    // Deoptimize if remainder is not 0.
1620    __ test(remainder, remainder);
1621    DeoptimizeIf(not_zero, instr, "lost precision");
1622  }
1623}
1624
1625
1626void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1627  Register dividend = ToRegister(instr->dividend());
1628  int32_t divisor = instr->divisor();
1629  DCHECK(dividend.is(ToRegister(instr->result())));
1630
1631  // If the divisor is positive, things are easy: There can be no deopts and we
1632  // can simply do an arithmetic right shift.
1633  if (divisor == 1) return;
1634  int32_t shift = WhichPowerOf2Abs(divisor);
1635  if (divisor > 1) {
1636    __ sar(dividend, shift);
1637    return;
1638  }
1639
1640  // If the divisor is negative, we have to negate and handle edge cases.
1641  __ neg(dividend);
1642  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1643    DeoptimizeIf(zero, instr, "minus zero");
1644  }
1645
1646  // Dividing by -1 is basically negation, unless we overflow.
1647  if (divisor == -1) {
1648    if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1649      DeoptimizeIf(overflow, instr, "overflow");
1650    }
1651    return;
1652  }
1653
1654  // If the negation could not overflow, simply shifting is OK.
1655  if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1656    __ sar(dividend, shift);
1657    return;
1658  }
1659
1660  Label not_kmin_int, done;
1661  __ j(no_overflow, &not_kmin_int, Label::kNear);
1662  __ mov(dividend, Immediate(kMinInt / divisor));
1663  __ jmp(&done, Label::kNear);
1664  __ bind(&not_kmin_int);
1665  __ sar(dividend, shift);
1666  __ bind(&done);
1667}
1668
1669
1670void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1671  Register dividend = ToRegister(instr->dividend());
1672  int32_t divisor = instr->divisor();
1673  DCHECK(ToRegister(instr->result()).is(edx));
1674
1675  if (divisor == 0) {
1676    DeoptimizeIf(no_condition, instr, "division by zero");
1677    return;
1678  }
1679
1680  // Check for (0 / -x) that will produce negative zero.
1681  HMathFloorOfDiv* hdiv = instr->hydrogen();
1682  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1683    __ test(dividend, dividend);
1684    DeoptimizeIf(zero, instr, "minus zero");
1685  }
1686
1687  // Easy case: We need no dynamic check for the dividend and the flooring
1688  // division is the same as the truncating division.
1689  if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1690      (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1691    __ TruncatingDiv(dividend, Abs(divisor));
1692    if (divisor < 0) __ neg(edx);
1693    return;
1694  }
1695
1696  // In the general case we may need to adjust before and after the truncating
1697  // division to get a flooring division.
1698  Register temp = ToRegister(instr->temp3());
1699  DCHECK(!temp.is(dividend) && !temp.is(eax) && !temp.is(edx));
1700  Label needs_adjustment, done;
1701  __ cmp(dividend, Immediate(0));
1702  __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear);
1703  __ TruncatingDiv(dividend, Abs(divisor));
1704  if (divisor < 0) __ neg(edx);
1705  __ jmp(&done, Label::kNear);
1706  __ bind(&needs_adjustment);
1707  __ lea(temp, Operand(dividend, divisor > 0 ? 1 : -1));
1708  __ TruncatingDiv(temp, Abs(divisor));
1709  if (divisor < 0) __ neg(edx);
1710  __ dec(edx);
1711  __ bind(&done);
1712}
1713
1714
1715// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
1716void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
1717  HBinaryOperation* hdiv = instr->hydrogen();
1718  Register dividend = ToRegister(instr->dividend());
1719  Register divisor = ToRegister(instr->divisor());
1720  Register remainder = ToRegister(instr->temp());
1721  Register result = ToRegister(instr->result());
1722  DCHECK(dividend.is(eax));
1723  DCHECK(remainder.is(edx));
1724  DCHECK(result.is(eax));
1725  DCHECK(!divisor.is(eax));
1726  DCHECK(!divisor.is(edx));
1727
1728  // Check for x / 0.
1729  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1730    __ test(divisor, divisor);
1731    DeoptimizeIf(zero, instr, "division by zero");
1732  }
1733
1734  // Check for (0 / -x) that will produce negative zero.
1735  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1736    Label dividend_not_zero;
1737    __ test(dividend, dividend);
1738    __ j(not_zero, &dividend_not_zero, Label::kNear);
1739    __ test(divisor, divisor);
1740    DeoptimizeIf(sign, instr, "minus zero");
1741    __ bind(&dividend_not_zero);
1742  }
1743
1744  // Check for (kMinInt / -1).
1745  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1746    Label dividend_not_min_int;
1747    __ cmp(dividend, kMinInt);
1748    __ j(not_zero, &dividend_not_min_int, Label::kNear);
1749    __ cmp(divisor, -1);
1750    DeoptimizeIf(zero, instr, "overflow");
1751    __ bind(&dividend_not_min_int);
1752  }
1753
1754  // Sign extend to edx (= remainder).
1755  __ cdq();
1756  __ idiv(divisor);
1757
1758  Label done;
1759  __ test(remainder, remainder);
1760  __ j(zero, &done, Label::kNear);
1761  __ xor_(remainder, divisor);
1762  __ sar(remainder, 31);
1763  __ add(result, remainder);
1764  __ bind(&done);
1765}
1766
1767
1768void LCodeGen::DoMulI(LMulI* instr) {
1769  Register left = ToRegister(instr->left());
1770  LOperand* right = instr->right();
1771
1772  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1773    __ mov(ToRegister(instr->temp()), left);
1774  }
1775
1776  if (right->IsConstantOperand()) {
1777    // Try strength reductions on the multiplication.
1778    // All replacement instructions are at most as long as the imul
1779    // and have better latency.
1780    int constant = ToInteger32(LConstantOperand::cast(right));
1781    if (constant == -1) {
1782      __ neg(left);
1783    } else if (constant == 0) {
1784      __ xor_(left, Operand(left));
1785    } else if (constant == 2) {
1786      __ add(left, Operand(left));
1787    } else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1788      // If we know that the multiplication can't overflow, it's safe to
1789      // use instructions that don't set the overflow flag for the
1790      // multiplication.
1791      switch (constant) {
1792        case 1:
1793          // Do nothing.
1794          break;
1795        case 3:
1796          __ lea(left, Operand(left, left, times_2, 0));
1797          break;
1798        case 4:
1799          __ shl(left, 2);
1800          break;
1801        case 5:
1802          __ lea(left, Operand(left, left, times_4, 0));
1803          break;
1804        case 8:
1805          __ shl(left, 3);
1806          break;
1807        case 9:
1808          __ lea(left, Operand(left, left, times_8, 0));
1809          break;
1810        case 16:
1811          __ shl(left, 4);
1812          break;
1813        default:
1814          __ imul(left, left, constant);
1815          break;
1816      }
1817    } else {
1818      __ imul(left, left, constant);
1819    }
1820  } else {
1821    if (instr->hydrogen()->representation().IsSmi()) {
1822      __ SmiUntag(left);
1823    }
1824    __ imul(left, ToOperand(right));
1825  }
1826
1827  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1828    DeoptimizeIf(overflow, instr, "overflow");
1829  }
1830
1831  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1832    // Bail out if the result is supposed to be negative zero.
1833    Label done;
1834    __ test(left, Operand(left));
1835    __ j(not_zero, &done);
1836    if (right->IsConstantOperand()) {
1837      if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1838        DeoptimizeIf(no_condition, instr, "minus zero");
1839      } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1840        __ cmp(ToRegister(instr->temp()), Immediate(0));
1841        DeoptimizeIf(less, instr, "minus zero");
1842      }
1843    } else {
1844      // Test the non-zero operand for negative sign.
1845      __ or_(ToRegister(instr->temp()), ToOperand(right));
1846      DeoptimizeIf(sign, instr, "minus zero");
1847    }
1848    __ bind(&done);
1849  }
1850}
1851
1852
1853void LCodeGen::DoBitI(LBitI* instr) {
1854  LOperand* left = instr->left();
1855  LOperand* right = instr->right();
1856  DCHECK(left->Equals(instr->result()));
1857  DCHECK(left->IsRegister());
1858
1859  if (right->IsConstantOperand()) {
1860    int32_t right_operand =
1861        ToRepresentation(LConstantOperand::cast(right),
1862                         instr->hydrogen()->representation());
1863    switch (instr->op()) {
1864      case Token::BIT_AND:
1865        __ and_(ToRegister(left), right_operand);
1866        break;
1867      case Token::BIT_OR:
1868        __ or_(ToRegister(left), right_operand);
1869        break;
1870      case Token::BIT_XOR:
1871        if (right_operand == int32_t(~0)) {
1872          __ not_(ToRegister(left));
1873        } else {
1874          __ xor_(ToRegister(left), right_operand);
1875        }
1876        break;
1877      default:
1878        UNREACHABLE();
1879        break;
1880    }
1881  } else {
1882    switch (instr->op()) {
1883      case Token::BIT_AND:
1884        __ and_(ToRegister(left), ToOperand(right));
1885        break;
1886      case Token::BIT_OR:
1887        __ or_(ToRegister(left), ToOperand(right));
1888        break;
1889      case Token::BIT_XOR:
1890        __ xor_(ToRegister(left), ToOperand(right));
1891        break;
1892      default:
1893        UNREACHABLE();
1894        break;
1895    }
1896  }
1897}
1898
1899
1900void LCodeGen::DoShiftI(LShiftI* instr) {
1901  LOperand* left = instr->left();
1902  LOperand* right = instr->right();
1903  DCHECK(left->Equals(instr->result()));
1904  DCHECK(left->IsRegister());
1905  if (right->IsRegister()) {
1906    DCHECK(ToRegister(right).is(ecx));
1907
1908    switch (instr->op()) {
1909      case Token::ROR:
1910        __ ror_cl(ToRegister(left));
1911        break;
1912      case Token::SAR:
1913        __ sar_cl(ToRegister(left));
1914        break;
1915      case Token::SHR:
1916        __ shr_cl(ToRegister(left));
1917        if (instr->can_deopt()) {
1918          __ test(ToRegister(left), ToRegister(left));
1919          DeoptimizeIf(sign, instr, "negative value");
1920        }
1921        break;
1922      case Token::SHL:
1923        __ shl_cl(ToRegister(left));
1924        break;
1925      default:
1926        UNREACHABLE();
1927        break;
1928    }
1929  } else {
1930    int value = ToInteger32(LConstantOperand::cast(right));
1931    uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1932    switch (instr->op()) {
1933      case Token::ROR:
1934        if (shift_count == 0 && instr->can_deopt()) {
1935          __ test(ToRegister(left), ToRegister(left));
1936          DeoptimizeIf(sign, instr, "negative value");
1937        } else {
1938          __ ror(ToRegister(left), shift_count);
1939        }
1940        break;
1941      case Token::SAR:
1942        if (shift_count != 0) {
1943          __ sar(ToRegister(left), shift_count);
1944        }
1945        break;
1946      case Token::SHR:
1947        if (shift_count != 0) {
1948          __ shr(ToRegister(left), shift_count);
1949        } else if (instr->can_deopt()) {
1950          __ test(ToRegister(left), ToRegister(left));
1951          DeoptimizeIf(sign, instr, "negative value");
1952        }
1953        break;
1954      case Token::SHL:
1955        if (shift_count != 0) {
1956          if (instr->hydrogen_value()->representation().IsSmi() &&
1957              instr->can_deopt()) {
1958            if (shift_count != 1) {
1959              __ shl(ToRegister(left), shift_count - 1);
1960            }
1961            __ SmiTag(ToRegister(left));
1962            DeoptimizeIf(overflow, instr, "overflow");
1963          } else {
1964            __ shl(ToRegister(left), shift_count);
1965          }
1966        }
1967        break;
1968      default:
1969        UNREACHABLE();
1970        break;
1971    }
1972  }
1973}
1974
1975
1976void LCodeGen::DoSubI(LSubI* instr) {
1977  LOperand* left = instr->left();
1978  LOperand* right = instr->right();
1979  DCHECK(left->Equals(instr->result()));
1980
1981  if (right->IsConstantOperand()) {
1982    __ sub(ToOperand(left),
1983           ToImmediate(right, instr->hydrogen()->representation()));
1984  } else {
1985    __ sub(ToRegister(left), ToOperand(right));
1986  }
1987  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1988    DeoptimizeIf(overflow, instr, "overflow");
1989  }
1990}
1991
1992
1993void LCodeGen::DoConstantI(LConstantI* instr) {
1994  __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1995}
1996
1997
1998void LCodeGen::DoConstantS(LConstantS* instr) {
1999  __ Move(ToRegister(instr->result()), Immediate(instr->value()));
2000}
2001
2002
2003void LCodeGen::DoConstantD(LConstantD* instr) {
2004  double v = instr->value();
2005  uint64_t int_val = bit_cast<uint64_t, double>(v);
2006  int32_t lower = static_cast<int32_t>(int_val);
2007  int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
2008  DCHECK(instr->result()->IsDoubleRegister());
2009
2010  __ push(Immediate(upper));
2011  __ push(Immediate(lower));
2012  X87Register reg = ToX87Register(instr->result());
2013  X87Mov(reg, Operand(esp, 0));
2014  __ add(Operand(esp), Immediate(kDoubleSize));
2015}
2016
2017
2018void LCodeGen::DoConstantE(LConstantE* instr) {
2019  __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value()));
2020}
2021
2022
2023void LCodeGen::DoConstantT(LConstantT* instr) {
2024  Register reg = ToRegister(instr->result());
2025  Handle<Object> object = instr->value(isolate());
2026  AllowDeferredHandleDereference smi_check;
2027  __ LoadObject(reg, object);
2028}
2029
2030
2031void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) {
2032  Register result = ToRegister(instr->result());
2033  Register map = ToRegister(instr->value());
2034  __ EnumLength(result, map);
2035}
2036
2037
2038void LCodeGen::DoDateField(LDateField* instr) {
2039  Register object = ToRegister(instr->date());
2040  Register result = ToRegister(instr->result());
2041  Register scratch = ToRegister(instr->temp());
2042  Smi* index = instr->index();
2043  Label runtime, done;
2044  DCHECK(object.is(result));
2045  DCHECK(object.is(eax));
2046
2047  __ test(object, Immediate(kSmiTagMask));
2048  DeoptimizeIf(zero, instr, "Smi");
2049  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
2050  DeoptimizeIf(not_equal, instr, "not a date object");
2051
2052  if (index->value() == 0) {
2053    __ mov(result, FieldOperand(object, JSDate::kValueOffset));
2054  } else {
2055    if (index->value() < JSDate::kFirstUncachedField) {
2056      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
2057      __ mov(scratch, Operand::StaticVariable(stamp));
2058      __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
2059      __ j(not_equal, &runtime, Label::kNear);
2060      __ mov(result, FieldOperand(object, JSDate::kValueOffset +
2061                                          kPointerSize * index->value()));
2062      __ jmp(&done, Label::kNear);
2063    }
2064    __ bind(&runtime);
2065    __ PrepareCallCFunction(2, scratch);
2066    __ mov(Operand(esp, 0), object);
2067    __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
2068    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
2069    __ bind(&done);
2070  }
2071}
2072
2073
2074Operand LCodeGen::BuildSeqStringOperand(Register string,
2075                                        LOperand* index,
2076                                        String::Encoding encoding) {
2077  if (index->IsConstantOperand()) {
2078    int offset = ToRepresentation(LConstantOperand::cast(index),
2079                                  Representation::Integer32());
2080    if (encoding == String::TWO_BYTE_ENCODING) {
2081      offset *= kUC16Size;
2082    }
2083    STATIC_ASSERT(kCharSize == 1);
2084    return FieldOperand(string, SeqString::kHeaderSize + offset);
2085  }
2086  return FieldOperand(
2087      string, ToRegister(index),
2088      encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2,
2089      SeqString::kHeaderSize);
2090}
2091
2092
2093void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
2094  String::Encoding encoding = instr->hydrogen()->encoding();
2095  Register result = ToRegister(instr->result());
2096  Register string = ToRegister(instr->string());
2097
2098  if (FLAG_debug_code) {
2099    __ push(string);
2100    __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
2101    __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
2102
2103    __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
2104    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
2105    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
2106    __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
2107                             ? one_byte_seq_type : two_byte_seq_type));
2108    __ Check(equal, kUnexpectedStringType);
2109    __ pop(string);
2110  }
2111
2112  Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
2113  if (encoding == String::ONE_BYTE_ENCODING) {
2114    __ movzx_b(result, operand);
2115  } else {
2116    __ movzx_w(result, operand);
2117  }
2118}
2119
2120
2121void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
2122  String::Encoding encoding = instr->hydrogen()->encoding();
2123  Register string = ToRegister(instr->string());
2124
2125  if (FLAG_debug_code) {
2126    Register value = ToRegister(instr->value());
2127    Register index = ToRegister(instr->index());
2128    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
2129    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
2130    int encoding_mask =
2131        instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
2132        ? one_byte_seq_type : two_byte_seq_type;
2133    __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
2134  }
2135
2136  Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
2137  if (instr->value()->IsConstantOperand()) {
2138    int value = ToRepresentation(LConstantOperand::cast(instr->value()),
2139                                 Representation::Integer32());
2140    DCHECK_LE(0, value);
2141    if (encoding == String::ONE_BYTE_ENCODING) {
2142      DCHECK_LE(value, String::kMaxOneByteCharCode);
2143      __ mov_b(operand, static_cast<int8_t>(value));
2144    } else {
2145      DCHECK_LE(value, String::kMaxUtf16CodeUnit);
2146      __ mov_w(operand, static_cast<int16_t>(value));
2147    }
2148  } else {
2149    Register value = ToRegister(instr->value());
2150    if (encoding == String::ONE_BYTE_ENCODING) {
2151      __ mov_b(operand, value);
2152    } else {
2153      __ mov_w(operand, value);
2154    }
2155  }
2156}
2157
2158
2159void LCodeGen::DoAddI(LAddI* instr) {
2160  LOperand* left = instr->left();
2161  LOperand* right = instr->right();
2162
2163  if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
2164    if (right->IsConstantOperand()) {
2165      int32_t offset = ToRepresentation(LConstantOperand::cast(right),
2166                                        instr->hydrogen()->representation());
2167      __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset));
2168    } else {
2169      Operand address(ToRegister(left), ToRegister(right), times_1, 0);
2170      __ lea(ToRegister(instr->result()), address);
2171    }
2172  } else {
2173    if (right->IsConstantOperand()) {
2174      __ add(ToOperand(left),
2175             ToImmediate(right, instr->hydrogen()->representation()));
2176    } else {
2177      __ add(ToRegister(left), ToOperand(right));
2178    }
2179    if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
2180      DeoptimizeIf(overflow, instr, "overflow");
2181    }
2182  }
2183}
2184
2185
2186void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
2187  LOperand* left = instr->left();
2188  LOperand* right = instr->right();
2189  DCHECK(left->Equals(instr->result()));
2190  HMathMinMax::Operation operation = instr->hydrogen()->operation();
2191  if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
2192    Label return_left;
2193    Condition condition = (operation == HMathMinMax::kMathMin)
2194        ? less_equal
2195        : greater_equal;
2196    if (right->IsConstantOperand()) {
2197      Operand left_op = ToOperand(left);
2198      Immediate immediate = ToImmediate(LConstantOperand::cast(instr->right()),
2199                                        instr->hydrogen()->representation());
2200      __ cmp(left_op, immediate);
2201      __ j(condition, &return_left, Label::kNear);
2202      __ mov(left_op, immediate);
2203    } else {
2204      Register left_reg = ToRegister(left);
2205      Operand right_op = ToOperand(right);
2206      __ cmp(left_reg, right_op);
2207      __ j(condition, &return_left, Label::kNear);
2208      __ mov(left_reg, right_op);
2209    }
2210    __ bind(&return_left);
2211  } else {
2212    DCHECK(instr->hydrogen()->representation().IsDouble());
2213    Label check_nan_left, check_zero, return_left, return_right;
2214    Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
2215    X87Register left_reg = ToX87Register(left);
2216    X87Register right_reg = ToX87Register(right);
2217
2218    X87PrepareBinaryOp(left_reg, right_reg, ToX87Register(instr->result()));
2219    __ fld(1);
2220    __ fld(1);
2221    __ FCmp();
2222    __ j(parity_even, &check_nan_left, Label::kNear);  // At least one NaN.
2223    __ j(equal, &check_zero, Label::kNear);            // left == right.
2224    __ j(condition, &return_left, Label::kNear);
2225    __ jmp(&return_right, Label::kNear);
2226
2227    __ bind(&check_zero);
2228    __ fld(0);
2229    __ fldz();
2230    __ FCmp();
2231    __ j(not_equal, &return_left, Label::kNear);  // left == right != 0.
2232    // At this point, both left and right are either 0 or -0.
2233    if (operation == HMathMinMax::kMathMin) {
2234      // Push st0 and st1 to stack, then pop them to temp registers and OR them,
2235      // load it to left.
2236      Register scratch_reg = ToRegister(instr->temp());
2237      __ fld(1);
2238      __ fld(1);
2239      __ sub(esp, Immediate(2 * kPointerSize));
2240      __ fstp_s(MemOperand(esp, 0));
2241      __ fstp_s(MemOperand(esp, kPointerSize));
2242      __ pop(scratch_reg);
2243      __ xor_(MemOperand(esp, 0), scratch_reg);
2244      X87Mov(left_reg, MemOperand(esp, 0), kX87FloatOperand);
2245      __ pop(scratch_reg);  // restore esp
2246    } else {
2247      // Since we operate on +0 and/or -0, addsd and andsd have the same effect.
2248      X87Fxch(left_reg);
2249      __ fadd(1);
2250    }
2251    __ jmp(&return_left, Label::kNear);
2252
2253    __ bind(&check_nan_left);
2254    __ fld(0);
2255    __ fld(0);
2256    __ FCmp();                                      // NaN check.
2257    __ j(parity_even, &return_left, Label::kNear);  // left == NaN.
2258
2259    __ bind(&return_right);
2260    X87Fxch(left_reg);
2261    X87Mov(left_reg, right_reg);
2262
2263    __ bind(&return_left);
2264  }
2265}
2266
2267
2268void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
2269  X87Register left = ToX87Register(instr->left());
2270  X87Register right = ToX87Register(instr->right());
2271  X87Register result = ToX87Register(instr->result());
2272  if (instr->op() != Token::MOD) {
2273    X87PrepareBinaryOp(left, right, result);
2274  }
2275  // Set the precision control to double-precision.
2276  __ X87SetFPUCW(0x027F);
2277  switch (instr->op()) {
2278    case Token::ADD:
2279      __ fadd_i(1);
2280      break;
2281    case Token::SUB:
2282      __ fsub_i(1);
2283      break;
2284    case Token::MUL:
2285      __ fmul_i(1);
2286      break;
2287    case Token::DIV:
2288      __ fdiv_i(1);
2289      break;
2290    case Token::MOD: {
2291      // Pass two doubles as arguments on the stack.
2292      __ PrepareCallCFunction(4, eax);
2293      X87Mov(Operand(esp, 1 * kDoubleSize), right);
2294      X87Mov(Operand(esp, 0), left);
2295      X87Free(right);
2296      DCHECK(left.is(result));
2297      X87PrepareToWrite(result);
2298      __ CallCFunction(
2299          ExternalReference::mod_two_doubles_operation(isolate()),
2300          4);
2301
2302      // Return value is in st(0) on ia32.
2303      X87CommitWrite(result);
2304      break;
2305    }
2306    default:
2307      UNREACHABLE();
2308      break;
2309  }
2310
2311  // Restore the default value of control word.
2312  __ X87SetFPUCW(0x037F);
2313}
2314
2315
2316void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
2317  DCHECK(ToRegister(instr->context()).is(esi));
2318  DCHECK(ToRegister(instr->left()).is(edx));
2319  DCHECK(ToRegister(instr->right()).is(eax));
2320  DCHECK(ToRegister(instr->result()).is(eax));
2321
2322  Handle<Code> code =
2323      CodeFactory::BinaryOpIC(isolate(), instr->op(), NO_OVERWRITE).code();
2324  CallCode(code, RelocInfo::CODE_TARGET, instr);
2325}
2326
2327
2328template<class InstrType>
2329void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
2330  int left_block = instr->TrueDestination(chunk_);
2331  int right_block = instr->FalseDestination(chunk_);
2332
2333  int next_block = GetNextEmittedBlock();
2334
2335  if (right_block == left_block || cc == no_condition) {
2336    EmitGoto(left_block);
2337  } else if (left_block == next_block) {
2338    __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
2339  } else if (right_block == next_block) {
2340    __ j(cc, chunk_->GetAssemblyLabel(left_block));
2341  } else {
2342    __ j(cc, chunk_->GetAssemblyLabel(left_block));
2343    __ jmp(chunk_->GetAssemblyLabel(right_block));
2344  }
2345}
2346
2347
2348template<class InstrType>
2349void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
2350  int false_block = instr->FalseDestination(chunk_);
2351  if (cc == no_condition) {
2352    __ jmp(chunk_->GetAssemblyLabel(false_block));
2353  } else {
2354    __ j(cc, chunk_->GetAssemblyLabel(false_block));
2355  }
2356}
2357
2358
2359void LCodeGen::DoBranch(LBranch* instr) {
2360  Representation r = instr->hydrogen()->value()->representation();
2361  if (r.IsSmiOrInteger32()) {
2362    Register reg = ToRegister(instr->value());
2363    __ test(reg, Operand(reg));
2364    EmitBranch(instr, not_zero);
2365  } else if (r.IsDouble()) {
2366    X87Register reg = ToX87Register(instr->value());
2367    X87LoadForUsage(reg);
2368    __ fldz();
2369    __ FCmp();
2370    EmitBranch(instr, not_zero);
2371  } else {
2372    DCHECK(r.IsTagged());
2373    Register reg = ToRegister(instr->value());
2374    HType type = instr->hydrogen()->value()->type();
2375    if (type.IsBoolean()) {
2376      DCHECK(!info()->IsStub());
2377      __ cmp(reg, factory()->true_value());
2378      EmitBranch(instr, equal);
2379    } else if (type.IsSmi()) {
2380      DCHECK(!info()->IsStub());
2381      __ test(reg, Operand(reg));
2382      EmitBranch(instr, not_equal);
2383    } else if (type.IsJSArray()) {
2384      DCHECK(!info()->IsStub());
2385      EmitBranch(instr, no_condition);
2386    } else if (type.IsHeapNumber()) {
2387      UNREACHABLE();
2388    } else if (type.IsString()) {
2389      DCHECK(!info()->IsStub());
2390      __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2391      EmitBranch(instr, not_equal);
2392    } else {
2393      ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2394      if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2395
2396      if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2397        // undefined -> false.
2398        __ cmp(reg, factory()->undefined_value());
2399        __ j(equal, instr->FalseLabel(chunk_));
2400      }
2401      if (expected.Contains(ToBooleanStub::BOOLEAN)) {
2402        // true -> true.
2403        __ cmp(reg, factory()->true_value());
2404        __ j(equal, instr->TrueLabel(chunk_));
2405        // false -> false.
2406        __ cmp(reg, factory()->false_value());
2407        __ j(equal, instr->FalseLabel(chunk_));
2408      }
2409      if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
2410        // 'null' -> false.
2411        __ cmp(reg, factory()->null_value());
2412        __ j(equal, instr->FalseLabel(chunk_));
2413      }
2414
2415      if (expected.Contains(ToBooleanStub::SMI)) {
2416        // Smis: 0 -> false, all other -> true.
2417        __ test(reg, Operand(reg));
2418        __ j(equal, instr->FalseLabel(chunk_));
2419        __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2420      } else if (expected.NeedsMap()) {
2421        // If we need a map later and have a Smi -> deopt.
2422        __ test(reg, Immediate(kSmiTagMask));
2423        DeoptimizeIf(zero, instr, "Smi");
2424      }
2425
2426      Register map = no_reg;  // Keep the compiler happy.
2427      if (expected.NeedsMap()) {
2428        map = ToRegister(instr->temp());
2429        DCHECK(!map.is(reg));
2430        __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
2431
2432        if (expected.CanBeUndetectable()) {
2433          // Undetectable -> false.
2434          __ test_b(FieldOperand(map, Map::kBitFieldOffset),
2435                    1 << Map::kIsUndetectable);
2436          __ j(not_zero, instr->FalseLabel(chunk_));
2437        }
2438      }
2439
2440      if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
2441        // spec object -> true.
2442        __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
2443        __ j(above_equal, instr->TrueLabel(chunk_));
2444      }
2445
2446      if (expected.Contains(ToBooleanStub::STRING)) {
2447        // String value -> false iff empty.
2448        Label not_string;
2449        __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
2450        __ j(above_equal, &not_string, Label::kNear);
2451        __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2452        __ j(not_zero, instr->TrueLabel(chunk_));
2453        __ jmp(instr->FalseLabel(chunk_));
2454        __ bind(&not_string);
2455      }
2456
2457      if (expected.Contains(ToBooleanStub::SYMBOL)) {
2458        // Symbol value -> true.
2459        __ CmpInstanceType(map, SYMBOL_TYPE);
2460        __ j(equal, instr->TrueLabel(chunk_));
2461      }
2462
2463      if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2464        // heap number -> false iff +0, -0, or NaN.
2465        Label not_heap_number;
2466        __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
2467               factory()->heap_number_map());
2468        __ j(not_equal, &not_heap_number, Label::kNear);
2469        __ fldz();
2470        __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
2471        __ FCmp();
2472        __ j(zero, instr->FalseLabel(chunk_));
2473        __ jmp(instr->TrueLabel(chunk_));
2474        __ bind(&not_heap_number);
2475      }
2476
2477      if (!expected.IsGeneric()) {
2478        // We've seen something for the first time -> deopt.
2479        // This can only happen if we are not generic already.
2480        DeoptimizeIf(no_condition, instr, "unexpected object");
2481      }
2482    }
2483  }
2484}
2485
2486
2487void LCodeGen::EmitGoto(int block) {
2488  if (!IsNextEmittedBlock(block)) {
2489    __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2490  }
2491}
2492
2493
2494void LCodeGen::DoClobberDoubles(LClobberDoubles* instr) {
2495}
2496
2497
2498void LCodeGen::DoGoto(LGoto* instr) {
2499  EmitGoto(instr->block_id());
2500}
2501
2502
2503Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
2504  Condition cond = no_condition;
2505  switch (op) {
2506    case Token::EQ:
2507    case Token::EQ_STRICT:
2508      cond = equal;
2509      break;
2510    case Token::NE:
2511    case Token::NE_STRICT:
2512      cond = not_equal;
2513      break;
2514    case Token::LT:
2515      cond = is_unsigned ? below : less;
2516      break;
2517    case Token::GT:
2518      cond = is_unsigned ? above : greater;
2519      break;
2520    case Token::LTE:
2521      cond = is_unsigned ? below_equal : less_equal;
2522      break;
2523    case Token::GTE:
2524      cond = is_unsigned ? above_equal : greater_equal;
2525      break;
2526    case Token::IN:
2527    case Token::INSTANCEOF:
2528    default:
2529      UNREACHABLE();
2530  }
2531  return cond;
2532}
2533
2534
2535void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
2536  LOperand* left = instr->left();
2537  LOperand* right = instr->right();
2538  bool is_unsigned =
2539      instr->is_double() ||
2540      instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
2541      instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
2542  Condition cc = TokenToCondition(instr->op(), is_unsigned);
2543
2544  if (left->IsConstantOperand() && right->IsConstantOperand()) {
2545    // We can statically evaluate the comparison.
2546    double left_val = ToDouble(LConstantOperand::cast(left));
2547    double right_val = ToDouble(LConstantOperand::cast(right));
2548    int next_block = EvalComparison(instr->op(), left_val, right_val) ?
2549        instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
2550    EmitGoto(next_block);
2551  } else {
2552    if (instr->is_double()) {
2553      X87LoadForUsage(ToX87Register(right), ToX87Register(left));
2554      __ FCmp();
2555      // Don't base result on EFLAGS when a NaN is involved. Instead
2556      // jump to the false block.
2557      __ j(parity_even, instr->FalseLabel(chunk_));
2558    } else {
2559      if (right->IsConstantOperand()) {
2560        __ cmp(ToOperand(left),
2561               ToImmediate(right, instr->hydrogen()->representation()));
2562      } else if (left->IsConstantOperand()) {
2563        __ cmp(ToOperand(right),
2564               ToImmediate(left, instr->hydrogen()->representation()));
2565        // We commuted the operands, so commute the condition.
2566        cc = CommuteCondition(cc);
2567      } else {
2568        __ cmp(ToRegister(left), ToOperand(right));
2569      }
2570    }
2571    EmitBranch(instr, cc);
2572  }
2573}
2574
2575
2576void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
2577  Register left = ToRegister(instr->left());
2578
2579  if (instr->right()->IsConstantOperand()) {
2580    Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
2581    __ CmpObject(left, right);
2582  } else {
2583    Operand right = ToOperand(instr->right());
2584    __ cmp(left, right);
2585  }
2586  EmitBranch(instr, equal);
2587}
2588
2589
2590void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2591  if (instr->hydrogen()->representation().IsTagged()) {
2592    Register input_reg = ToRegister(instr->object());
2593    __ cmp(input_reg, factory()->the_hole_value());
2594    EmitBranch(instr, equal);
2595    return;
2596  }
2597
2598  // Put the value to the top of stack
2599  X87Register src = ToX87Register(instr->object());
2600  X87LoadForUsage(src);
2601  __ fld(0);
2602  __ fld(0);
2603  __ FCmp();
2604  Label ok;
2605  __ j(parity_even, &ok, Label::kNear);
2606  __ fstp(0);
2607  EmitFalseBranch(instr, no_condition);
2608  __ bind(&ok);
2609
2610
2611  __ sub(esp, Immediate(kDoubleSize));
2612  __ fstp_d(MemOperand(esp, 0));
2613
2614  __ add(esp, Immediate(kDoubleSize));
2615  int offset = sizeof(kHoleNanUpper32);
2616  __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
2617  EmitBranch(instr, equal);
2618}
2619
2620
2621void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2622  Representation rep = instr->hydrogen()->value()->representation();
2623  DCHECK(!rep.IsInteger32());
2624
2625  if (rep.IsDouble()) {
2626    X87Register input = ToX87Register(instr->value());
2627    X87LoadForUsage(input);
2628    __ FXamMinusZero();
2629    EmitBranch(instr, equal);
2630  } else {
2631    Register value = ToRegister(instr->value());
2632    Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
2633    __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
2634    __ cmp(FieldOperand(value, HeapNumber::kExponentOffset),
2635           Immediate(0x1));
2636    EmitFalseBranch(instr, no_overflow);
2637    __ cmp(FieldOperand(value, HeapNumber::kMantissaOffset),
2638           Immediate(0x00000000));
2639    EmitBranch(instr, equal);
2640  }
2641}
2642
2643
2644Condition LCodeGen::EmitIsObject(Register input,
2645                                 Register temp1,
2646                                 Label* is_not_object,
2647                                 Label* is_object) {
2648  __ JumpIfSmi(input, is_not_object);
2649
2650  __ cmp(input, isolate()->factory()->null_value());
2651  __ j(equal, is_object);
2652
2653  __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
2654  // Undetectable objects behave like undefined.
2655  __ test_b(FieldOperand(temp1, Map::kBitFieldOffset),
2656            1 << Map::kIsUndetectable);
2657  __ j(not_zero, is_not_object);
2658
2659  __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset));
2660  __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
2661  __ j(below, is_not_object);
2662  __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
2663  return below_equal;
2664}
2665
2666
2667void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
2668  Register reg = ToRegister(instr->value());
2669  Register temp = ToRegister(instr->temp());
2670
2671  Condition true_cond = EmitIsObject(
2672      reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));
2673
2674  EmitBranch(instr, true_cond);
2675}
2676
2677
2678Condition LCodeGen::EmitIsString(Register input,
2679                                 Register temp1,
2680                                 Label* is_not_string,
2681                                 SmiCheck check_needed = INLINE_SMI_CHECK) {
2682  if (check_needed == INLINE_SMI_CHECK) {
2683    __ JumpIfSmi(input, is_not_string);
2684  }
2685
2686  Condition cond = masm_->IsObjectStringType(input, temp1, temp1);
2687
2688  return cond;
2689}
2690
2691
2692void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
2693  Register reg = ToRegister(instr->value());
2694  Register temp = ToRegister(instr->temp());
2695
2696  SmiCheck check_needed =
2697      instr->hydrogen()->value()->type().IsHeapObject()
2698          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2699
2700  Condition true_cond = EmitIsString(
2701      reg, temp, instr->FalseLabel(chunk_), check_needed);
2702
2703  EmitBranch(instr, true_cond);
2704}
2705
2706
2707void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
2708  Operand input = ToOperand(instr->value());
2709
2710  __ test(input, Immediate(kSmiTagMask));
2711  EmitBranch(instr, zero);
2712}
2713
2714
2715void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
2716  Register input = ToRegister(instr->value());
2717  Register temp = ToRegister(instr->temp());
2718
2719  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2720    STATIC_ASSERT(kSmiTag == 0);
2721    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2722  }
2723  __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
2724  __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
2725            1 << Map::kIsUndetectable);
2726  EmitBranch(instr, not_zero);
2727}
2728
2729
2730static Condition ComputeCompareCondition(Token::Value op) {
2731  switch (op) {
2732    case Token::EQ_STRICT:
2733    case Token::EQ:
2734      return equal;
2735    case Token::LT:
2736      return less;
2737    case Token::GT:
2738      return greater;
2739    case Token::LTE:
2740      return less_equal;
2741    case Token::GTE:
2742      return greater_equal;
2743    default:
2744      UNREACHABLE();
2745      return no_condition;
2746  }
2747}
2748
2749
2750void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2751  Token::Value op = instr->op();
2752
2753  Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
2754  CallCode(ic, RelocInfo::CODE_TARGET, instr);
2755
2756  Condition condition = ComputeCompareCondition(op);
2757  __ test(eax, Operand(eax));
2758
2759  EmitBranch(instr, condition);
2760}
2761
2762
2763static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2764  InstanceType from = instr->from();
2765  InstanceType to = instr->to();
2766  if (from == FIRST_TYPE) return to;
2767  DCHECK(from == to || to == LAST_TYPE);
2768  return from;
2769}
2770
2771
2772static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
2773  InstanceType from = instr->from();
2774  InstanceType to = instr->to();
2775  if (from == to) return equal;
2776  if (to == LAST_TYPE) return above_equal;
2777  if (from == FIRST_TYPE) return below_equal;
2778  UNREACHABLE();
2779  return equal;
2780}
2781
2782
2783void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
2784  Register input = ToRegister(instr->value());
2785  Register temp = ToRegister(instr->temp());
2786
2787  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
2788    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
2789  }
2790
2791  __ CmpObjectType(input, TestType(instr->hydrogen()), temp);
2792  EmitBranch(instr, BranchCondition(instr->hydrogen()));
2793}
2794
2795
2796void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
2797  Register input = ToRegister(instr->value());
2798  Register result = ToRegister(instr->result());
2799
2800  __ AssertString(input);
2801
2802  __ mov(result, FieldOperand(input, String::kHashFieldOffset));
2803  __ IndexFromHash(result, result);
2804}
2805
2806
2807void LCodeGen::DoHasCachedArrayIndexAndBranch(
2808    LHasCachedArrayIndexAndBranch* instr) {
2809  Register input = ToRegister(instr->value());
2810
2811  __ test(FieldOperand(input, String::kHashFieldOffset),
2812          Immediate(String::kContainsCachedArrayIndexMask));
2813  EmitBranch(instr, equal);
2814}
2815
2816
2817// Branches to a label or falls through with the answer in the z flag.  Trashes
2818// the temp registers, but not the input.
2819void LCodeGen::EmitClassOfTest(Label* is_true,
2820                               Label* is_false,
2821                               Handle<String>class_name,
2822                               Register input,
2823                               Register temp,
2824                               Register temp2) {
2825  DCHECK(!input.is(temp));
2826  DCHECK(!input.is(temp2));
2827  DCHECK(!temp.is(temp2));
2828  __ JumpIfSmi(input, is_false);
2829
2830  if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
2831    // Assuming the following assertions, we can use the same compares to test
2832    // for both being a function type and being in the object type range.
2833    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
2834    STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2835                  FIRST_SPEC_OBJECT_TYPE + 1);
2836    STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
2837                  LAST_SPEC_OBJECT_TYPE - 1);
2838    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
2839    __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
2840    __ j(below, is_false);
2841    __ j(equal, is_true);
2842    __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE);
2843    __ j(equal, is_true);
2844  } else {
2845    // Faster code path to avoid two compares: subtract lower bound from the
2846    // actual type and do a signed compare with the width of the type range.
2847    __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
2848    __ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
2849    __ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2850    __ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
2851                                     FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
2852    __ j(above, is_false);
2853  }
2854
2855  // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
2856  // Check if the constructor in the map is a function.
2857  __ mov(temp, FieldOperand(temp, Map::kConstructorOffset));
2858  // Objects with a non-function constructor have class 'Object'.
2859  __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2);
2860  if (String::Equals(class_name, isolate()->factory()->Object_string())) {
2861    __ j(not_equal, is_true);
2862  } else {
2863    __ j(not_equal, is_false);
2864  }
2865
2866  // temp now contains the constructor function. Grab the
2867  // instance class name from there.
2868  __ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
2869  __ mov(temp, FieldOperand(temp,
2870                            SharedFunctionInfo::kInstanceClassNameOffset));
2871  // The class name we are testing against is internalized since it's a literal.
2872  // The name in the constructor is internalized because of the way the context
2873  // is booted.  This routine isn't expected to work for random API-created
2874  // classes and it doesn't have to because you can't access it with natives
2875  // syntax.  Since both sides are internalized it is sufficient to use an
2876  // identity comparison.
2877  __ cmp(temp, class_name);
2878  // End with the answer in the z flag.
2879}
2880
2881
2882void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
2883  Register input = ToRegister(instr->value());
2884  Register temp = ToRegister(instr->temp());
2885  Register temp2 = ToRegister(instr->temp2());
2886
2887  Handle<String> class_name = instr->hydrogen()->class_name();
2888
2889  EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2890      class_name, input, temp, temp2);
2891
2892  EmitBranch(instr, equal);
2893}
2894
2895
2896void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
2897  Register reg = ToRegister(instr->value());
2898  __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
2899  EmitBranch(instr, equal);
2900}
2901
2902
2903void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2904  // Object and function are in fixed registers defined by the stub.
2905  DCHECK(ToRegister(instr->context()).is(esi));
2906  InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters);
2907  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2908
2909  Label true_value, done;
2910  __ test(eax, Operand(eax));
2911  __ j(zero, &true_value, Label::kNear);
2912  __ mov(ToRegister(instr->result()), factory()->false_value());
2913  __ jmp(&done, Label::kNear);
2914  __ bind(&true_value);
2915  __ mov(ToRegister(instr->result()), factory()->true_value());
2916  __ bind(&done);
2917}
2918
2919
2920void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2921  class DeferredInstanceOfKnownGlobal FINAL : public LDeferredCode {
2922   public:
2923    DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2924                                  LInstanceOfKnownGlobal* instr,
2925                                  const X87Stack& x87_stack)
2926        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
2927    virtual void Generate() OVERRIDE {
2928      codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
2929    }
2930    virtual LInstruction* instr() OVERRIDE { return instr_; }
2931    Label* map_check() { return &map_check_; }
2932   private:
2933    LInstanceOfKnownGlobal* instr_;
2934    Label map_check_;
2935  };
2936
2937  DeferredInstanceOfKnownGlobal* deferred;
2938  deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_);
2939
2940  Label done, false_result;
2941  Register object = ToRegister(instr->value());
2942  Register temp = ToRegister(instr->temp());
2943
2944  // A Smi is not an instance of anything.
2945  __ JumpIfSmi(object, &false_result, Label::kNear);
2946
2947  // This is the inlined call site instanceof cache. The two occurences of the
2948  // hole value will be patched to the last map/result pair generated by the
2949  // instanceof stub.
2950  Label cache_miss;
2951  Register map = ToRegister(instr->temp());
2952  __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
2953  __ bind(deferred->map_check());  // Label for calculating code patching.
2954  Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
2955  __ cmp(map, Operand::ForCell(cache_cell));  // Patched to cached map.
2956  __ j(not_equal, &cache_miss, Label::kNear);
2957  __ mov(eax, factory()->the_hole_value());  // Patched to either true or false.
2958  __ jmp(&done, Label::kNear);
2959
2960  // The inlined call site cache did not match. Check for null and string
2961  // before calling the deferred code.
2962  __ bind(&cache_miss);
2963  // Null is not an instance of anything.
2964  __ cmp(object, factory()->null_value());
2965  __ j(equal, &false_result, Label::kNear);
2966
2967  // String values are not instances of anything.
2968  Condition is_string = masm_->IsObjectStringType(object, temp, temp);
2969  __ j(is_string, &false_result, Label::kNear);
2970
2971  // Go to the deferred code.
2972  __ jmp(deferred->entry());
2973
2974  __ bind(&false_result);
2975  __ mov(ToRegister(instr->result()), factory()->false_value());
2976
2977  // Here result has either true or false. Deferred code also produces true or
2978  // false object.
2979  __ bind(deferred->exit());
2980  __ bind(&done);
2981}
2982
2983
2984void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
2985                                               Label* map_check) {
2986  PushSafepointRegistersScope scope(this);
2987
2988  InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
2989  flags = static_cast<InstanceofStub::Flags>(
2990      flags | InstanceofStub::kArgsInRegisters);
2991  flags = static_cast<InstanceofStub::Flags>(
2992      flags | InstanceofStub::kCallSiteInlineCheck);
2993  flags = static_cast<InstanceofStub::Flags>(
2994      flags | InstanceofStub::kReturnTrueFalseObject);
2995  InstanceofStub stub(isolate(), flags);
2996
2997  // Get the temp register reserved by the instruction. This needs to be a
2998  // register which is pushed last by PushSafepointRegisters as top of the
2999  // stack is used to pass the offset to the location of the map check to
3000  // the stub.
3001  Register temp = ToRegister(instr->temp());
3002  DCHECK(MacroAssembler::SafepointRegisterStackIndex(temp) == 0);
3003  __ LoadHeapObject(InstanceofStub::right(), instr->function());
3004  static const int kAdditionalDelta = 13;
3005  int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
3006  __ mov(temp, Immediate(delta));
3007  __ StoreToSafepointRegisterSlot(temp, temp);
3008  CallCodeGeneric(stub.GetCode(),
3009                  RelocInfo::CODE_TARGET,
3010                  instr,
3011                  RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
3012  // Get the deoptimization index of the LLazyBailout-environment that
3013  // corresponds to this instruction.
3014  LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
3015  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
3016
3017  // Put the result value into the eax slot and restore all registers.
3018  __ StoreToSafepointRegisterSlot(eax, eax);
3019}
3020
3021
3022void LCodeGen::DoCmpT(LCmpT* instr) {
3023  Token::Value op = instr->op();
3024
3025  Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
3026  CallCode(ic, RelocInfo::CODE_TARGET, instr);
3027
3028  Condition condition = ComputeCompareCondition(op);
3029  Label true_value, done;
3030  __ test(eax, Operand(eax));
3031  __ j(condition, &true_value, Label::kNear);
3032  __ mov(ToRegister(instr->result()), factory()->false_value());
3033  __ jmp(&done, Label::kNear);
3034  __ bind(&true_value);
3035  __ mov(ToRegister(instr->result()), factory()->true_value());
3036  __ bind(&done);
3037}
3038
3039
3040void LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) {
3041  int extra_value_count = dynamic_frame_alignment ? 2 : 1;
3042
3043  if (instr->has_constant_parameter_count()) {
3044    int parameter_count = ToInteger32(instr->constant_parameter_count());
3045    if (dynamic_frame_alignment && FLAG_debug_code) {
3046      __ cmp(Operand(esp,
3047                     (parameter_count + extra_value_count) * kPointerSize),
3048             Immediate(kAlignmentZapValue));
3049      __ Assert(equal, kExpectedAlignmentMarker);
3050    }
3051    __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx);
3052  } else {
3053    Register reg = ToRegister(instr->parameter_count());
3054    // The argument count parameter is a smi
3055    __ SmiUntag(reg);
3056    Register return_addr_reg = reg.is(ecx) ? ebx : ecx;
3057    if (dynamic_frame_alignment && FLAG_debug_code) {
3058      DCHECK(extra_value_count == 2);
3059      __ cmp(Operand(esp, reg, times_pointer_size,
3060                     extra_value_count * kPointerSize),
3061             Immediate(kAlignmentZapValue));
3062      __ Assert(equal, kExpectedAlignmentMarker);
3063    }
3064
3065    // emit code to restore stack based on instr->parameter_count()
3066    __ pop(return_addr_reg);  // save return address
3067    if (dynamic_frame_alignment) {
3068      __ inc(reg);  // 1 more for alignment
3069    }
3070    __ shl(reg, kPointerSizeLog2);
3071    __ add(esp, reg);
3072    __ jmp(return_addr_reg);
3073  }
3074}
3075
3076
3077void LCodeGen::DoReturn(LReturn* instr) {
3078  if (FLAG_trace && info()->IsOptimizing()) {
3079    // Preserve the return value on the stack and rely on the runtime call
3080    // to return the value in the same register.  We're leaving the code
3081    // managed by the register allocator and tearing down the frame, it's
3082    // safe to write to the context register.
3083    __ push(eax);
3084    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3085    __ CallRuntime(Runtime::kTraceExit, 1);
3086  }
3087  if (dynamic_frame_alignment_) {
3088    // Fetch the state of the dynamic frame alignment.
3089    __ mov(edx, Operand(ebp,
3090      JavaScriptFrameConstants::kDynamicAlignmentStateOffset));
3091  }
3092  int no_frame_start = -1;
3093  if (NeedsEagerFrame()) {
3094    __ mov(esp, ebp);
3095    __ pop(ebp);
3096    no_frame_start = masm_->pc_offset();
3097  }
3098  if (dynamic_frame_alignment_) {
3099    Label no_padding;
3100    __ cmp(edx, Immediate(kNoAlignmentPadding));
3101    __ j(equal, &no_padding, Label::kNear);
3102
3103    EmitReturn(instr, true);
3104    __ bind(&no_padding);
3105  }
3106
3107  EmitReturn(instr, false);
3108  if (no_frame_start != -1) {
3109    info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
3110  }
3111}
3112
3113
3114void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
3115  Register result = ToRegister(instr->result());
3116  __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle()));
3117  if (instr->hydrogen()->RequiresHoleCheck()) {
3118    __ cmp(result, factory()->the_hole_value());
3119    DeoptimizeIf(equal, instr, "hole");
3120  }
3121}
3122
3123
3124template <class T>
3125void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
3126  DCHECK(FLAG_vector_ics);
3127  Register vector = ToRegister(instr->temp_vector());
3128  DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
3129  __ mov(vector, instr->hydrogen()->feedback_vector());
3130  // No need to allocate this register.
3131  DCHECK(VectorLoadICDescriptor::SlotRegister().is(eax));
3132  __ mov(VectorLoadICDescriptor::SlotRegister(),
3133         Immediate(Smi::FromInt(instr->hydrogen()->slot())));
3134}
3135
3136
3137void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
3138  DCHECK(ToRegister(instr->context()).is(esi));
3139  DCHECK(ToRegister(instr->global_object())
3140             .is(LoadDescriptor::ReceiverRegister()));
3141  DCHECK(ToRegister(instr->result()).is(eax));
3142
3143  __ mov(LoadDescriptor::NameRegister(), instr->name());
3144  if (FLAG_vector_ics) {
3145    EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
3146  }
3147  ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
3148  Handle<Code> ic = CodeFactory::LoadIC(isolate(), mode).code();
3149  CallCode(ic, RelocInfo::CODE_TARGET, instr);
3150}
3151
3152
3153void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
3154  Register value = ToRegister(instr->value());
3155  Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle();
3156
3157  // If the cell we are storing to contains the hole it could have
3158  // been deleted from the property dictionary. In that case, we need
3159  // to update the property details in the property dictionary to mark
3160  // it as no longer deleted. We deoptimize in that case.
3161  if (instr->hydrogen()->RequiresHoleCheck()) {
3162    __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
3163    DeoptimizeIf(equal, instr, "hole");
3164  }
3165
3166  // Store the value.
3167  __ mov(Operand::ForCell(cell_handle), value);
3168  // Cells are always rescanned, so no write barrier here.
3169}
3170
3171
3172void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3173  Register context = ToRegister(instr->context());
3174  Register result = ToRegister(instr->result());
3175  __ mov(result, ContextOperand(context, instr->slot_index()));
3176
3177  if (instr->hydrogen()->RequiresHoleCheck()) {
3178    __ cmp(result, factory()->the_hole_value());
3179    if (instr->hydrogen()->DeoptimizesOnHole()) {
3180      DeoptimizeIf(equal, instr, "hole");
3181    } else {
3182      Label is_not_hole;
3183      __ j(not_equal, &is_not_hole, Label::kNear);
3184      __ mov(result, factory()->undefined_value());
3185      __ bind(&is_not_hole);
3186    }
3187  }
3188}
3189
3190
3191void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3192  Register context = ToRegister(instr->context());
3193  Register value = ToRegister(instr->value());
3194
3195  Label skip_assignment;
3196
3197  Operand target = ContextOperand(context, instr->slot_index());
3198  if (instr->hydrogen()->RequiresHoleCheck()) {
3199    __ cmp(target, factory()->the_hole_value());
3200    if (instr->hydrogen()->DeoptimizesOnHole()) {
3201      DeoptimizeIf(equal, instr, "hole");
3202    } else {
3203      __ j(not_equal, &skip_assignment, Label::kNear);
3204    }
3205  }
3206
3207  __ mov(target, value);
3208  if (instr->hydrogen()->NeedsWriteBarrier()) {
3209    SmiCheck check_needed =
3210        instr->hydrogen()->value()->type().IsHeapObject()
3211            ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3212    Register temp = ToRegister(instr->temp());
3213    int offset = Context::SlotOffset(instr->slot_index());
3214    __ RecordWriteContextSlot(context, offset, value, temp, kSaveFPRegs,
3215                              EMIT_REMEMBERED_SET, check_needed);
3216  }
3217
3218  __ bind(&skip_assignment);
3219}
3220
3221
3222void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
3223  HObjectAccess access = instr->hydrogen()->access();
3224  int offset = access.offset();
3225
3226  if (access.IsExternalMemory()) {
3227    Register result = ToRegister(instr->result());
3228    MemOperand operand = instr->object()->IsConstantOperand()
3229        ? MemOperand::StaticVariable(ToExternalReference(
3230                LConstantOperand::cast(instr->object())))
3231        : MemOperand(ToRegister(instr->object()), offset);
3232    __ Load(result, operand, access.representation());
3233    return;
3234  }
3235
3236  Register object = ToRegister(instr->object());
3237  if (instr->hydrogen()->representation().IsDouble()) {
3238    X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
3239    return;
3240  }
3241
3242  Register result = ToRegister(instr->result());
3243  if (!access.IsInobject()) {
3244    __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
3245    object = result;
3246  }
3247  __ Load(result, FieldOperand(object, offset), access.representation());
3248}
3249
3250
3251void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
3252  DCHECK(!operand->IsDoubleRegister());
3253  if (operand->IsConstantOperand()) {
3254    Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
3255    AllowDeferredHandleDereference smi_check;
3256    if (object->IsSmi()) {
3257      __ Push(Handle<Smi>::cast(object));
3258    } else {
3259      __ PushHeapObject(Handle<HeapObject>::cast(object));
3260    }
3261  } else if (operand->IsRegister()) {
3262    __ push(ToRegister(operand));
3263  } else {
3264    __ push(ToOperand(operand));
3265  }
3266}
3267
3268
3269void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
3270  DCHECK(ToRegister(instr->context()).is(esi));
3271  DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3272  DCHECK(ToRegister(instr->result()).is(eax));
3273
3274  __ mov(LoadDescriptor::NameRegister(), instr->name());
3275  if (FLAG_vector_ics) {
3276    EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
3277  }
3278  Handle<Code> ic = CodeFactory::LoadIC(isolate(), NOT_CONTEXTUAL).code();
3279  CallCode(ic, RelocInfo::CODE_TARGET, instr);
3280}
3281
3282
3283void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
3284  Register function = ToRegister(instr->function());
3285  Register temp = ToRegister(instr->temp());
3286  Register result = ToRegister(instr->result());
3287
3288  // Get the prototype or initial map from the function.
3289  __ mov(result,
3290         FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3291
3292  // Check that the function has a prototype or an initial map.
3293  __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
3294  DeoptimizeIf(equal, instr, "hole");
3295
3296  // If the function does not have an initial map, we're done.
3297  Label done;
3298  __ CmpObjectType(result, MAP_TYPE, temp);
3299  __ j(not_equal, &done, Label::kNear);
3300
3301  // Get the prototype from the initial map.
3302  __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
3303
3304  // All done.
3305  __ bind(&done);
3306}
3307
3308
3309void LCodeGen::DoLoadRoot(LLoadRoot* instr) {
3310  Register result = ToRegister(instr->result());
3311  __ LoadRoot(result, instr->index());
3312}
3313
3314
3315void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
3316  Register arguments = ToRegister(instr->arguments());
3317  Register result = ToRegister(instr->result());
3318  if (instr->length()->IsConstantOperand() &&
3319      instr->index()->IsConstantOperand()) {
3320    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
3321    int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
3322    int index = (const_length - const_index) + 1;
3323    __ mov(result, Operand(arguments, index * kPointerSize));
3324  } else {
3325    Register length = ToRegister(instr->length());
3326    Operand index = ToOperand(instr->index());
3327    // There are two words between the frame pointer and the last argument.
3328    // Subtracting from length accounts for one of them add one more.
3329    __ sub(length, index);
3330    __ mov(result, Operand(arguments, length, times_4, kPointerSize));
3331  }
3332}
3333
3334
3335void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
3336  ElementsKind elements_kind = instr->elements_kind();
3337  LOperand* key = instr->key();
3338  if (!key->IsConstantOperand() &&
3339      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
3340                                  elements_kind)) {
3341    __ SmiUntag(ToRegister(key));
3342  }
3343  Operand operand(BuildFastArrayOperand(
3344      instr->elements(),
3345      key,
3346      instr->hydrogen()->key()->representation(),
3347      elements_kind,
3348      instr->base_offset()));
3349  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
3350      elements_kind == FLOAT32_ELEMENTS) {
3351    X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
3352  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
3353             elements_kind == FLOAT64_ELEMENTS) {
3354    X87Mov(ToX87Register(instr->result()), operand);
3355  } else {
3356    Register result(ToRegister(instr->result()));
3357    switch (elements_kind) {
3358      case EXTERNAL_INT8_ELEMENTS:
3359      case INT8_ELEMENTS:
3360        __ movsx_b(result, operand);
3361        break;
3362      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
3363      case EXTERNAL_UINT8_ELEMENTS:
3364      case UINT8_ELEMENTS:
3365      case UINT8_CLAMPED_ELEMENTS:
3366        __ movzx_b(result, operand);
3367        break;
3368      case EXTERNAL_INT16_ELEMENTS:
3369      case INT16_ELEMENTS:
3370        __ movsx_w(result, operand);
3371        break;
3372      case EXTERNAL_UINT16_ELEMENTS:
3373      case UINT16_ELEMENTS:
3374        __ movzx_w(result, operand);
3375        break;
3376      case EXTERNAL_INT32_ELEMENTS:
3377      case INT32_ELEMENTS:
3378        __ mov(result, operand);
3379        break;
3380      case EXTERNAL_UINT32_ELEMENTS:
3381      case UINT32_ELEMENTS:
3382        __ mov(result, operand);
3383        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3384          __ test(result, Operand(result));
3385          DeoptimizeIf(negative, instr, "negative value");
3386        }
3387        break;
3388      case EXTERNAL_FLOAT32_ELEMENTS:
3389      case EXTERNAL_FLOAT64_ELEMENTS:
3390      case FLOAT32_ELEMENTS:
3391      case FLOAT64_ELEMENTS:
3392      case FAST_SMI_ELEMENTS:
3393      case FAST_ELEMENTS:
3394      case FAST_DOUBLE_ELEMENTS:
3395      case FAST_HOLEY_SMI_ELEMENTS:
3396      case FAST_HOLEY_ELEMENTS:
3397      case FAST_HOLEY_DOUBLE_ELEMENTS:
3398      case DICTIONARY_ELEMENTS:
3399      case SLOPPY_ARGUMENTS_ELEMENTS:
3400        UNREACHABLE();
3401        break;
3402    }
3403  }
3404}
3405
3406
3407void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
3408  if (instr->hydrogen()->RequiresHoleCheck()) {
3409    Operand hole_check_operand = BuildFastArrayOperand(
3410        instr->elements(), instr->key(),
3411        instr->hydrogen()->key()->representation(),
3412        FAST_DOUBLE_ELEMENTS,
3413        instr->base_offset() + sizeof(kHoleNanLower32));
3414    __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
3415    DeoptimizeIf(equal, instr, "hole");
3416  }
3417
3418  Operand double_load_operand = BuildFastArrayOperand(
3419      instr->elements(),
3420      instr->key(),
3421      instr->hydrogen()->key()->representation(),
3422      FAST_DOUBLE_ELEMENTS,
3423      instr->base_offset());
3424  X87Mov(ToX87Register(instr->result()), double_load_operand);
3425}
3426
3427
3428void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3429  Register result = ToRegister(instr->result());
3430
3431  // Load the result.
3432  __ mov(result,
3433         BuildFastArrayOperand(instr->elements(), instr->key(),
3434                               instr->hydrogen()->key()->representation(),
3435                               FAST_ELEMENTS, instr->base_offset()));
3436
3437  // Check for the hole value.
3438  if (instr->hydrogen()->RequiresHoleCheck()) {
3439    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3440      __ test(result, Immediate(kSmiTagMask));
3441      DeoptimizeIf(not_equal, instr, "not a Smi");
3442    } else {
3443      __ cmp(result, factory()->the_hole_value());
3444      DeoptimizeIf(equal, instr, "hole");
3445    }
3446  }
3447}
3448
3449
3450void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3451  if (instr->is_typed_elements()) {
3452    DoLoadKeyedExternalArray(instr);
3453  } else if (instr->hydrogen()->representation().IsDouble()) {
3454    DoLoadKeyedFixedDoubleArray(instr);
3455  } else {
3456    DoLoadKeyedFixedArray(instr);
3457  }
3458}
3459
3460
3461Operand LCodeGen::BuildFastArrayOperand(
3462    LOperand* elements_pointer,
3463    LOperand* key,
3464    Representation key_representation,
3465    ElementsKind elements_kind,
3466    uint32_t base_offset) {
3467  Register elements_pointer_reg = ToRegister(elements_pointer);
3468  int element_shift_size = ElementsKindToShiftSize(elements_kind);
3469  int shift_size = element_shift_size;
3470  if (key->IsConstantOperand()) {
3471    int constant_value = ToInteger32(LConstantOperand::cast(key));
3472    if (constant_value & 0xF0000000) {
3473      Abort(kArrayIndexConstantValueTooBig);
3474    }
3475    return Operand(elements_pointer_reg,
3476                   ((constant_value) << shift_size)
3477                       + base_offset);
3478  } else {
3479    // Take the tag bit into account while computing the shift size.
3480    if (key_representation.IsSmi() && (shift_size >= 1)) {
3481      shift_size -= kSmiTagSize;
3482    }
3483    ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
3484    return Operand(elements_pointer_reg,
3485                   ToRegister(key),
3486                   scale_factor,
3487                   base_offset);
3488  }
3489}
3490
3491
3492void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
3493  DCHECK(ToRegister(instr->context()).is(esi));
3494  DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
3495  DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));
3496
3497  if (FLAG_vector_ics) {
3498    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
3499  }
3500
3501  Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
3502  CallCode(ic, RelocInfo::CODE_TARGET, instr);
3503}
3504
3505
3506void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
3507  Register result = ToRegister(instr->result());
3508
3509  if (instr->hydrogen()->from_inlined()) {
3510    __ lea(result, Operand(esp, -2 * kPointerSize));
3511  } else {
3512    // Check for arguments adapter frame.
3513    Label done, adapted;
3514    __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3515    __ mov(result, Operand(result, StandardFrameConstants::kContextOffset));
3516    __ cmp(Operand(result),
3517           Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
3518    __ j(equal, &adapted, Label::kNear);
3519
3520    // No arguments adaptor frame.
3521    __ mov(result, Operand(ebp));
3522    __ jmp(&done, Label::kNear);
3523
3524    // Arguments adaptor frame present.
3525    __ bind(&adapted);
3526    __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3527
3528    // Result is the frame pointer for the frame if not adapted and for the real
3529    // frame below the adaptor frame if adapted.
3530    __ bind(&done);
3531  }
3532}
3533
3534
3535void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
3536  Operand elem = ToOperand(instr->elements());
3537  Register result = ToRegister(instr->result());
3538
3539  Label done;
3540
3541  // If no arguments adaptor frame the number of arguments is fixed.
3542  __ cmp(ebp, elem);
3543  __ mov(result, Immediate(scope()->num_parameters()));
3544  __ j(equal, &done, Label::kNear);
3545
3546  // Arguments adaptor frame present. Get argument length from there.
3547  __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
3548  __ mov(result, Operand(result,
3549                         ArgumentsAdaptorFrameConstants::kLengthOffset));
3550  __ SmiUntag(result);
3551
3552  // Argument length is in result register.
3553  __ bind(&done);
3554}
3555
3556
3557void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
3558  Register receiver = ToRegister(instr->receiver());
3559  Register function = ToRegister(instr->function());
3560
3561  // If the receiver is null or undefined, we have to pass the global
3562  // object as a receiver to normal functions. Values have to be
3563  // passed unchanged to builtins and strict-mode functions.
3564  Label receiver_ok, global_object;
3565  Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3566  Register scratch = ToRegister(instr->temp());
3567
3568  if (!instr->hydrogen()->known_function()) {
3569    // Do not transform the receiver to object for strict mode
3570    // functions.
3571    __ mov(scratch,
3572           FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
3573    __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
3574              1 << SharedFunctionInfo::kStrictModeBitWithinByte);
3575    __ j(not_equal, &receiver_ok, dist);
3576
3577    // Do not transform the receiver to object for builtins.
3578    __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
3579              1 << SharedFunctionInfo::kNativeBitWithinByte);
3580    __ j(not_equal, &receiver_ok, dist);
3581  }
3582
3583  // Normal function. Replace undefined or null with global receiver.
3584  __ cmp(receiver, factory()->null_value());
3585  __ j(equal, &global_object, Label::kNear);
3586  __ cmp(receiver, factory()->undefined_value());
3587  __ j(equal, &global_object, Label::kNear);
3588
3589  // The receiver should be a JS object.
3590  __ test(receiver, Immediate(kSmiTagMask));
3591  DeoptimizeIf(equal, instr, "Smi");
3592  __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
3593  DeoptimizeIf(below, instr, "not a JavaScript object");
3594
3595  __ jmp(&receiver_ok, Label::kNear);
3596  __ bind(&global_object);
3597  __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
3598  const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
3599  __ mov(receiver, Operand(receiver, global_offset));
3600  const int proxy_offset = GlobalObject::kGlobalProxyOffset;
3601  __ mov(receiver, FieldOperand(receiver, proxy_offset));
3602  __ bind(&receiver_ok);
3603}
3604
3605
3606void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3607  Register receiver = ToRegister(instr->receiver());
3608  Register function = ToRegister(instr->function());
3609  Register length = ToRegister(instr->length());
3610  Register elements = ToRegister(instr->elements());
3611  DCHECK(receiver.is(eax));  // Used for parameter count.
3612  DCHECK(function.is(edi));  // Required by InvokeFunction.
3613  DCHECK(ToRegister(instr->result()).is(eax));
3614
3615  // Copy the arguments to this function possibly from the
3616  // adaptor frame below it.
3617  const uint32_t kArgumentsLimit = 1 * KB;
3618  __ cmp(length, kArgumentsLimit);
3619  DeoptimizeIf(above, instr, "too many arguments");
3620
3621  __ push(receiver);
3622  __ mov(receiver, length);
3623
3624  // Loop through the arguments pushing them onto the execution
3625  // stack.
3626  Label invoke, loop;
3627  // length is a small non-negative integer, due to the test above.
3628  __ test(length, Operand(length));
3629  __ j(zero, &invoke, Label::kNear);
3630  __ bind(&loop);
3631  __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
3632  __ dec(length);
3633  __ j(not_zero, &loop);
3634
3635  // Invoke the function.
3636  __ bind(&invoke);
3637  DCHECK(instr->HasPointerMap());
3638  LPointerMap* pointers = instr->pointer_map();
3639  SafepointGenerator safepoint_generator(
3640      this, pointers, Safepoint::kLazyDeopt);
3641  ParameterCount actual(eax);
3642  __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
3643}
3644
3645
3646void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
3647  __ int3();
3648}
3649
3650
3651void LCodeGen::DoPushArgument(LPushArgument* instr) {
3652  LOperand* argument = instr->value();
3653  EmitPushTaggedOperand(argument);
3654}
3655
3656
3657void LCodeGen::DoDrop(LDrop* instr) {
3658  __ Drop(instr->count());
3659}
3660
3661
3662void LCodeGen::DoThisFunction(LThisFunction* instr) {
3663  Register result = ToRegister(instr->result());
3664  __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
3665}
3666
3667
3668void LCodeGen::DoContext(LContext* instr) {
3669  Register result = ToRegister(instr->result());
3670  if (info()->IsOptimizing()) {
3671    __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
3672  } else {
3673    // If there is no frame, the context must be in esi.
3674    DCHECK(result.is(esi));
3675  }
3676}
3677
3678
3679void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
3680  DCHECK(ToRegister(instr->context()).is(esi));
3681  __ push(esi);  // The context is the first argument.
3682  __ push(Immediate(instr->hydrogen()->pairs()));
3683  __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags())));
3684  CallRuntime(Runtime::kDeclareGlobals, 3, instr);
3685}
3686
3687
3688void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
3689                                 int formal_parameter_count,
3690                                 int arity,
3691                                 LInstruction* instr,
3692                                 EDIState edi_state) {
3693  bool dont_adapt_arguments =
3694      formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
3695  bool can_invoke_directly =
3696      dont_adapt_arguments || formal_parameter_count == arity;
3697
3698  if (can_invoke_directly) {
3699    if (edi_state == EDI_UNINITIALIZED) {
3700      __ LoadHeapObject(edi, function);
3701    }
3702
3703    // Change context.
3704    __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
3705
3706    // Set eax to arguments count if adaption is not needed. Assumes that eax
3707    // is available to write to at this point.
3708    if (dont_adapt_arguments) {
3709      __ mov(eax, arity);
3710    }
3711
3712    // Invoke function directly.
3713    if (function.is_identical_to(info()->closure())) {
3714      __ CallSelf();
3715    } else {
3716      __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
3717    }
3718    RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3719  } else {
3720    // We need to adapt arguments.
3721    LPointerMap* pointers = instr->pointer_map();
3722    SafepointGenerator generator(
3723        this, pointers, Safepoint::kLazyDeopt);
3724    ParameterCount count(arity);
3725    ParameterCount expected(formal_parameter_count);
3726    __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator);
3727  }
3728}
3729
3730
3731void LCodeGen::DoTailCallThroughMegamorphicCache(
3732    LTailCallThroughMegamorphicCache* instr) {
3733  Register receiver = ToRegister(instr->receiver());
3734  Register name = ToRegister(instr->name());
3735  DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
3736  DCHECK(name.is(LoadDescriptor::NameRegister()));
3737
3738  Register scratch = ebx;
3739  Register extra = eax;
3740  DCHECK(!scratch.is(receiver) && !scratch.is(name));
3741  DCHECK(!extra.is(receiver) && !extra.is(name));
3742
3743  // Important for the tail-call.
3744  bool must_teardown_frame = NeedsEagerFrame();
3745
3746  // The probe will tail call to a handler if found.
3747  isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
3748                                         must_teardown_frame, receiver, name,
3749                                         scratch, extra);
3750
3751  // Tail call to miss if we ended up here.
3752  if (must_teardown_frame) __ leave();
3753  LoadIC::GenerateMiss(masm());
3754}
3755
3756
3757void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
3758  DCHECK(ToRegister(instr->result()).is(eax));
3759
3760  LPointerMap* pointers = instr->pointer_map();
3761  SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
3762
3763  if (instr->target()->IsConstantOperand()) {
3764    LConstantOperand* target = LConstantOperand::cast(instr->target());
3765    Handle<Code> code = Handle<Code>::cast(ToHandle(target));
3766    generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
3767    __ call(code, RelocInfo::CODE_TARGET);
3768  } else {
3769    DCHECK(instr->target()->IsRegister());
3770    Register target = ToRegister(instr->target());
3771    generator.BeforeCall(__ CallSize(Operand(target)));
3772    __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
3773    __ call(target);
3774  }
3775  generator.AfterCall();
3776}
3777
3778
3779void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
3780  DCHECK(ToRegister(instr->function()).is(edi));
3781  DCHECK(ToRegister(instr->result()).is(eax));
3782
3783  if (instr->hydrogen()->pass_argument_count()) {
3784    __ mov(eax, instr->arity());
3785  }
3786
3787  // Change context.
3788  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
3789
3790  bool is_self_call = false;
3791  if (instr->hydrogen()->function()->IsConstant()) {
3792    HConstant* fun_const = HConstant::cast(instr->hydrogen()->function());
3793    Handle<JSFunction> jsfun =
3794      Handle<JSFunction>::cast(fun_const->handle(isolate()));
3795    is_self_call = jsfun.is_identical_to(info()->closure());
3796  }
3797
3798  if (is_self_call) {
3799    __ CallSelf();
3800  } else {
3801    __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
3802  }
3803
3804  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
3805}
3806
3807
3808void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3809  Register input_reg = ToRegister(instr->value());
3810  __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3811         factory()->heap_number_map());
3812  DeoptimizeIf(not_equal, instr, "not a heap number");
3813
3814  Label slow, allocated, done;
3815  Register tmp = input_reg.is(eax) ? ecx : eax;
3816  Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;
3817
3818  // Preserve the value of all registers.
3819  PushSafepointRegistersScope scope(this);
3820
3821  __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3822  // Check the sign of the argument. If the argument is positive, just
3823  // return it. We do not need to patch the stack since |input| and
3824  // |result| are the same register and |input| will be restored
3825  // unchanged by popping safepoint registers.
3826  __ test(tmp, Immediate(HeapNumber::kSignMask));
3827  __ j(zero, &done, Label::kNear);
3828
3829  __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
3830  __ jmp(&allocated, Label::kNear);
3831
3832  // Slow case: Call the runtime system to do the number allocation.
3833  __ bind(&slow);
3834  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
3835                          instr, instr->context());
3836  // Set the pointer to the new heap number in tmp.
3837  if (!tmp.is(eax)) __ mov(tmp, eax);
3838  // Restore input_reg after call to runtime.
3839  __ LoadFromSafepointRegisterSlot(input_reg, input_reg);
3840
3841  __ bind(&allocated);
3842  __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3843  __ and_(tmp2, ~HeapNumber::kSignMask);
3844  __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
3845  __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
3846  __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
3847  __ StoreToSafepointRegisterSlot(input_reg, tmp);
3848
3849  __ bind(&done);
3850}
3851
3852
3853void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3854  Register input_reg = ToRegister(instr->value());
3855  __ test(input_reg, Operand(input_reg));
3856  Label is_positive;
3857  __ j(not_sign, &is_positive, Label::kNear);
3858  __ neg(input_reg);  // Sets flags.
3859  DeoptimizeIf(negative, instr, "overflow");
3860  __ bind(&is_positive);
3861}
3862
3863
3864void LCodeGen::DoMathAbs(LMathAbs* instr) {
3865  // Class for deferred case.
3866  class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3867   public:
3868    DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3869                                    LMathAbs* instr,
3870                                    const X87Stack& x87_stack)
3871        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
3872    virtual void Generate() OVERRIDE {
3873      codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3874    }
3875    virtual LInstruction* instr() OVERRIDE { return instr_; }
3876   private:
3877    LMathAbs* instr_;
3878  };
3879
3880  DCHECK(instr->value()->Equals(instr->result()));
3881  Representation r = instr->hydrogen()->value()->representation();
3882
3883  if (r.IsDouble()) {
3884    X87Register value = ToX87Register(instr->value());
3885    X87Fxch(value);
3886    __ fabs();
3887  } else if (r.IsSmiOrInteger32()) {
3888    EmitIntegerMathAbs(instr);
3889  } else {  // Tagged case.
3890    DeferredMathAbsTaggedHeapNumber* deferred =
3891        new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_);
3892    Register input_reg = ToRegister(instr->value());
3893    // Smi check.
3894    __ JumpIfNotSmi(input_reg, deferred->entry());
3895    EmitIntegerMathAbs(instr);
3896    __ bind(deferred->exit());
3897  }
3898}
3899
3900
3901void LCodeGen::DoMathFloor(LMathFloor* instr) {
3902  Register output_reg = ToRegister(instr->result());
3903  X87Register input_reg = ToX87Register(instr->value());
3904  X87Fxch(input_reg);
3905
3906  Label not_minus_zero, done;
3907  // Deoptimize on unordered.
3908  __ fldz();
3909  __ fld(1);
3910  __ FCmp();
3911  DeoptimizeIf(parity_even, instr, "NaN");
3912  __ j(below, &not_minus_zero, Label::kNear);
3913
3914  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3915    // Check for negative zero.
3916    __ j(not_equal, &not_minus_zero, Label::kNear);
3917    // +- 0.0.
3918    __ fld(0);
3919    __ FXamSign();
3920    DeoptimizeIf(not_zero, instr, "minus zero");
3921    __ Move(output_reg, Immediate(0));
3922    __ jmp(&done, Label::kFar);
3923  }
3924
3925  // Positive input.
3926  // rc=01B, round down.
3927  __ bind(&not_minus_zero);
3928  __ fnclex();
3929  __ X87SetRC(0x0400);
3930  __ sub(esp, Immediate(kPointerSize));
3931  __ fist_s(Operand(esp, 0));
3932  __ pop(output_reg);
3933  __ X87CheckIA();
3934  DeoptimizeIf(equal, instr, "overflow");
3935  __ fnclex();
3936  __ X87SetRC(0x0000);
3937  __ bind(&done);
3938}
3939
3940
3941void LCodeGen::DoMathRound(LMathRound* instr) {
3942  X87Register input_reg = ToX87Register(instr->value());
3943  Register result = ToRegister(instr->result());
3944  X87Fxch(input_reg);
3945  Label below_one_half, below_minus_one_half, done;
3946
3947  ExternalReference one_half = ExternalReference::address_of_one_half();
3948  ExternalReference minus_one_half =
3949      ExternalReference::address_of_minus_one_half();
3950
3951  __ fld_d(Operand::StaticVariable(one_half));
3952  __ fld(1);
3953  __ FCmp();
3954  __ j(carry, &below_one_half);
3955
3956  // Use rounds towards zero, since 0.5 <= x, we use floor(0.5 + x)
3957  __ fld(0);
3958  __ fadd_d(Operand::StaticVariable(one_half));
3959  // rc=11B, round toward zero.
3960  __ X87SetRC(0x0c00);
3961  __ sub(esp, Immediate(kPointerSize));
3962  // Clear exception bits.
3963  __ fnclex();
3964  __ fistp_s(MemOperand(esp, 0));
3965  // Check overflow.
3966  __ X87CheckIA();
3967  __ pop(result);
3968  DeoptimizeIf(equal, instr, "conversion overflow");
3969  __ fnclex();
3970  // Restore round mode.
3971  __ X87SetRC(0x0000);
3972  __ jmp(&done);
3973
3974  __ bind(&below_one_half);
3975  __ fld_d(Operand::StaticVariable(minus_one_half));
3976  __ fld(1);
3977  __ FCmp();
3978  __ j(carry, &below_minus_one_half);
3979  // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3980  // we can ignore the difference between a result of -0 and +0.
3981  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3982    // If the sign is positive, we return +0.
3983    __ fld(0);
3984    __ FXamSign();
3985    DeoptimizeIf(not_zero, instr, "minus zero");
3986  }
3987  __ Move(result, Immediate(0));
3988  __ jmp(&done);
3989
3990  __ bind(&below_minus_one_half);
3991  __ fld(0);
3992  __ fadd_d(Operand::StaticVariable(one_half));
3993  // rc=01B, round down.
3994  __ X87SetRC(0x0400);
3995  __ sub(esp, Immediate(kPointerSize));
3996  // Clear exception bits.
3997  __ fnclex();
3998  __ fistp_s(MemOperand(esp, 0));
3999  // Check overflow.
4000  __ X87CheckIA();
4001  __ pop(result);
4002  DeoptimizeIf(equal, instr, "conversion overflow");
4003  __ fnclex();
4004  // Restore round mode.
4005  __ X87SetRC(0x0000);
4006
4007  __ bind(&done);
4008}
4009
4010
4011void LCodeGen::DoMathFround(LMathFround* instr) {
4012  X87Register input_reg = ToX87Register(instr->value());
4013  X87Fxch(input_reg);
4014  __ sub(esp, Immediate(kPointerSize));
4015  __ fstp_s(MemOperand(esp, 0));
4016  X87Fld(MemOperand(esp, 0), kX87FloatOperand);
4017  __ add(esp, Immediate(kPointerSize));
4018}
4019
4020
4021void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
4022  X87Register input = ToX87Register(instr->value());
4023  X87Register result_reg = ToX87Register(instr->result());
4024  Register temp_result = ToRegister(instr->temp1());
4025  Register temp = ToRegister(instr->temp2());
4026  Label slow, done, smi, finish;
4027  DCHECK(result_reg.is(input));
4028
4029  // Store input into Heap number and call runtime function kMathExpRT.
4030  if (FLAG_inline_new) {
4031    __ AllocateHeapNumber(temp_result, temp, no_reg, &slow);
4032    __ jmp(&done, Label::kNear);
4033  }
4034
4035  // Slow case: Call the runtime system to do the number allocation.
4036  __ bind(&slow);
4037  {
4038    // TODO(3095996): Put a valid pointer value in the stack slot where the
4039    // result register is stored, as this register is in the pointer map, but
4040    // contains an integer value.
4041    __ Move(temp_result, Immediate(0));
4042
4043    // Preserve the value of all registers.
4044    PushSafepointRegistersScope scope(this);
4045
4046    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4047    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4048    RecordSafepointWithRegisters(
4049       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4050    __ StoreToSafepointRegisterSlot(temp_result, eax);
4051  }
4052  __ bind(&done);
4053  X87LoadForUsage(input);
4054  __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
4055
4056  {
4057    // Preserve the value of all registers.
4058    PushSafepointRegistersScope scope(this);
4059
4060    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4061    __ push(temp_result);
4062    __ CallRuntimeSaveDoubles(Runtime::kMathSqrtRT);
4063    RecordSafepointWithRegisters(instr->pointer_map(), 1,
4064                                 Safepoint::kNoLazyDeopt);
4065    __ StoreToSafepointRegisterSlot(temp_result, eax);
4066  }
4067  X87PrepareToWrite(result_reg);
4068  // return value of MathExpRT is Smi or Heap Number.
4069  __ JumpIfSmi(temp_result, &smi);
4070  // Heap number(double)
4071  __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
4072  __ jmp(&finish);
4073  // SMI
4074  __ bind(&smi);
4075  __ SmiUntag(temp_result);
4076  __ push(temp_result);
4077  __ fild_s(MemOperand(esp, 0));
4078  __ pop(temp_result);
4079  __ bind(&finish);
4080  X87CommitWrite(result_reg);
4081}
4082
4083
4084void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
4085  X87Register input_reg = ToX87Register(instr->value());
4086  DCHECK(ToX87Register(instr->result()).is(input_reg));
4087  X87Fxch(input_reg);
4088  // Note that according to ECMA-262 15.8.2.13:
4089  // Math.pow(-Infinity, 0.5) == Infinity
4090  // Math.sqrt(-Infinity) == NaN
4091  Label done, sqrt;
4092  // Check base for -Infinity. C3 == 0, C2 == 1, C1 == 1 and C0 == 1
4093  __ fxam();
4094  __ push(eax);
4095  __ fnstsw_ax();
4096  __ and_(eax, Immediate(0x4700));
4097  __ cmp(eax, Immediate(0x0700));
4098  __ j(not_equal, &sqrt, Label::kNear);
4099  // If input is -Infinity, return Infinity.
4100  __ fchs();
4101  __ jmp(&done, Label::kNear);
4102
4103  // Square root.
4104  __ bind(&sqrt);
4105  __ fldz();
4106  __ faddp();  // Convert -0 to +0.
4107  __ fsqrt();
4108  __ bind(&done);
4109  __ pop(eax);
4110}
4111
4112
4113void LCodeGen::DoPower(LPower* instr) {
4114  Representation exponent_type = instr->hydrogen()->right()->representation();
4115  X87Register result = ToX87Register(instr->result());
4116  // Having marked this as a call, we can use any registers.
4117  X87Register base = ToX87Register(instr->left());
4118  ExternalReference one_half = ExternalReference::address_of_one_half();
4119
4120  if (exponent_type.IsSmi()) {
4121    Register exponent = ToRegister(instr->right());
4122    X87LoadForUsage(base);
4123    __ SmiUntag(exponent);
4124    __ push(exponent);
4125    __ fild_s(MemOperand(esp, 0));
4126    __ pop(exponent);
4127  } else if (exponent_type.IsTagged()) {
4128    Register exponent = ToRegister(instr->right());
4129    Register temp = exponent.is(ecx) ? eax : ecx;
4130    Label no_deopt, done;
4131    X87LoadForUsage(base);
4132    __ JumpIfSmi(exponent, &no_deopt);
4133    __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp);
4134    DeoptimizeIf(not_equal, instr, "not a heap number");
4135    // Heap number(double)
4136    __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset));
4137    __ jmp(&done);
4138    // SMI
4139    __ bind(&no_deopt);
4140    __ SmiUntag(exponent);
4141    __ push(exponent);
4142    __ fild_s(MemOperand(esp, 0));
4143    __ pop(exponent);
4144    __ bind(&done);
4145  } else if (exponent_type.IsInteger32()) {
4146    Register exponent = ToRegister(instr->right());
4147    X87LoadForUsage(base);
4148    __ push(exponent);
4149    __ fild_s(MemOperand(esp, 0));
4150    __ pop(exponent);
4151  } else {
4152    DCHECK(exponent_type.IsDouble());
4153    X87Register exponent_double = ToX87Register(instr->right());
4154    X87LoadForUsage(base, exponent_double);
4155  }
4156
4157  // FP data stack {base, exponent(TOS)}.
4158  // Handle (exponent==+-0.5 && base == -0).
4159  Label not_plus_0;
4160  __ fld(0);
4161  __ fabs();
4162  X87Fld(Operand::StaticVariable(one_half), kX87DoubleOperand);
4163  __ FCmp();
4164  __ j(parity_even, &not_plus_0, Label::kNear);  // NaN.
4165  __ j(not_equal, &not_plus_0, Label::kNear);
4166  __ fldz();
4167  // FP data stack {base, exponent(TOS), zero}.
4168  __ faddp(2);
4169  __ bind(&not_plus_0);
4170
4171  {
4172    __ PrepareCallCFunction(4, eax);
4173    __ fstp_d(MemOperand(esp, kDoubleSize));  // Exponent value.
4174    __ fstp_d(MemOperand(esp, 0));            // Base value.
4175    X87PrepareToWrite(result);
4176    __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
4177                     4);
4178    // Return value is in st(0) on ia32.
4179    X87CommitWrite(result);
4180  }
4181}
4182
4183
4184void LCodeGen::DoMathLog(LMathLog* instr) {
4185  DCHECK(instr->value()->Equals(instr->result()));
4186  X87Register input_reg = ToX87Register(instr->value());
4187  X87Fxch(input_reg);
4188
4189  Label positive, done, zero, nan_result;
4190  __ fldz();
4191  __ fld(1);
4192  __ FCmp();
4193  __ j(below, &nan_result, Label::kNear);
4194  __ j(equal, &zero, Label::kNear);
4195  // Positive input.
4196  // {input, ln2}.
4197  __ fldln2();
4198  // {ln2, input}.
4199  __ fxch();
4200  // {result}.
4201  __ fyl2x();
4202  __ jmp(&done, Label::kNear);
4203
4204  __ bind(&nan_result);
4205  ExternalReference nan =
4206      ExternalReference::address_of_canonical_non_hole_nan();
4207  X87PrepareToWrite(input_reg);
4208  __ fld_d(Operand::StaticVariable(nan));
4209  X87CommitWrite(input_reg);
4210  __ jmp(&done, Label::kNear);
4211
4212  __ bind(&zero);
4213  ExternalReference ninf = ExternalReference::address_of_negative_infinity();
4214  X87PrepareToWrite(input_reg);
4215  __ fld_d(Operand::StaticVariable(ninf));
4216  X87CommitWrite(input_reg);
4217
4218  __ bind(&done);
4219}
4220
4221
4222void LCodeGen::DoMathClz32(LMathClz32* instr) {
4223  Register input = ToRegister(instr->value());
4224  Register result = ToRegister(instr->result());
4225  Label not_zero_input;
4226  __ bsr(result, input);
4227
4228  __ j(not_zero, &not_zero_input);
4229  __ Move(result, Immediate(63));  // 63^31 == 32
4230
4231  __ bind(&not_zero_input);
4232  __ xor_(result, Immediate(31));  // for x in [0..31], 31^x == 31-x.
4233}
4234
4235
4236void LCodeGen::DoMathExp(LMathExp* instr) {
4237  X87Register input = ToX87Register(instr->value());
4238  X87Register result_reg = ToX87Register(instr->result());
4239  Register temp_result = ToRegister(instr->temp1());
4240  Register temp = ToRegister(instr->temp2());
4241  Label slow, done, smi, finish;
4242  DCHECK(result_reg.is(input));
4243
4244  // Store input into Heap number and call runtime function kMathExpRT.
4245  if (FLAG_inline_new) {
4246    __ AllocateHeapNumber(temp_result, temp, no_reg, &slow);
4247    __ jmp(&done, Label::kNear);
4248  }
4249
4250  // Slow case: Call the runtime system to do the number allocation.
4251  __ bind(&slow);
4252  {
4253    // TODO(3095996): Put a valid pointer value in the stack slot where the
4254    // result register is stored, as this register is in the pointer map, but
4255    // contains an integer value.
4256    __ Move(temp_result, Immediate(0));
4257
4258    // Preserve the value of all registers.
4259    PushSafepointRegistersScope scope(this);
4260
4261    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4262    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4263    RecordSafepointWithRegisters(instr->pointer_map(), 0,
4264                                 Safepoint::kNoLazyDeopt);
4265    __ StoreToSafepointRegisterSlot(temp_result, eax);
4266  }
4267  __ bind(&done);
4268  X87LoadForUsage(input);
4269  __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
4270
4271  {
4272    // Preserve the value of all registers.
4273    PushSafepointRegistersScope scope(this);
4274
4275    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4276    __ push(temp_result);
4277    __ CallRuntimeSaveDoubles(Runtime::kMathExpRT);
4278    RecordSafepointWithRegisters(instr->pointer_map(), 1,
4279                                 Safepoint::kNoLazyDeopt);
4280    __ StoreToSafepointRegisterSlot(temp_result, eax);
4281  }
4282  X87PrepareToWrite(result_reg);
4283  // return value of MathExpRT is Smi or Heap Number.
4284  __ JumpIfSmi(temp_result, &smi);
4285  // Heap number(double)
4286  __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
4287  __ jmp(&finish);
4288  // SMI
4289  __ bind(&smi);
4290  __ SmiUntag(temp_result);
4291  __ push(temp_result);
4292  __ fild_s(MemOperand(esp, 0));
4293  __ pop(temp_result);
4294  __ bind(&finish);
4295  X87CommitWrite(result_reg);
4296}
4297
4298
4299void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
4300  DCHECK(ToRegister(instr->context()).is(esi));
4301  DCHECK(ToRegister(instr->function()).is(edi));
4302  DCHECK(instr->HasPointerMap());
4303
4304  Handle<JSFunction> known_function = instr->hydrogen()->known_function();
4305  if (known_function.is_null()) {
4306    LPointerMap* pointers = instr->pointer_map();
4307    SafepointGenerator generator(
4308        this, pointers, Safepoint::kLazyDeopt);
4309    ParameterCount count(instr->arity());
4310    __ InvokeFunction(edi, count, CALL_FUNCTION, generator);
4311  } else {
4312    CallKnownFunction(known_function,
4313                      instr->hydrogen()->formal_parameter_count(),
4314                      instr->arity(),
4315                      instr,
4316                      EDI_CONTAINS_TARGET);
4317  }
4318}
4319
4320
4321void LCodeGen::DoCallFunction(LCallFunction* instr) {
4322  DCHECK(ToRegister(instr->context()).is(esi));
4323  DCHECK(ToRegister(instr->function()).is(edi));
4324  DCHECK(ToRegister(instr->result()).is(eax));
4325
4326  int arity = instr->arity();
4327  CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags());
4328  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4329}
4330
4331
4332void LCodeGen::DoCallNew(LCallNew* instr) {
4333  DCHECK(ToRegister(instr->context()).is(esi));
4334  DCHECK(ToRegister(instr->constructor()).is(edi));
4335  DCHECK(ToRegister(instr->result()).is(eax));
4336
4337  // No cell in ebx for construct type feedback in optimized code
4338  __ mov(ebx, isolate()->factory()->undefined_value());
4339  CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
4340  __ Move(eax, Immediate(instr->arity()));
4341  CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4342}
4343
4344
4345void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
4346  DCHECK(ToRegister(instr->context()).is(esi));
4347  DCHECK(ToRegister(instr->constructor()).is(edi));
4348  DCHECK(ToRegister(instr->result()).is(eax));
4349
4350  __ Move(eax, Immediate(instr->arity()));
4351  __ mov(ebx, isolate()->factory()->undefined_value());
4352  ElementsKind kind = instr->hydrogen()->elements_kind();
4353  AllocationSiteOverrideMode override_mode =
4354      (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
4355          ? DISABLE_ALLOCATION_SITES
4356          : DONT_OVERRIDE;
4357
4358  if (instr->arity() == 0) {
4359    ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
4360    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4361  } else if (instr->arity() == 1) {
4362    Label done;
4363    if (IsFastPackedElementsKind(kind)) {
4364      Label packed_case;
4365      // We might need a change here
4366      // look at the first argument
4367      __ mov(ecx, Operand(esp, 0));
4368      __ test(ecx, ecx);
4369      __ j(zero, &packed_case, Label::kNear);
4370
4371      ElementsKind holey_kind = GetHoleyElementsKind(kind);
4372      ArraySingleArgumentConstructorStub stub(isolate(),
4373                                              holey_kind,
4374                                              override_mode);
4375      CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4376      __ jmp(&done, Label::kNear);
4377      __ bind(&packed_case);
4378    }
4379
4380    ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
4381    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4382    __ bind(&done);
4383  } else {
4384    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
4385    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
4386  }
4387}
4388
4389
4390void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
4391  DCHECK(ToRegister(instr->context()).is(esi));
4392  CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
4393}
4394
4395
4396void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
4397  Register function = ToRegister(instr->function());
4398  Register code_object = ToRegister(instr->code_object());
4399  __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
4400  __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
4401}
4402
4403
4404void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
4405  Register result = ToRegister(instr->result());
4406  Register base = ToRegister(instr->base_object());
4407  if (instr->offset()->IsConstantOperand()) {
4408    LConstantOperand* offset = LConstantOperand::cast(instr->offset());
4409    __ lea(result, Operand(base, ToInteger32(offset)));
4410  } else {
4411    Register offset = ToRegister(instr->offset());
4412    __ lea(result, Operand(base, offset, times_1, 0));
4413  }
4414}
4415
4416
4417void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
4418  Representation representation = instr->hydrogen()->field_representation();
4419
4420  HObjectAccess access = instr->hydrogen()->access();
4421  int offset = access.offset();
4422
4423  if (access.IsExternalMemory()) {
4424    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4425    MemOperand operand = instr->object()->IsConstantOperand()
4426        ? MemOperand::StaticVariable(
4427            ToExternalReference(LConstantOperand::cast(instr->object())))
4428        : MemOperand(ToRegister(instr->object()), offset);
4429    if (instr->value()->IsConstantOperand()) {
4430      LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4431      __ mov(operand, Immediate(ToInteger32(operand_value)));
4432    } else {
4433      Register value = ToRegister(instr->value());
4434      __ Store(value, operand, representation);
4435    }
4436    return;
4437  }
4438
4439  Register object = ToRegister(instr->object());
4440  __ AssertNotSmi(object);
4441  DCHECK(!representation.IsSmi() ||
4442         !instr->value()->IsConstantOperand() ||
4443         IsSmi(LConstantOperand::cast(instr->value())));
4444  if (representation.IsDouble()) {
4445    DCHECK(access.IsInobject());
4446    DCHECK(!instr->hydrogen()->has_transition());
4447    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4448    X87Register value = ToX87Register(instr->value());
4449    X87Mov(FieldOperand(object, offset), value);
4450    return;
4451  }
4452
4453  if (instr->hydrogen()->has_transition()) {
4454    Handle<Map> transition = instr->hydrogen()->transition_map();
4455    AddDeprecationDependency(transition);
4456    __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
4457    if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
4458      Register temp = ToRegister(instr->temp());
4459      Register temp_map = ToRegister(instr->temp_map());
4460      __ mov(temp_map, transition);
4461      __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map);
4462      // Update the write barrier for the map field.
4463      __ RecordWriteForMap(object, transition, temp_map, temp, kSaveFPRegs);
4464    }
4465  }
4466
4467  // Do the store.
4468  Register write_register = object;
4469  if (!access.IsInobject()) {
4470    write_register = ToRegister(instr->temp());
4471    __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
4472  }
4473
4474  MemOperand operand = FieldOperand(write_register, offset);
4475  if (instr->value()->IsConstantOperand()) {
4476    LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4477    if (operand_value->IsRegister()) {
4478      Register value = ToRegister(operand_value);
4479      __ Store(value, operand, representation);
4480    } else if (representation.IsInteger32()) {
4481      Immediate immediate = ToImmediate(operand_value, representation);
4482      DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4483      __ mov(operand, immediate);
4484    } else {
4485      Handle<Object> handle_value = ToHandle(operand_value);
4486      DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
4487      __ mov(operand, handle_value);
4488    }
4489  } else {
4490    Register value = ToRegister(instr->value());
4491    __ Store(value, operand, representation);
4492  }
4493
4494  if (instr->hydrogen()->NeedsWriteBarrier()) {
4495    Register value = ToRegister(instr->value());
4496    Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
4497    // Update the write barrier for the object for in-object properties.
4498    __ RecordWriteField(write_register, offset, value, temp, kSaveFPRegs,
4499                        EMIT_REMEMBERED_SET,
4500                        instr->hydrogen()->SmiCheckForWriteBarrier(),
4501                        instr->hydrogen()->PointersToHereCheckForValue());
4502  }
4503}
4504
4505
4506void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4507  DCHECK(ToRegister(instr->context()).is(esi));
4508  DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4509  DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4510
4511  __ mov(StoreDescriptor::NameRegister(), instr->name());
4512  Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
4513  CallCode(ic, RelocInfo::CODE_TARGET, instr);
4514}
4515
4516
4517void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
4518  Condition cc = instr->hydrogen()->allow_equality() ? above : above_equal;
4519  if (instr->index()->IsConstantOperand()) {
4520    __ cmp(ToOperand(instr->length()),
4521           ToImmediate(LConstantOperand::cast(instr->index()),
4522                       instr->hydrogen()->length()->representation()));
4523    cc = CommuteCondition(cc);
4524  } else if (instr->length()->IsConstantOperand()) {
4525    __ cmp(ToOperand(instr->index()),
4526           ToImmediate(LConstantOperand::cast(instr->length()),
4527                       instr->hydrogen()->index()->representation()));
4528  } else {
4529    __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
4530  }
4531  if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4532    Label done;
4533    __ j(NegateCondition(cc), &done, Label::kNear);
4534    __ int3();
4535    __ bind(&done);
4536  } else {
4537    DeoptimizeIf(cc, instr, "out of bounds");
4538  }
4539}
4540
4541
4542void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4543  ElementsKind elements_kind = instr->elements_kind();
4544  LOperand* key = instr->key();
4545  if (!key->IsConstantOperand() &&
4546      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
4547                                  elements_kind)) {
4548    __ SmiUntag(ToRegister(key));
4549  }
4550  Operand operand(BuildFastArrayOperand(
4551      instr->elements(),
4552      key,
4553      instr->hydrogen()->key()->representation(),
4554      elements_kind,
4555      instr->base_offset()));
4556  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
4557      elements_kind == FLOAT32_ELEMENTS) {
4558    X87Mov(operand, ToX87Register(instr->value()), kX87FloatOperand);
4559  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
4560             elements_kind == FLOAT64_ELEMENTS) {
4561    X87Mov(operand, ToX87Register(instr->value()));
4562  } else {
4563    Register value = ToRegister(instr->value());
4564    switch (elements_kind) {
4565      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
4566      case EXTERNAL_UINT8_ELEMENTS:
4567      case EXTERNAL_INT8_ELEMENTS:
4568      case UINT8_ELEMENTS:
4569      case INT8_ELEMENTS:
4570      case UINT8_CLAMPED_ELEMENTS:
4571        __ mov_b(operand, value);
4572        break;
4573      case EXTERNAL_INT16_ELEMENTS:
4574      case EXTERNAL_UINT16_ELEMENTS:
4575      case UINT16_ELEMENTS:
4576      case INT16_ELEMENTS:
4577        __ mov_w(operand, value);
4578        break;
4579      case EXTERNAL_INT32_ELEMENTS:
4580      case EXTERNAL_UINT32_ELEMENTS:
4581      case UINT32_ELEMENTS:
4582      case INT32_ELEMENTS:
4583        __ mov(operand, value);
4584        break;
4585      case EXTERNAL_FLOAT32_ELEMENTS:
4586      case EXTERNAL_FLOAT64_ELEMENTS:
4587      case FLOAT32_ELEMENTS:
4588      case FLOAT64_ELEMENTS:
4589      case FAST_SMI_ELEMENTS:
4590      case FAST_ELEMENTS:
4591      case FAST_DOUBLE_ELEMENTS:
4592      case FAST_HOLEY_SMI_ELEMENTS:
4593      case FAST_HOLEY_ELEMENTS:
4594      case FAST_HOLEY_DOUBLE_ELEMENTS:
4595      case DICTIONARY_ELEMENTS:
4596      case SLOPPY_ARGUMENTS_ELEMENTS:
4597        UNREACHABLE();
4598        break;
4599    }
4600  }
4601}
4602
4603
4604void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4605  ExternalReference canonical_nan_reference =
4606      ExternalReference::address_of_canonical_non_hole_nan();
4607  Operand double_store_operand = BuildFastArrayOperand(
4608      instr->elements(),
4609      instr->key(),
4610      instr->hydrogen()->key()->representation(),
4611      FAST_DOUBLE_ELEMENTS,
4612      instr->base_offset());
4613
4614  // Can't use SSE2 in the serializer
4615  if (instr->hydrogen()->IsConstantHoleStore()) {
4616    // This means we should store the (double) hole. No floating point
4617    // registers required.
4618    double nan_double = FixedDoubleArray::hole_nan_as_double();
4619    uint64_t int_val = bit_cast<uint64_t, double>(nan_double);
4620    int32_t lower = static_cast<int32_t>(int_val);
4621    int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
4622
4623    __ mov(double_store_operand, Immediate(lower));
4624    Operand double_store_operand2 = BuildFastArrayOperand(
4625        instr->elements(),
4626        instr->key(),
4627        instr->hydrogen()->key()->representation(),
4628        FAST_DOUBLE_ELEMENTS,
4629        instr->base_offset() + kPointerSize);
4630    __ mov(double_store_operand2, Immediate(upper));
4631  } else {
4632    Label no_special_nan_handling;
4633    X87Register value = ToX87Register(instr->value());
4634    X87Fxch(value);
4635
4636    if (instr->NeedsCanonicalization()) {
4637      __ fld(0);
4638      __ fld(0);
4639      __ FCmp();
4640
4641      __ j(parity_odd, &no_special_nan_handling, Label::kNear);
4642      __ sub(esp, Immediate(kDoubleSize));
4643      __ fst_d(MemOperand(esp, 0));
4644      __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
4645             Immediate(kHoleNanUpper32));
4646      __ add(esp, Immediate(kDoubleSize));
4647      Label canonicalize;
4648      __ j(not_equal, &canonicalize, Label::kNear);
4649      __ jmp(&no_special_nan_handling, Label::kNear);
4650      __ bind(&canonicalize);
4651      __ fstp(0);
4652      __ fld_d(Operand::StaticVariable(canonical_nan_reference));
4653    }
4654
4655    __ bind(&no_special_nan_handling);
4656    __ fst_d(double_store_operand);
4657  }
4658}
4659
4660
4661void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4662  Register elements = ToRegister(instr->elements());
4663  Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
4664
4665  Operand operand = BuildFastArrayOperand(
4666      instr->elements(),
4667      instr->key(),
4668      instr->hydrogen()->key()->representation(),
4669      FAST_ELEMENTS,
4670      instr->base_offset());
4671  if (instr->value()->IsRegister()) {
4672    __ mov(operand, ToRegister(instr->value()));
4673  } else {
4674    LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
4675    if (IsSmi(operand_value)) {
4676      Immediate immediate = ToImmediate(operand_value, Representation::Smi());
4677      __ mov(operand, immediate);
4678    } else {
4679      DCHECK(!IsInteger32(operand_value));
4680      Handle<Object> handle_value = ToHandle(operand_value);
4681      __ mov(operand, handle_value);
4682    }
4683  }
4684
4685  if (instr->hydrogen()->NeedsWriteBarrier()) {
4686    DCHECK(instr->value()->IsRegister());
4687    Register value = ToRegister(instr->value());
4688    DCHECK(!instr->key()->IsConstantOperand());
4689    SmiCheck check_needed =
4690        instr->hydrogen()->value()->type().IsHeapObject()
4691          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4692    // Compute address of modified element and store it into key register.
4693    __ lea(key, operand);
4694    __ RecordWrite(elements, key, value, kSaveFPRegs, EMIT_REMEMBERED_SET,
4695                   check_needed,
4696                   instr->hydrogen()->PointersToHereCheckForValue());
4697  }
4698}
4699
4700
4701void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4702  // By cases...external, fast-double, fast
4703  if (instr->is_typed_elements()) {
4704    DoStoreKeyedExternalArray(instr);
4705  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
4706    DoStoreKeyedFixedDoubleArray(instr);
4707  } else {
4708    DoStoreKeyedFixedArray(instr);
4709  }
4710}
4711
4712
4713void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4714  DCHECK(ToRegister(instr->context()).is(esi));
4715  DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
4716  DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
4717  DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));
4718
4719  Handle<Code> ic =
4720      CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code();
4721  CallCode(ic, RelocInfo::CODE_TARGET, instr);
4722}
4723
4724
4725void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4726  Register object = ToRegister(instr->object());
4727  Register temp = ToRegister(instr->temp());
4728  Label no_memento_found;
4729  __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4730  DeoptimizeIf(equal, instr, "memento found");
4731  __ bind(&no_memento_found);
4732}
4733
4734
4735void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4736  Register object_reg = ToRegister(instr->object());
4737
4738  Handle<Map> from_map = instr->original_map();
4739  Handle<Map> to_map = instr->transitioned_map();
4740  ElementsKind from_kind = instr->from_kind();
4741  ElementsKind to_kind = instr->to_kind();
4742
4743  Label not_applicable;
4744  bool is_simple_map_transition =
4745      IsSimpleMapChangeTransition(from_kind, to_kind);
4746  Label::Distance branch_distance =
4747      is_simple_map_transition ? Label::kNear : Label::kFar;
4748  __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
4749  __ j(not_equal, &not_applicable, branch_distance);
4750  if (is_simple_map_transition) {
4751    Register new_map_reg = ToRegister(instr->new_map_temp());
4752    __ mov(FieldOperand(object_reg, HeapObject::kMapOffset),
4753           Immediate(to_map));
4754    // Write barrier.
4755    DCHECK_NE(instr->temp(), NULL);
4756    __ RecordWriteForMap(object_reg, to_map, new_map_reg,
4757                         ToRegister(instr->temp()), kDontSaveFPRegs);
4758  } else {
4759    DCHECK(ToRegister(instr->context()).is(esi));
4760    DCHECK(object_reg.is(eax));
4761    PushSafepointRegistersScope scope(this);
4762    __ mov(ebx, to_map);
4763    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
4764    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
4765    __ CallStub(&stub);
4766    RecordSafepointWithLazyDeopt(instr,
4767        RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4768  }
4769  __ bind(&not_applicable);
4770}
4771
4772
4773void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4774  class DeferredStringCharCodeAt FINAL : public LDeferredCode {
4775   public:
4776    DeferredStringCharCodeAt(LCodeGen* codegen,
4777                             LStringCharCodeAt* instr,
4778                             const X87Stack& x87_stack)
4779        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4780    virtual void Generate() OVERRIDE {
4781      codegen()->DoDeferredStringCharCodeAt(instr_);
4782    }
4783    virtual LInstruction* instr() OVERRIDE { return instr_; }
4784   private:
4785    LStringCharCodeAt* instr_;
4786  };
4787
4788  DeferredStringCharCodeAt* deferred =
4789      new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_);
4790
4791  StringCharLoadGenerator::Generate(masm(),
4792                                    factory(),
4793                                    ToRegister(instr->string()),
4794                                    ToRegister(instr->index()),
4795                                    ToRegister(instr->result()),
4796                                    deferred->entry());
4797  __ bind(deferred->exit());
4798}
4799
4800
4801void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
4802  Register string = ToRegister(instr->string());
4803  Register result = ToRegister(instr->result());
4804
4805  // TODO(3095996): Get rid of this. For now, we need to make the
4806  // result register contain a valid pointer because it is already
4807  // contained in the register pointer map.
4808  __ Move(result, Immediate(0));
4809
4810  PushSafepointRegistersScope scope(this);
4811  __ push(string);
4812  // Push the index as a smi. This is safe because of the checks in
4813  // DoStringCharCodeAt above.
4814  STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
4815  if (instr->index()->IsConstantOperand()) {
4816    Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()),
4817                                      Representation::Smi());
4818    __ push(immediate);
4819  } else {
4820    Register index = ToRegister(instr->index());
4821    __ SmiTag(index);
4822    __ push(index);
4823  }
4824  CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2,
4825                          instr, instr->context());
4826  __ AssertSmi(eax);
4827  __ SmiUntag(eax);
4828  __ StoreToSafepointRegisterSlot(result, eax);
4829}
4830
4831
4832void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4833  class DeferredStringCharFromCode FINAL : public LDeferredCode {
4834   public:
4835    DeferredStringCharFromCode(LCodeGen* codegen,
4836                               LStringCharFromCode* instr,
4837                               const X87Stack& x87_stack)
4838        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4839    virtual void Generate() OVERRIDE {
4840      codegen()->DoDeferredStringCharFromCode(instr_);
4841    }
4842    virtual LInstruction* instr() OVERRIDE { return instr_; }
4843   private:
4844    LStringCharFromCode* instr_;
4845  };
4846
4847  DeferredStringCharFromCode* deferred =
4848      new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_);
4849
4850  DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
4851  Register char_code = ToRegister(instr->char_code());
4852  Register result = ToRegister(instr->result());
4853  DCHECK(!char_code.is(result));
4854
4855  __ cmp(char_code, String::kMaxOneByteCharCode);
4856  __ j(above, deferred->entry());
4857  __ Move(result, Immediate(factory()->single_character_string_cache()));
4858  __ mov(result, FieldOperand(result,
4859                              char_code, times_pointer_size,
4860                              FixedArray::kHeaderSize));
4861  __ cmp(result, factory()->undefined_value());
4862  __ j(equal, deferred->entry());
4863  __ bind(deferred->exit());
4864}
4865
4866
4867void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4868  Register char_code = ToRegister(instr->char_code());
4869  Register result = ToRegister(instr->result());
4870
4871  // TODO(3095996): Get rid of this. For now, we need to make the
4872  // result register contain a valid pointer because it is already
4873  // contained in the register pointer map.
4874  __ Move(result, Immediate(0));
4875
4876  PushSafepointRegistersScope scope(this);
4877  __ SmiTag(char_code);
4878  __ push(char_code);
4879  CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
4880  __ StoreToSafepointRegisterSlot(result, eax);
4881}
4882
4883
4884void LCodeGen::DoStringAdd(LStringAdd* instr) {
4885  DCHECK(ToRegister(instr->context()).is(esi));
4886  DCHECK(ToRegister(instr->left()).is(edx));
4887  DCHECK(ToRegister(instr->right()).is(eax));
4888  StringAddStub stub(isolate(),
4889                     instr->hydrogen()->flags(),
4890                     instr->hydrogen()->pretenure_flag());
4891  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4892}
4893
4894
4895void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4896  LOperand* input = instr->value();
4897  LOperand* output = instr->result();
4898  DCHECK(input->IsRegister() || input->IsStackSlot());
4899  DCHECK(output->IsDoubleRegister());
4900  if (input->IsRegister()) {
4901    Register input_reg = ToRegister(input);
4902    __ push(input_reg);
4903    X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand);
4904    __ pop(input_reg);
4905  } else {
4906    X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
4907  }
4908}
4909
4910
4911void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4912  LOperand* input = instr->value();
4913  LOperand* output = instr->result();
4914  X87Register res = ToX87Register(output);
4915  X87PrepareToWrite(res);
4916  __ LoadUint32NoSSE2(ToRegister(input));
4917  X87CommitWrite(res);
4918}
4919
4920
4921void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4922  class DeferredNumberTagI FINAL : public LDeferredCode {
4923   public:
4924    DeferredNumberTagI(LCodeGen* codegen,
4925                       LNumberTagI* instr,
4926                       const X87Stack& x87_stack)
4927        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4928    virtual void Generate() OVERRIDE {
4929      codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4930                                       SIGNED_INT32);
4931    }
4932    virtual LInstruction* instr() OVERRIDE { return instr_; }
4933   private:
4934    LNumberTagI* instr_;
4935  };
4936
4937  LOperand* input = instr->value();
4938  DCHECK(input->IsRegister() && input->Equals(instr->result()));
4939  Register reg = ToRegister(input);
4940
4941  DeferredNumberTagI* deferred =
4942      new(zone()) DeferredNumberTagI(this, instr, x87_stack_);
4943  __ SmiTag(reg);
4944  __ j(overflow, deferred->entry());
4945  __ bind(deferred->exit());
4946}
4947
4948
4949void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4950  class DeferredNumberTagU FINAL : public LDeferredCode {
4951   public:
4952    DeferredNumberTagU(LCodeGen* codegen,
4953                       LNumberTagU* instr,
4954                       const X87Stack& x87_stack)
4955        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4956    virtual void Generate() OVERRIDE {
4957      codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4958                                       UNSIGNED_INT32);
4959    }
4960    virtual LInstruction* instr() OVERRIDE { return instr_; }
4961   private:
4962    LNumberTagU* instr_;
4963  };
4964
4965  LOperand* input = instr->value();
4966  DCHECK(input->IsRegister() && input->Equals(instr->result()));
4967  Register reg = ToRegister(input);
4968
4969  DeferredNumberTagU* deferred =
4970      new(zone()) DeferredNumberTagU(this, instr, x87_stack_);
4971  __ cmp(reg, Immediate(Smi::kMaxValue));
4972  __ j(above, deferred->entry());
4973  __ SmiTag(reg);
4974  __ bind(deferred->exit());
4975}
4976
4977
4978void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4979                                     LOperand* value,
4980                                     LOperand* temp,
4981                                     IntegerSignedness signedness) {
4982  Label done, slow;
4983  Register reg = ToRegister(value);
4984  Register tmp = ToRegister(temp);
4985
4986  if (signedness == SIGNED_INT32) {
4987    // There was overflow, so bits 30 and 31 of the original integer
4988    // disagree. Try to allocate a heap number in new space and store
4989    // the value in there. If that fails, call the runtime system.
4990    __ SmiUntag(reg);
4991    __ xor_(reg, 0x80000000);
4992    __ push(reg);
4993    __ fild_s(Operand(esp, 0));
4994    __ pop(reg);
4995  } else {
4996    // There's no fild variant for unsigned values, so zero-extend to a 64-bit
4997    // int manually.
4998    __ push(Immediate(0));
4999    __ push(reg);
5000    __ fild_d(Operand(esp, 0));
5001    __ pop(reg);
5002    __ pop(reg);
5003  }
5004
5005  if (FLAG_inline_new) {
5006    __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
5007    __ jmp(&done, Label::kNear);
5008  }
5009
5010  // Slow case: Call the runtime system to do the number allocation.
5011  __ bind(&slow);
5012  {
5013    // TODO(3095996): Put a valid pointer value in the stack slot where the
5014    // result register is stored, as this register is in the pointer map, but
5015    // contains an integer value.
5016    __ Move(reg, Immediate(0));
5017
5018    // Preserve the value of all registers.
5019    PushSafepointRegistersScope scope(this);
5020
5021    // NumberTagI and NumberTagD use the context from the frame, rather than
5022    // the environment's HContext or HInlinedContext value.
5023    // They only call Runtime::kAllocateHeapNumber.
5024    // The corresponding HChange instructions are added in a phase that does
5025    // not have easy access to the local context.
5026    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
5027    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
5028    RecordSafepointWithRegisters(
5029        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5030    __ StoreToSafepointRegisterSlot(reg, eax);
5031  }
5032
5033  __ bind(&done);
5034  __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
5035}
5036
5037
5038void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
5039  class DeferredNumberTagD FINAL : public LDeferredCode {
5040   public:
5041    DeferredNumberTagD(LCodeGen* codegen,
5042                       LNumberTagD* instr,
5043                       const X87Stack& x87_stack)
5044        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5045    virtual void Generate() OVERRIDE {
5046      codegen()->DoDeferredNumberTagD(instr_);
5047    }
5048    virtual LInstruction* instr() OVERRIDE { return instr_; }
5049   private:
5050    LNumberTagD* instr_;
5051  };
5052
5053  Register reg = ToRegister(instr->result());
5054
5055  // Put the value to the top of stack
5056  X87Register src = ToX87Register(instr->value());
5057  // Don't use X87LoadForUsage here, which is only used by Instruction which
5058  // clobbers fp registers.
5059  x87_stack_.Fxch(src);
5060
5061  DeferredNumberTagD* deferred =
5062      new(zone()) DeferredNumberTagD(this, instr, x87_stack_);
5063  if (FLAG_inline_new) {
5064    Register tmp = ToRegister(instr->temp());
5065    __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
5066  } else {
5067    __ jmp(deferred->entry());
5068  }
5069  __ bind(deferred->exit());
5070  __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset));
5071}
5072
5073
5074void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
5075  // TODO(3095996): Get rid of this. For now, we need to make the
5076  // result register contain a valid pointer because it is already
5077  // contained in the register pointer map.
5078  Register reg = ToRegister(instr->result());
5079  __ Move(reg, Immediate(0));
5080
5081  PushSafepointRegistersScope scope(this);
5082  // NumberTagI and NumberTagD use the context from the frame, rather than
5083  // the environment's HContext or HInlinedContext value.
5084  // They only call Runtime::kAllocateHeapNumber.
5085  // The corresponding HChange instructions are added in a phase that does
5086  // not have easy access to the local context.
5087  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
5088  __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
5089  RecordSafepointWithRegisters(
5090      instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5091  __ StoreToSafepointRegisterSlot(reg, eax);
5092}
5093
5094
5095void LCodeGen::DoSmiTag(LSmiTag* instr) {
5096  HChange* hchange = instr->hydrogen();
5097  Register input = ToRegister(instr->value());
5098  if (hchange->CheckFlag(HValue::kCanOverflow) &&
5099      hchange->value()->CheckFlag(HValue::kUint32)) {
5100    __ test(input, Immediate(0xc0000000));
5101    DeoptimizeIf(not_zero, instr, "overflow");
5102  }
5103  __ SmiTag(input);
5104  if (hchange->CheckFlag(HValue::kCanOverflow) &&
5105      !hchange->value()->CheckFlag(HValue::kUint32)) {
5106    DeoptimizeIf(overflow, instr, "overflow");
5107  }
5108}
5109
5110
5111void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
5112  LOperand* input = instr->value();
5113  Register result = ToRegister(input);
5114  DCHECK(input->IsRegister() && input->Equals(instr->result()));
5115  if (instr->needs_check()) {
5116    __ test(result, Immediate(kSmiTagMask));
5117    DeoptimizeIf(not_zero, instr, "not a Smi");
5118  } else {
5119    __ AssertSmi(result);
5120  }
5121  __ SmiUntag(result);
5122}
5123
5124
5125void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
5126                                      Register temp_reg, X87Register res_reg,
5127                                      NumberUntagDMode mode) {
5128  bool can_convert_undefined_to_nan =
5129      instr->hydrogen()->can_convert_undefined_to_nan();
5130  bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
5131
5132  Label load_smi, done;
5133
5134  X87PrepareToWrite(res_reg);
5135  if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5136    // Smi check.
5137    __ JumpIfSmi(input_reg, &load_smi);
5138
5139    // Heap number map check.
5140    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5141           factory()->heap_number_map());
5142    if (!can_convert_undefined_to_nan) {
5143      DeoptimizeIf(not_equal, instr, "not a heap number");
5144    } else {
5145      Label heap_number, convert;
5146      __ j(equal, &heap_number);
5147
5148      // Convert undefined (or hole) to NaN.
5149      __ cmp(input_reg, factory()->undefined_value());
5150      DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5151
5152      __ bind(&convert);
5153      ExternalReference nan =
5154          ExternalReference::address_of_canonical_non_hole_nan();
5155      __ fld_d(Operand::StaticVariable(nan));
5156      __ jmp(&done, Label::kNear);
5157
5158      __ bind(&heap_number);
5159    }
5160    // Heap number to x87 conversion.
5161    __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5162    if (deoptimize_on_minus_zero) {
5163      __ fldz();
5164      __ FCmp();
5165      __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5166      __ j(not_zero, &done, Label::kNear);
5167
5168      // Use general purpose registers to check if we have -0.0
5169      __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5170      __ test(temp_reg, Immediate(HeapNumber::kSignMask));
5171      __ j(zero, &done, Label::kNear);
5172
5173      // Pop FPU stack before deoptimizing.
5174      __ fstp(0);
5175      DeoptimizeIf(not_zero, instr, "minus zero");
5176    }
5177    __ jmp(&done, Label::kNear);
5178  } else {
5179    DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
5180  }
5181
5182  __ bind(&load_smi);
5183  // Clobbering a temp is faster than re-tagging the
5184  // input register since we avoid dependencies.
5185  __ mov(temp_reg, input_reg);
5186  __ SmiUntag(temp_reg);  // Untag smi before converting to float.
5187  __ push(temp_reg);
5188  __ fild_s(Operand(esp, 0));
5189  __ add(esp, Immediate(kPointerSize));
5190  __ bind(&done);
5191  X87CommitWrite(res_reg);
5192}
5193
5194
5195void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
5196  Register input_reg = ToRegister(instr->value());
5197
5198  // The input was optimistically untagged; revert it.
5199  STATIC_ASSERT(kSmiTagSize == 1);
5200  __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag));
5201
5202  if (instr->truncating()) {
5203    Label no_heap_number, check_bools, check_false;
5204
5205    // Heap number map check.
5206    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5207           factory()->heap_number_map());
5208    __ j(not_equal, &no_heap_number, Label::kNear);
5209    __ TruncateHeapNumberToI(input_reg, input_reg);
5210    __ jmp(done);
5211
5212    __ bind(&no_heap_number);
5213    // Check for Oddballs. Undefined/False is converted to zero and True to one
5214    // for truncating conversions.
5215    __ cmp(input_reg, factory()->undefined_value());
5216    __ j(not_equal, &check_bools, Label::kNear);
5217    __ Move(input_reg, Immediate(0));
5218    __ jmp(done);
5219
5220    __ bind(&check_bools);
5221    __ cmp(input_reg, factory()->true_value());
5222    __ j(not_equal, &check_false, Label::kNear);
5223    __ Move(input_reg, Immediate(1));
5224    __ jmp(done);
5225
5226    __ bind(&check_false);
5227    __ cmp(input_reg, factory()->false_value());
5228    DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
5229    __ Move(input_reg, Immediate(0));
5230  } else {
5231    // TODO(olivf) Converting a number on the fpu is actually quite slow. We
5232    // should first try a fast conversion and then bailout to this slow case.
5233    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5234           isolate()->factory()->heap_number_map());
5235    DeoptimizeIf(not_equal, instr, "not a heap number");
5236
5237    __ sub(esp, Immediate(kPointerSize));
5238    __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5239
5240    if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
5241      Label no_precision_lost, not_nan, zero_check;
5242      __ fld(0);
5243
5244      __ fist_s(MemOperand(esp, 0));
5245      __ fild_s(MemOperand(esp, 0));
5246      __ FCmp();
5247      __ pop(input_reg);
5248
5249      __ j(equal, &no_precision_lost, Label::kNear);
5250      __ fstp(0);
5251      DeoptimizeIf(no_condition, instr, "lost precision");
5252      __ bind(&no_precision_lost);
5253
5254      __ j(parity_odd, &not_nan);
5255      __ fstp(0);
5256      DeoptimizeIf(no_condition, instr, "NaN");
5257      __ bind(&not_nan);
5258
5259      __ test(input_reg, Operand(input_reg));
5260      __ j(zero, &zero_check, Label::kNear);
5261      __ fstp(0);
5262      __ jmp(done);
5263
5264      __ bind(&zero_check);
5265      // To check for minus zero, we load the value again as float, and check
5266      // if that is still 0.
5267      __ sub(esp, Immediate(kPointerSize));
5268      __ fstp_s(Operand(esp, 0));
5269      __ pop(input_reg);
5270      __ test(input_reg, Operand(input_reg));
5271      DeoptimizeIf(not_zero, instr, "minus zero");
5272    } else {
5273      __ fist_s(MemOperand(esp, 0));
5274      __ fild_s(MemOperand(esp, 0));
5275      __ FCmp();
5276      __ pop(input_reg);
5277      DeoptimizeIf(not_equal, instr, "lost precision");
5278      DeoptimizeIf(parity_even, instr, "NaN");
5279    }
5280  }
5281}
5282
5283
5284void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5285  class DeferredTaggedToI FINAL : public LDeferredCode {
5286   public:
5287    DeferredTaggedToI(LCodeGen* codegen,
5288                      LTaggedToI* instr,
5289                      const X87Stack& x87_stack)
5290        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5291    virtual void Generate() OVERRIDE {
5292      codegen()->DoDeferredTaggedToI(instr_, done());
5293    }
5294    virtual LInstruction* instr() OVERRIDE { return instr_; }
5295   private:
5296    LTaggedToI* instr_;
5297  };
5298
5299  LOperand* input = instr->value();
5300  DCHECK(input->IsRegister());
5301  Register input_reg = ToRegister(input);
5302  DCHECK(input_reg.is(ToRegister(instr->result())));
5303
5304  if (instr->hydrogen()->value()->representation().IsSmi()) {
5305    __ SmiUntag(input_reg);
5306  } else {
5307    DeferredTaggedToI* deferred =
5308        new(zone()) DeferredTaggedToI(this, instr, x87_stack_);
5309    // Optimistically untag the input.
5310    // If the input is a HeapObject, SmiUntag will set the carry flag.
5311    STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
5312    __ SmiUntag(input_reg);
5313    // Branch to deferred code if the input was tagged.
5314    // The deferred code will take care of restoring the tag.
5315    __ j(carry, deferred->entry());
5316    __ bind(deferred->exit());
5317  }
5318}
5319
5320
5321void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
5322  LOperand* input = instr->value();
5323  DCHECK(input->IsRegister());
5324  LOperand* temp = instr->temp();
5325  DCHECK(temp->IsRegister());
5326  LOperand* result = instr->result();
5327  DCHECK(result->IsDoubleRegister());
5328
5329  Register input_reg = ToRegister(input);
5330  Register temp_reg = ToRegister(temp);
5331
5332  HValue* value = instr->hydrogen()->value();
5333  NumberUntagDMode mode = value->representation().IsSmi()
5334      ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5335
5336  EmitNumberUntagDNoSSE2(instr, input_reg, temp_reg, ToX87Register(result),
5337                         mode);
5338}
5339
5340
5341void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5342  LOperand* input = instr->value();
5343  DCHECK(input->IsDoubleRegister());
5344  LOperand* result = instr->result();
5345  DCHECK(result->IsRegister());
5346  Register result_reg = ToRegister(result);
5347
5348  if (instr->truncating()) {
5349    X87Register input_reg = ToX87Register(input);
5350    X87Fxch(input_reg);
5351    __ TruncateX87TOSToI(result_reg);
5352  } else {
5353    Label lost_precision, is_nan, minus_zero, done;
5354    X87Register input_reg = ToX87Register(input);
5355    X87Fxch(input_reg);
5356    Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
5357    __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
5358                 &lost_precision, &is_nan, &minus_zero, dist);
5359    __ jmp(&done);
5360    __ bind(&lost_precision);
5361    DeoptimizeIf(no_condition, instr, "lost precision");
5362    __ bind(&is_nan);
5363    DeoptimizeIf(no_condition, instr, "NaN");
5364    __ bind(&minus_zero);
5365    DeoptimizeIf(no_condition, instr, "minus zero");
5366    __ bind(&done);
5367  }
5368}
5369
5370
5371void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5372  LOperand* input = instr->value();
5373  DCHECK(input->IsDoubleRegister());
5374  LOperand* result = instr->result();
5375  DCHECK(result->IsRegister());
5376  Register result_reg = ToRegister(result);
5377
5378  Label lost_precision, is_nan, minus_zero, done;
5379  X87Register input_reg = ToX87Register(input);
5380  X87Fxch(input_reg);
5381  Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
5382  __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
5383               &lost_precision, &is_nan, &minus_zero, dist);
5384  __ jmp(&done);
5385  __ bind(&lost_precision);
5386  DeoptimizeIf(no_condition, instr, "lost precision");
5387  __ bind(&is_nan);
5388  DeoptimizeIf(no_condition, instr, "NaN");
5389  __ bind(&minus_zero);
5390  DeoptimizeIf(no_condition, instr, "minus zero");
5391  __ bind(&done);
5392  __ SmiTag(result_reg);
5393  DeoptimizeIf(overflow, instr, "overflow");
5394}
5395
5396
5397void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5398  LOperand* input = instr->value();
5399  __ test(ToOperand(input), Immediate(kSmiTagMask));
5400  DeoptimizeIf(not_zero, instr, "not a Smi");
5401}
5402
5403
5404void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5405  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5406    LOperand* input = instr->value();
5407    __ test(ToOperand(input), Immediate(kSmiTagMask));
5408    DeoptimizeIf(zero, instr, "Smi");
5409  }
5410}
5411
5412
5413void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5414  Register input = ToRegister(instr->value());
5415  Register temp = ToRegister(instr->temp());
5416
5417  __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
5418
5419  if (instr->hydrogen()->is_interval_check()) {
5420    InstanceType first;
5421    InstanceType last;
5422    instr->hydrogen()->GetCheckInterval(&first, &last);
5423
5424    __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5425            static_cast<int8_t>(first));
5426
5427    // If there is only one type in the interval check for equality.
5428    if (first == last) {
5429      DeoptimizeIf(not_equal, instr, "wrong instance type");
5430    } else {
5431      DeoptimizeIf(below, instr, "wrong instance type");
5432      // Omit check for the last type.
5433      if (last != LAST_TYPE) {
5434        __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
5435                static_cast<int8_t>(last));
5436        DeoptimizeIf(above, instr, "wrong instance type");
5437      }
5438    }
5439  } else {
5440    uint8_t mask;
5441    uint8_t tag;
5442    instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5443
5444    if (base::bits::IsPowerOfTwo32(mask)) {
5445      DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5446      __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
5447      DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
5448    } else {
5449      __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
5450      __ and_(temp, mask);
5451      __ cmp(temp, tag);
5452      DeoptimizeIf(not_equal, instr, "wrong instance type");
5453    }
5454  }
5455}
5456
5457
5458void LCodeGen::DoCheckValue(LCheckValue* instr) {
5459  Handle<HeapObject> object = instr->hydrogen()->object().handle();
5460  if (instr->hydrogen()->object_in_new_space()) {
5461    Register reg = ToRegister(instr->value());
5462    Handle<Cell> cell = isolate()->factory()->NewCell(object);
5463    __ cmp(reg, Operand::ForCell(cell));
5464  } else {
5465    Operand operand = ToOperand(instr->value());
5466    __ cmp(operand, object);
5467  }
5468  DeoptimizeIf(not_equal, instr, "value mismatch");
5469}
5470
5471
5472void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5473  {
5474    PushSafepointRegistersScope scope(this);
5475    __ push(object);
5476    __ xor_(esi, esi);
5477    __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5478    RecordSafepointWithRegisters(
5479        instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5480
5481    __ test(eax, Immediate(kSmiTagMask));
5482  }
5483  DeoptimizeIf(zero, instr, "instance migration failed");
5484}
5485
5486
5487void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5488  class DeferredCheckMaps FINAL : public LDeferredCode {
5489   public:
5490    DeferredCheckMaps(LCodeGen* codegen,
5491                      LCheckMaps* instr,
5492                      Register object,
5493                      const X87Stack& x87_stack)
5494        : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) {
5495      SetExit(check_maps());
5496    }
5497    virtual void Generate() OVERRIDE {
5498      codegen()->DoDeferredInstanceMigration(instr_, object_);
5499    }
5500    Label* check_maps() { return &check_maps_; }
5501    virtual LInstruction* instr() OVERRIDE { return instr_; }
5502   private:
5503    LCheckMaps* instr_;
5504    Label check_maps_;
5505    Register object_;
5506  };
5507
5508  if (instr->hydrogen()->IsStabilityCheck()) {
5509    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5510    for (int i = 0; i < maps->size(); ++i) {
5511      AddStabilityDependency(maps->at(i).handle());
5512    }
5513    return;
5514  }
5515
5516  LOperand* input = instr->value();
5517  DCHECK(input->IsRegister());
5518  Register reg = ToRegister(input);
5519
5520  DeferredCheckMaps* deferred = NULL;
5521  if (instr->hydrogen()->HasMigrationTarget()) {
5522    deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
5523    __ bind(deferred->check_maps());
5524  }
5525
5526  const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5527  Label success;
5528  for (int i = 0; i < maps->size() - 1; i++) {
5529    Handle<Map> map = maps->at(i).handle();
5530    __ CompareMap(reg, map);
5531    __ j(equal, &success, Label::kNear);
5532  }
5533
5534  Handle<Map> map = maps->at(maps->size() - 1).handle();
5535  __ CompareMap(reg, map);
5536  if (instr->hydrogen()->HasMigrationTarget()) {
5537    __ j(not_equal, deferred->entry());
5538  } else {
5539    DeoptimizeIf(not_equal, instr, "wrong map");
5540  }
5541
5542  __ bind(&success);
5543}
5544
5545
5546void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5547  X87Register value_reg = ToX87Register(instr->unclamped());
5548  Register result_reg = ToRegister(instr->result());
5549  X87Fxch(value_reg);
5550  __ ClampTOSToUint8(result_reg);
5551}
5552
5553
5554void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5555  DCHECK(instr->unclamped()->Equals(instr->result()));
5556  Register value_reg = ToRegister(instr->result());
5557  __ ClampUint8(value_reg);
5558}
5559
5560
5561void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
5562  Register input_reg = ToRegister(instr->unclamped());
5563  Register result_reg = ToRegister(instr->result());
5564  Register scratch = ToRegister(instr->scratch());
5565  Register scratch2 = ToRegister(instr->scratch2());
5566  Register scratch3 = ToRegister(instr->scratch3());
5567  Label is_smi, done, heap_number, valid_exponent,
5568      largest_value, zero_result, maybe_nan_or_infinity;
5569
5570  __ JumpIfSmi(input_reg, &is_smi);
5571
5572  // Check for heap number
5573  __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5574         factory()->heap_number_map());
5575  __ j(equal, &heap_number, Label::kNear);
5576
5577  // Check for undefined. Undefined is converted to zero for clamping
5578  // conversions.
5579  __ cmp(input_reg, factory()->undefined_value());
5580  DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5581  __ jmp(&zero_result, Label::kNear);
5582
5583  // Heap number
5584  __ bind(&heap_number);
5585
5586  // Surprisingly, all of the hand-crafted bit-manipulations below are much
5587  // faster than the x86 FPU built-in instruction, especially since "banker's
5588  // rounding" would be additionally very expensive
5589
5590  // Get exponent word.
5591  __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5592  __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5593
5594  // Test for negative values --> clamp to zero
5595  __ test(scratch, scratch);
5596  __ j(negative, &zero_result, Label::kNear);
5597
5598  // Get exponent alone in scratch2.
5599  __ mov(scratch2, scratch);
5600  __ and_(scratch2, HeapNumber::kExponentMask);
5601  __ shr(scratch2, HeapNumber::kExponentShift);
5602  __ j(zero, &zero_result, Label::kNear);
5603  __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
5604  __ j(negative, &zero_result, Label::kNear);
5605
5606  const uint32_t non_int8_exponent = 7;
5607  __ cmp(scratch2, Immediate(non_int8_exponent + 1));
5608  // If the exponent is too big, check for special values.
5609  __ j(greater, &maybe_nan_or_infinity, Label::kNear);
5610
5611  __ bind(&valid_exponent);
5612  // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
5613  // < 7. The shift bias is the number of bits to shift the mantissa such that
5614  // with an exponent of 7 such the that top-most one is in bit 30, allowing
5615  // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to
5616  // 1).
5617  int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1;
5618  __ lea(result_reg, MemOperand(scratch2, shift_bias));
5619  // Here result_reg (ecx) is the shift, scratch is the exponent word.  Get the
5620  // top bits of the mantissa.
5621  __ and_(scratch, HeapNumber::kMantissaMask);
5622  // Put back the implicit 1 of the mantissa
5623  __ or_(scratch, 1 << HeapNumber::kExponentShift);
5624  // Shift up to round
5625  __ shl_cl(scratch);
5626  // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
5627  // use the bit in the "ones" place and add it to the "halves" place, which has
5628  // the effect of rounding to even.
5629  __ mov(scratch2, scratch);
5630  const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
5631  const uint32_t one_bit_shift = one_half_bit_shift + 1;
5632  __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
5633  __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
5634  Label no_round;
5635  __ j(less, &no_round, Label::kNear);
5636  Label round_up;
5637  __ mov(scratch2, Immediate(1 << one_half_bit_shift));
5638  __ j(greater, &round_up, Label::kNear);
5639  __ test(scratch3, scratch3);
5640  __ j(not_zero, &round_up, Label::kNear);
5641  __ mov(scratch2, scratch);
5642  __ and_(scratch2, Immediate(1 << one_bit_shift));
5643  __ shr(scratch2, 1);
5644  __ bind(&round_up);
5645  __ add(scratch, scratch2);
5646  __ j(overflow, &largest_value, Label::kNear);
5647  __ bind(&no_round);
5648  __ shr(scratch, 23);
5649  __ mov(result_reg, scratch);
5650  __ jmp(&done, Label::kNear);
5651
5652  __ bind(&maybe_nan_or_infinity);
5653  // Check for NaN/Infinity, all other values map to 255
5654  __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
5655  __ j(not_equal, &largest_value, Label::kNear);
5656
5657  // Check for NaN, which differs from Infinity in that at least one mantissa
5658  // bit is set.
5659  __ and_(scratch, HeapNumber::kMantissaMask);
5660  __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5661  __ j(not_zero, &zero_result, Label::kNear);  // M!=0 --> NaN
5662  // Infinity -> Fall through to map to 255.
5663
5664  __ bind(&largest_value);
5665  __ mov(result_reg, Immediate(255));
5666  __ jmp(&done, Label::kNear);
5667
5668  __ bind(&zero_result);
5669  __ xor_(result_reg, result_reg);
5670  __ jmp(&done, Label::kNear);
5671
5672  // smi
5673  __ bind(&is_smi);
5674  if (!input_reg.is(result_reg)) {
5675    __ mov(result_reg, input_reg);
5676  }
5677  __ SmiUntag(result_reg);
5678  __ ClampUint8(result_reg);
5679  __ bind(&done);
5680}
5681
5682
5683void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5684  X87Register value_reg = ToX87Register(instr->value());
5685  Register result_reg = ToRegister(instr->result());
5686  X87Fxch(value_reg);
5687  __ sub(esp, Immediate(kDoubleSize));
5688  __ fst_d(Operand(esp, 0));
5689  if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5690    __ mov(result_reg, Operand(esp, kPointerSize));
5691  } else {
5692    __ mov(result_reg, Operand(esp, 0));
5693  }
5694  __ add(esp, Immediate(kDoubleSize));
5695}
5696
5697
5698void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5699  Register hi_reg = ToRegister(instr->hi());
5700  Register lo_reg = ToRegister(instr->lo());
5701  X87Register result_reg = ToX87Register(instr->result());
5702  // Follow below pattern to write a x87 fp register.
5703  X87PrepareToWrite(result_reg);
5704  __ sub(esp, Immediate(kDoubleSize));
5705  __ mov(Operand(esp, 0), lo_reg);
5706  __ mov(Operand(esp, kPointerSize), hi_reg);
5707  __ fld_d(Operand(esp, 0));
5708  __ add(esp, Immediate(kDoubleSize));
5709  X87CommitWrite(result_reg);
5710}
5711
5712
5713void LCodeGen::DoAllocate(LAllocate* instr) {
5714  class DeferredAllocate FINAL : public LDeferredCode {
5715   public:
5716    DeferredAllocate(LCodeGen* codegen,
5717                     LAllocate* instr,
5718                     const X87Stack& x87_stack)
5719        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5720    virtual void Generate() OVERRIDE {
5721      codegen()->DoDeferredAllocate(instr_);
5722    }
5723    virtual LInstruction* instr() OVERRIDE { return instr_; }
5724   private:
5725    LAllocate* instr_;
5726  };
5727
5728  DeferredAllocate* deferred =
5729      new(zone()) DeferredAllocate(this, instr, x87_stack_);
5730
5731  Register result = ToRegister(instr->result());
5732  Register temp = ToRegister(instr->temp());
5733
5734  // Allocate memory for the object.
5735  AllocationFlags flags = TAG_OBJECT;
5736  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5737    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5738  }
5739  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
5740    DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation());
5741    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5742    flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
5743  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
5744    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5745    flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
5746  }
5747
5748  if (instr->size()->IsConstantOperand()) {
5749    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5750    if (size <= Page::kMaxRegularHeapObjectSize) {
5751      __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
5752    } else {
5753      __ jmp(deferred->entry());
5754    }
5755  } else {
5756    Register size = ToRegister(instr->size());
5757    __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
5758  }
5759
5760  __ bind(deferred->exit());
5761
5762  if (instr->hydrogen()->MustPrefillWithFiller()) {
5763    if (instr->size()->IsConstantOperand()) {
5764      int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5765      __ mov(temp, (size / kPointerSize) - 1);
5766    } else {
5767      temp = ToRegister(instr->size());
5768      __ shr(temp, kPointerSizeLog2);
5769      __ dec(temp);
5770    }
5771    Label loop;
5772    __ bind(&loop);
5773    __ mov(FieldOperand(result, temp, times_pointer_size, 0),
5774        isolate()->factory()->one_pointer_filler_map());
5775    __ dec(temp);
5776    __ j(not_zero, &loop);
5777  }
5778}
5779
5780
5781void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
5782  Register result = ToRegister(instr->result());
5783
5784  // TODO(3095996): Get rid of this. For now, we need to make the
5785  // result register contain a valid pointer because it is already
5786  // contained in the register pointer map.
5787  __ Move(result, Immediate(Smi::FromInt(0)));
5788
5789  PushSafepointRegistersScope scope(this);
5790  if (instr->size()->IsRegister()) {
5791    Register size = ToRegister(instr->size());
5792    DCHECK(!size.is(result));
5793    __ SmiTag(ToRegister(instr->size()));
5794    __ push(size);
5795  } else {
5796    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
5797    if (size >= 0 && size <= Smi::kMaxValue) {
5798      __ push(Immediate(Smi::FromInt(size)));
5799    } else {
5800      // We should never get here at runtime => abort
5801      __ int3();
5802      return;
5803    }
5804  }
5805
5806  int flags = AllocateDoubleAlignFlag::encode(
5807      instr->hydrogen()->MustAllocateDoubleAligned());
5808  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
5809    DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation());
5810    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5811    flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE);
5812  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
5813    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
5814    flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE);
5815  } else {
5816    flags = AllocateTargetSpace::update(flags, NEW_SPACE);
5817  }
5818  __ push(Immediate(Smi::FromInt(flags)));
5819
5820  CallRuntimeFromDeferred(
5821      Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
5822  __ StoreToSafepointRegisterSlot(result, eax);
5823}
5824
5825
5826void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
5827  DCHECK(ToRegister(instr->value()).is(eax));
5828  __ push(eax);
5829  CallRuntime(Runtime::kToFastProperties, 1, instr);
5830}
5831
5832
5833void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
5834  DCHECK(ToRegister(instr->context()).is(esi));
5835  Label materialized;
5836  // Registers will be used as follows:
5837  // ecx = literals array.
5838  // ebx = regexp literal.
5839  // eax = regexp literal clone.
5840  // esi = context.
5841  int literal_offset =
5842      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
5843  __ LoadHeapObject(ecx, instr->hydrogen()->literals());
5844  __ mov(ebx, FieldOperand(ecx, literal_offset));
5845  __ cmp(ebx, factory()->undefined_value());
5846  __ j(not_equal, &materialized, Label::kNear);
5847
5848  // Create regexp literal using runtime function
5849  // Result will be in eax.
5850  __ push(ecx);
5851  __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
5852  __ push(Immediate(instr->hydrogen()->pattern()));
5853  __ push(Immediate(instr->hydrogen()->flags()));
5854  CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
5855  __ mov(ebx, eax);
5856
5857  __ bind(&materialized);
5858  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
5859  Label allocated, runtime_allocate;
5860  __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
5861  __ jmp(&allocated, Label::kNear);
5862
5863  __ bind(&runtime_allocate);
5864  __ push(ebx);
5865  __ push(Immediate(Smi::FromInt(size)));
5866  CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
5867  __ pop(ebx);
5868
5869  __ bind(&allocated);
5870  // Copy the content into the newly allocated memory.
5871  // (Unroll copy loop once for better throughput).
5872  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
5873    __ mov(edx, FieldOperand(ebx, i));
5874    __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
5875    __ mov(FieldOperand(eax, i), edx);
5876    __ mov(FieldOperand(eax, i + kPointerSize), ecx);
5877  }
5878  if ((size % (2 * kPointerSize)) != 0) {
5879    __ mov(edx, FieldOperand(ebx, size - kPointerSize));
5880    __ mov(FieldOperand(eax, size - kPointerSize), edx);
5881  }
5882}
5883
5884
5885void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
5886  DCHECK(ToRegister(instr->context()).is(esi));
5887  // Use the fast case closure allocation code that allocates in new
5888  // space for nested functions that don't need literals cloning.
5889  bool pretenure = instr->hydrogen()->pretenure();
5890  if (!pretenure && instr->hydrogen()->has_no_literals()) {
5891    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
5892                            instr->hydrogen()->kind());
5893    __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
5894    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
5895  } else {
5896    __ push(esi);
5897    __ push(Immediate(instr->hydrogen()->shared_info()));
5898    __ push(Immediate(pretenure ? factory()->true_value()
5899                                : factory()->false_value()));
5900    CallRuntime(Runtime::kNewClosure, 3, instr);
5901  }
5902}
5903
5904
5905void LCodeGen::DoTypeof(LTypeof* instr) {
5906  DCHECK(ToRegister(instr->context()).is(esi));
5907  LOperand* input = instr->value();
5908  EmitPushTaggedOperand(input);
5909  CallRuntime(Runtime::kTypeof, 1, instr);
5910}
5911
5912
5913void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
5914  Register input = ToRegister(instr->value());
5915  Condition final_branch_condition = EmitTypeofIs(instr, input);
5916  if (final_branch_condition != no_condition) {
5917    EmitBranch(instr, final_branch_condition);
5918  }
5919}
5920
5921
5922Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
5923  Label* true_label = instr->TrueLabel(chunk_);
5924  Label* false_label = instr->FalseLabel(chunk_);
5925  Handle<String> type_name = instr->type_literal();
5926  int left_block = instr->TrueDestination(chunk_);
5927  int right_block = instr->FalseDestination(chunk_);
5928  int next_block = GetNextEmittedBlock();
5929
5930  Label::Distance true_distance = left_block == next_block ? Label::kNear
5931                                                           : Label::kFar;
5932  Label::Distance false_distance = right_block == next_block ? Label::kNear
5933                                                             : Label::kFar;
5934  Condition final_branch_condition = no_condition;
5935  if (String::Equals(type_name, factory()->number_string())) {
5936    __ JumpIfSmi(input, true_label, true_distance);
5937    __ cmp(FieldOperand(input, HeapObject::kMapOffset),
5938           factory()->heap_number_map());
5939    final_branch_condition = equal;
5940
5941  } else if (String::Equals(type_name, factory()->string_string())) {
5942    __ JumpIfSmi(input, false_label, false_distance);
5943    __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
5944    __ j(above_equal, false_label, false_distance);
5945    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5946              1 << Map::kIsUndetectable);
5947    final_branch_condition = zero;
5948
5949  } else if (String::Equals(type_name, factory()->symbol_string())) {
5950    __ JumpIfSmi(input, false_label, false_distance);
5951    __ CmpObjectType(input, SYMBOL_TYPE, input);
5952    final_branch_condition = equal;
5953
5954  } else if (String::Equals(type_name, factory()->boolean_string())) {
5955    __ cmp(input, factory()->true_value());
5956    __ j(equal, true_label, true_distance);
5957    __ cmp(input, factory()->false_value());
5958    final_branch_condition = equal;
5959
5960  } else if (String::Equals(type_name, factory()->undefined_string())) {
5961    __ cmp(input, factory()->undefined_value());
5962    __ j(equal, true_label, true_distance);
5963    __ JumpIfSmi(input, false_label, false_distance);
5964    // Check for undetectable objects => true.
5965    __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
5966    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5967              1 << Map::kIsUndetectable);
5968    final_branch_condition = not_zero;
5969
5970  } else if (String::Equals(type_name, factory()->function_string())) {
5971    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
5972    __ JumpIfSmi(input, false_label, false_distance);
5973    __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
5974    __ j(equal, true_label, true_distance);
5975    __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
5976    final_branch_condition = equal;
5977
5978  } else if (String::Equals(type_name, factory()->object_string())) {
5979    __ JumpIfSmi(input, false_label, false_distance);
5980    __ cmp(input, factory()->null_value());
5981    __ j(equal, true_label, true_distance);
5982    __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
5983    __ j(below, false_label, false_distance);
5984    __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
5985    __ j(above, false_label, false_distance);
5986    // Check for undetectable objects => false.
5987    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
5988              1 << Map::kIsUndetectable);
5989    final_branch_condition = zero;
5990
5991  } else {
5992    __ jmp(false_label, false_distance);
5993  }
5994  return final_branch_condition;
5995}
5996
5997
5998void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
5999  Register temp = ToRegister(instr->temp());
6000
6001  EmitIsConstructCall(temp);
6002  EmitBranch(instr, equal);
6003}
6004
6005
6006void LCodeGen::EmitIsConstructCall(Register temp) {
6007  // Get the frame pointer for the calling frame.
6008  __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
6009
6010  // Skip the arguments adaptor frame if it exists.
6011  Label check_frame_marker;
6012  __ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
6013         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
6014  __ j(not_equal, &check_frame_marker, Label::kNear);
6015  __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));
6016
6017  // Check the marker in the calling frame.
6018  __ bind(&check_frame_marker);
6019  __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
6020         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
6021}
6022
6023
6024void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
6025  if (!info()->IsStub()) {
6026    // Ensure that we have enough space after the previous lazy-bailout
6027    // instruction for patching the code here.
6028    int current_pc = masm()->pc_offset();
6029    if (current_pc < last_lazy_deopt_pc_ + space_needed) {
6030      int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
6031      __ Nop(padding_size);
6032    }
6033  }
6034  last_lazy_deopt_pc_ = masm()->pc_offset();
6035}
6036
6037
6038void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
6039  last_lazy_deopt_pc_ = masm()->pc_offset();
6040  DCHECK(instr->HasEnvironment());
6041  LEnvironment* env = instr->environment();
6042  RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6043  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6044}
6045
6046
6047void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
6048  Deoptimizer::BailoutType type = instr->hydrogen()->type();
6049  // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
6050  // needed return address), even though the implementation of LAZY and EAGER is
6051  // now identical. When LAZY is eventually completely folded into EAGER, remove
6052  // the special case below.
6053  if (info()->IsStub() && type == Deoptimizer::EAGER) {
6054    type = Deoptimizer::LAZY;
6055  }
6056  DeoptimizeIf(no_condition, instr, instr->hydrogen()->reason(), type);
6057}
6058
6059
6060void LCodeGen::DoDummy(LDummy* instr) {
6061  // Nothing to see here, move on!
6062}
6063
6064
6065void LCodeGen::DoDummyUse(LDummyUse* instr) {
6066  // Nothing to see here, move on!
6067}
6068
6069
6070void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
6071  PushSafepointRegistersScope scope(this);
6072  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
6073  __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
6074  RecordSafepointWithLazyDeopt(
6075      instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
6076  DCHECK(instr->HasEnvironment());
6077  LEnvironment* env = instr->environment();
6078  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6079}
6080
6081
6082void LCodeGen::DoStackCheck(LStackCheck* instr) {
6083  class DeferredStackCheck FINAL : public LDeferredCode {
6084   public:
6085    DeferredStackCheck(LCodeGen* codegen,
6086                       LStackCheck* instr,
6087                       const X87Stack& x87_stack)
6088        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
6089    virtual void Generate() OVERRIDE {
6090      codegen()->DoDeferredStackCheck(instr_);
6091    }
6092    virtual LInstruction* instr() OVERRIDE { return instr_; }
6093   private:
6094    LStackCheck* instr_;
6095  };
6096
6097  DCHECK(instr->HasEnvironment());
6098  LEnvironment* env = instr->environment();
6099  // There is no LLazyBailout instruction for stack-checks. We have to
6100  // prepare for lazy deoptimization explicitly here.
6101  if (instr->hydrogen()->is_function_entry()) {
6102    // Perform stack overflow check.
6103    Label done;
6104    ExternalReference stack_limit =
6105        ExternalReference::address_of_stack_limit(isolate());
6106    __ cmp(esp, Operand::StaticVariable(stack_limit));
6107    __ j(above_equal, &done, Label::kNear);
6108
6109    DCHECK(instr->context()->IsRegister());
6110    DCHECK(ToRegister(instr->context()).is(esi));
6111    CallCode(isolate()->builtins()->StackCheck(),
6112             RelocInfo::CODE_TARGET,
6113             instr);
6114    __ bind(&done);
6115  } else {
6116    DCHECK(instr->hydrogen()->is_backwards_branch());
6117    // Perform stack overflow check if this goto needs it before jumping.
6118    DeferredStackCheck* deferred_stack_check =
6119        new(zone()) DeferredStackCheck(this, instr, x87_stack_);
6120    ExternalReference stack_limit =
6121        ExternalReference::address_of_stack_limit(isolate());
6122    __ cmp(esp, Operand::StaticVariable(stack_limit));
6123    __ j(below, deferred_stack_check->entry());
6124    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
6125    __ bind(instr->done_label());
6126    deferred_stack_check->SetExit(instr->done_label());
6127    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6128    // Don't record a deoptimization index for the safepoint here.
6129    // This will be done explicitly when emitting call and the safepoint in
6130    // the deferred code.
6131  }
6132}
6133
6134
6135void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
6136  // This is a pseudo-instruction that ensures that the environment here is
6137  // properly registered for deoptimization and records the assembler's PC
6138  // offset.
6139  LEnvironment* environment = instr->environment();
6140
6141  // If the environment were already registered, we would have no way of
6142  // backpatching it with the spill slot operands.
6143  DCHECK(!environment->HasBeenRegistered());
6144  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
6145
6146  GenerateOsrPrologue();
6147}
6148
6149
6150void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
6151  DCHECK(ToRegister(instr->context()).is(esi));
6152  __ cmp(eax, isolate()->factory()->undefined_value());
6153  DeoptimizeIf(equal, instr, "undefined");
6154
6155  __ cmp(eax, isolate()->factory()->null_value());
6156  DeoptimizeIf(equal, instr, "null");
6157
6158  __ test(eax, Immediate(kSmiTagMask));
6159  DeoptimizeIf(zero, instr, "Smi");
6160
6161  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
6162  __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
6163  DeoptimizeIf(below_equal, instr, "wrong instance type");
6164
6165  Label use_cache, call_runtime;
6166  __ CheckEnumCache(&call_runtime);
6167
6168  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
6169  __ jmp(&use_cache, Label::kNear);
6170
6171  // Get the set of properties to enumerate.
6172  __ bind(&call_runtime);
6173  __ push(eax);
6174  CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
6175
6176  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
6177         isolate()->factory()->meta_map());
6178  DeoptimizeIf(not_equal, instr, "wrong map");
6179  __ bind(&use_cache);
6180}
6181
6182
6183void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
6184  Register map = ToRegister(instr->map());
6185  Register result = ToRegister(instr->result());
6186  Label load_cache, done;
6187  __ EnumLength(result, map);
6188  __ cmp(result, Immediate(Smi::FromInt(0)));
6189  __ j(not_equal, &load_cache, Label::kNear);
6190  __ mov(result, isolate()->factory()->empty_fixed_array());
6191  __ jmp(&done, Label::kNear);
6192
6193  __ bind(&load_cache);
6194  __ LoadInstanceDescriptors(map, result);
6195  __ mov(result,
6196         FieldOperand(result, DescriptorArray::kEnumCacheOffset));
6197  __ mov(result,
6198         FieldOperand(result, FixedArray::SizeFor(instr->idx())));
6199  __ bind(&done);
6200  __ test(result, result);
6201  DeoptimizeIf(equal, instr, "no cache");
6202}
6203
6204
6205void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6206  Register object = ToRegister(instr->value());
6207  __ cmp(ToRegister(instr->map()),
6208         FieldOperand(object, HeapObject::kMapOffset));
6209  DeoptimizeIf(not_equal, instr, "wrong map");
6210}
6211
6212
6213void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
6214                                           Register object,
6215                                           Register index) {
6216  PushSafepointRegistersScope scope(this);
6217  __ push(object);
6218  __ push(index);
6219  __ xor_(esi, esi);
6220  __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
6221  RecordSafepointWithRegisters(
6222      instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
6223  __ StoreToSafepointRegisterSlot(object, eax);
6224}
6225
6226
6227void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6228  class DeferredLoadMutableDouble FINAL : public LDeferredCode {
6229   public:
6230    DeferredLoadMutableDouble(LCodeGen* codegen,
6231                              LLoadFieldByIndex* instr,
6232                              Register object,
6233                              Register index,
6234                              const X87Stack& x87_stack)
6235        : LDeferredCode(codegen, x87_stack),
6236          instr_(instr),
6237          object_(object),
6238          index_(index) {
6239    }
6240    virtual void Generate() OVERRIDE {
6241      codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
6242    }
6243    virtual LInstruction* instr() OVERRIDE { return instr_; }
6244   private:
6245    LLoadFieldByIndex* instr_;
6246    Register object_;
6247    Register index_;
6248  };
6249
6250  Register object = ToRegister(instr->object());
6251  Register index = ToRegister(instr->index());
6252
6253  DeferredLoadMutableDouble* deferred;
6254  deferred = new(zone()) DeferredLoadMutableDouble(
6255      this, instr, object, index, x87_stack_);
6256
6257  Label out_of_object, done;
6258  __ test(index, Immediate(Smi::FromInt(1)));
6259  __ j(not_zero, deferred->entry());
6260
6261  __ sar(index, 1);
6262
6263  __ cmp(index, Immediate(0));
6264  __ j(less, &out_of_object, Label::kNear);
6265  __ mov(object, FieldOperand(object,
6266                              index,
6267                              times_half_pointer_size,
6268                              JSObject::kHeaderSize));
6269  __ jmp(&done, Label::kNear);
6270
6271  __ bind(&out_of_object);
6272  __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset));
6273  __ neg(index);
6274  // Index is now equal to out of object property index plus 1.
6275  __ mov(object, FieldOperand(object,
6276                              index,
6277                              times_half_pointer_size,
6278                              FixedArray::kHeaderSize - kPointerSize));
6279  __ bind(deferred->exit());
6280  __ bind(&done);
6281}
6282
6283
6284void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
6285  Register context = ToRegister(instr->context());
6286  __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), context);
6287}
6288
6289
6290void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) {
6291  Handle<ScopeInfo> scope_info = instr->scope_info();
6292  __ Push(scope_info);
6293  __ push(ToRegister(instr->function()));
6294  CallRuntime(Runtime::kPushBlockContext, 2, instr);
6295  RecordSafepoint(Safepoint::kNoLazyDeopt);
6296}
6297
6298
6299#undef __
6300
6301} }  // namespace v8::internal
6302
6303#endif  // V8_TARGET_ARCH_X87
6304