// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

#if V8_TARGET_ARCH_X87

#include "src/base/bits.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
#include "src/codegen.h"
#include "src/deoptimizer.h"
#include "src/hydrogen-osr.h"
#include "src/ic/ic.h"
#include "src/ic/stub-cache.h"
#include "src/x87/lithium-codegen-x87.h"

namespace v8 {
namespace internal {


// When invoking builtins, we need to record the safepoint in the middle of
// the invoke instruction sequence generated by the macro assembler.
class SafepointGenerator FINAL : public CallWrapper {
 public:
  SafepointGenerator(LCodeGen* codegen,
                     LPointerMap* pointers,
                     Safepoint::DeoptMode mode)
      : codegen_(codegen),
        pointers_(pointers),
        deopt_mode_(mode) {}
  virtual ~SafepointGenerator() {}

  void BeforeCall(int call_size) const OVERRIDE {}

  void AfterCall() const OVERRIDE {
    codegen_->RecordSafepoint(pointers_, deopt_mode_);
  }

 private:
  LCodeGen* codegen_;
  LPointerMap* pointers_;
  Safepoint::DeoptMode deopt_mode_;
};


#define __ masm()->

bool LCodeGen::GenerateCode() {
  LPhase phase("Z_Code generation", chunk());
  DCHECK(is_unused());
  status_ = GENERATING;

  // Open a frame scope to indicate that there is a frame on the stack.  The
  // MANUAL indicates that the scope shouldn't actually generate code to set up
  // the frame (that is done in GeneratePrologue).
  FrameScope frame_scope(masm_, StackFrame::MANUAL);

  support_aligned_spilled_doubles_ = info()->IsOptimizing();

  dynamic_frame_alignment_ = info()->IsOptimizing() &&
      ((chunk()->num_double_slots() > 2 &&
        !chunk()->graph()->is_recursive()) ||
       !info()->osr_ast_id().IsNone());

  return GeneratePrologue() &&
      GenerateBody() &&
      GenerateDeferredCode() &&
      GenerateJumpTable() &&
      GenerateSafepointTable();
}


void LCodeGen::FinishCode(Handle<Code> code) {
  DCHECK(is_done());
  code->set_stack_slots(GetStackSlotCount());
  code->set_safepoint_table_offset(safepoints_.GetCodeOffset());
  if (code->is_optimized_code()) RegisterWeakObjectsInOptimizedCode(code);
  PopulateDeoptimizationData(code);
  if (!info()->IsStub()) {
    Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(code);
  }
}


#ifdef _MSC_VER
void LCodeGen::MakeSureStackPagesMapped(int offset) {
  const int kPageSize = 4 * KB;
  for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
    __ mov(Operand(esp, offset), eax);
  }
}
#endif


bool LCodeGen::GeneratePrologue() {
  DCHECK(is_generating());

  if (info()->IsOptimizing()) {
    ProfileEntryHookStub::MaybeCallEntryHook(masm_);

#ifdef DEBUG
    if (strlen(FLAG_stop_at) > 0 &&
        info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
      __ int3();
    }
#endif

    // Sloppy mode functions and builtins need to replace the receiver with the
    // global proxy when called as functions (without an explicit receiver
    // object).
    if (info_->this_has_uses() &&
        info_->strict_mode() == SLOPPY &&
        !info_->is_native()) {
      Label ok;
      // +1 for return address.
      int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
      __ mov(ecx, Operand(esp, receiver_offset));

      __ cmp(ecx, isolate()->factory()->undefined_value());
      __ j(not_equal, &ok, Label::kNear);

      __ mov(ecx, GlobalObjectOperand());
      __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));

      __ mov(Operand(esp, receiver_offset), ecx);

      __ bind(&ok);
    }

    if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
      // Move state of dynamic frame alignment into edx.
      __ Move(edx, Immediate(kNoAlignmentPadding));

      Label do_not_pad, align_loop;
      STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
      // Align esp + 4 to a multiple of 2 * kPointerSize.
      __ test(esp, Immediate(kPointerSize));
      __ j(not_zero, &do_not_pad, Label::kNear);
      __ push(Immediate(0));
      __ mov(ebx, esp);
      __ mov(edx, Immediate(kAlignmentPaddingPushed));
      // Copy arguments, receiver, and return address.
      __ mov(ecx, Immediate(scope()->num_parameters() + 2));

      __ bind(&align_loop);
      __ mov(eax, Operand(ebx, 1 * kPointerSize));
      __ mov(Operand(ebx, 0), eax);
      __ add(Operand(ebx), Immediate(kPointerSize));
      __ dec(ecx);
      __ j(not_zero, &align_loop, Label::kNear);
      __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue));
      __ bind(&do_not_pad);
    }
  }

  info()->set_prologue_offset(masm_->pc_offset());
  if (NeedsEagerFrame()) {
    DCHECK(!frame_is_built_);
    frame_is_built_ = true;
    if (info()->IsStub()) {
      __ StubPrologue();
    } else {
      __ Prologue(info()->IsCodePreAgingActive());
    }
    info()->AddNoFrameRange(0, masm_->pc_offset());
  }

  if (info()->IsOptimizing() &&
      dynamic_frame_alignment_ &&
      FLAG_debug_code) {
    __ test(esp, Immediate(kPointerSize));
    __ Assert(zero, kFrameIsExpectedToBeAligned);
  }

  // Reserve space for the stack slots needed by the code.
  int slots = GetStackSlotCount();
  DCHECK(slots != 0 || !info()->IsOptimizing());
  if (slots > 0) {
    if (slots == 1) {
      if (dynamic_frame_alignment_) {
        __ push(edx);
      } else {
        __ push(Immediate(kNoAlignmentPadding));
      }
    } else {
      if (FLAG_debug_code) {
        __ sub(Operand(esp), Immediate(slots * kPointerSize));
#ifdef _MSC_VER
        MakeSureStackPagesMapped(slots * kPointerSize);
#endif
        __ push(eax);
        __ mov(Operand(eax), Immediate(slots));
        Label loop;
        __ bind(&loop);
        __ mov(MemOperand(esp, eax, times_4, 0),
               Immediate(kSlotsZapValue));
        __ dec(eax);
        __ j(not_zero, &loop);
        __ pop(eax);
      } else {
        __ sub(Operand(esp), Immediate(slots * kPointerSize));
#ifdef _MSC_VER
        MakeSureStackPagesMapped(slots * kPointerSize);
#endif
      }

      if (support_aligned_spilled_doubles_) {
        Comment(";;; Store dynamic frame alignment tag for spilled doubles");
        // Store dynamic frame alignment state in the first local.
        int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset;
        if (dynamic_frame_alignment_) {
          __ mov(Operand(ebp, offset), edx);
        } else {
          __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding));
        }
      }
    }
  }

  // Possibly allocate a local context.
  int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
  if (heap_slots > 0) {
    Comment(";;; Allocate local context");
    bool need_write_barrier = true;
    // Argument to NewContext is the function, which is still in edi.
    if (heap_slots <= FastNewContextStub::kMaximumSlots) {
      FastNewContextStub stub(isolate(), heap_slots);
      __ CallStub(&stub);
      // Result of FastNewContextStub is always in new space.
      need_write_barrier = false;
    } else {
      __ push(edi);
      __ CallRuntime(Runtime::kNewFunctionContext, 1);
    }
    RecordSafepoint(Safepoint::kNoLazyDeopt);
    // Context is returned in eax.  It replaces the context passed to us.
    // It's saved in the stack and kept live in esi.
    __ mov(esi, eax);
    __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);

    // Copy parameters into context if necessary.
    int num_parameters = scope()->num_parameters();
    for (int i = 0; i < num_parameters; i++) {
      Variable* var = scope()->parameter(i);
      if (var->IsContextSlot()) {
        int parameter_offset = StandardFrameConstants::kCallerSPOffset +
            (num_parameters - 1 - i) * kPointerSize;
        // Load parameter from stack.
        __ mov(eax, Operand(ebp, parameter_offset));
        // Store it in the context.
        int context_offset = Context::SlotOffset(var->index());
        __ mov(Operand(esi, context_offset), eax);
        // Update the write barrier. This clobbers eax and ebx.
        if (need_write_barrier) {
          __ RecordWriteContextSlot(esi, context_offset, eax, ebx,
                                    kDontSaveFPRegs);
        } else if (FLAG_debug_code) {
          Label done;
          __ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
          __ Abort(kExpectedNewSpaceObject);
          __ bind(&done);
        }
      }
    }
    Comment(";;; End allocate local context");
  }

  // Initailize FPU state.
  __ fninit();
  // Trace the call.
  if (FLAG_trace && info()->IsOptimizing()) {
    // We have not executed any compiled code yet, so esi still holds the
    // incoming context.
    __ CallRuntime(Runtime::kTraceEnter, 0);
  }
  return !is_aborted();
}


void LCodeGen::GenerateOsrPrologue() {
  // Generate the OSR entry prologue at the first unknown OSR value, or if there
  // are none, at the OSR entrypoint instruction.
  if (osr_pc_offset_ >= 0) return;

  osr_pc_offset_ = masm()->pc_offset();

    // Move state of dynamic frame alignment into edx.
  __ Move(edx, Immediate(kNoAlignmentPadding));

  if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
    Label do_not_pad, align_loop;
    // Align ebp + 4 to a multiple of 2 * kPointerSize.
    __ test(ebp, Immediate(kPointerSize));
    __ j(zero, &do_not_pad, Label::kNear);
    __ push(Immediate(0));
    __ mov(ebx, esp);
    __ mov(edx, Immediate(kAlignmentPaddingPushed));

    // Move all parts of the frame over one word. The frame consists of:
    // unoptimized frame slots, alignment state, context, frame pointer, return
    // address, receiver, and the arguments.
    __ mov(ecx, Immediate(scope()->num_parameters() +
           5 + graph()->osr()->UnoptimizedFrameSlots()));

    __ bind(&align_loop);
    __ mov(eax, Operand(ebx, 1 * kPointerSize));
    __ mov(Operand(ebx, 0), eax);
    __ add(Operand(ebx), Immediate(kPointerSize));
    __ dec(ecx);
    __ j(not_zero, &align_loop, Label::kNear);
    __ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue));
    __ sub(Operand(ebp), Immediate(kPointerSize));
    __ bind(&do_not_pad);
  }

  // Save the first local, which is overwritten by the alignment state.
  Operand alignment_loc = MemOperand(ebp, -3 * kPointerSize);
  __ push(alignment_loc);

  // Set the dynamic frame alignment state.
  __ mov(alignment_loc, edx);

  // Adjust the frame size, subsuming the unoptimized frame into the
  // optimized frame.
  int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
  DCHECK(slots >= 1);
  __ sub(esp, Immediate((slots - 1) * kPointerSize));

  // Initailize FPU state.
  __ fninit();
}


void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
  if (instr->IsCall()) {
    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
  }
  if (!instr->IsLazyBailout() && !instr->IsGap()) {
    safepoints_.BumpLastLazySafepointIndex();
  }
  FlushX87StackIfNecessary(instr);
}


void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) {
  // When return from function call, FPU should be initialized again.
  if (instr->IsCall() && instr->ClobbersDoubleRegisters(isolate())) {
    bool double_result = instr->HasDoubleRegisterResult();
    if (double_result) {
      __ lea(esp, Operand(esp, -kDoubleSize));
      __ fstp_d(Operand(esp, 0));
    }
    __ fninit();
    if (double_result) {
      __ fld_d(Operand(esp, 0));
      __ lea(esp, Operand(esp, kDoubleSize));
    }
  }
  if (instr->IsGoto()) {
    x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr), this);
  } else if (FLAG_debug_code && FLAG_enable_slow_asserts &&
             !instr->IsGap() && !instr->IsReturn()) {
    if (instr->ClobbersDoubleRegisters(isolate())) {
      if (instr->HasDoubleRegisterResult()) {
        DCHECK_EQ(1, x87_stack_.depth());
      } else {
        DCHECK_EQ(0, x87_stack_.depth());
      }
    }
    __ VerifyX87StackDepth(x87_stack_.depth());
  }
}


bool LCodeGen::GenerateJumpTable() {
  Label needs_frame;
  if (jump_table_.length() > 0) {
    Comment(";;; -------------------- Jump table --------------------");
  }
  for (int i = 0; i < jump_table_.length(); i++) {
    Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i];
    __ bind(&table_entry->label);
    Address entry = table_entry->address;
    DeoptComment(table_entry->reason);
    if (table_entry->needs_frame) {
      DCHECK(!info()->saves_caller_doubles());
      __ push(Immediate(ExternalReference::ForDeoptEntry(entry)));
      if (needs_frame.is_bound()) {
        __ jmp(&needs_frame);
      } else {
        __ bind(&needs_frame);
        __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset));
        // This variant of deopt can only be used with stubs. Since we don't
        // have a function pointer to install in the stack frame that we're
        // building, install a special marker there instead.
        DCHECK(info()->IsStub());
        __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
        // Push a PC inside the function so that the deopt code can find where
        // the deopt comes from. It doesn't have to be the precise return
        // address of a "calling" LAZY deopt, it only has to be somewhere
        // inside the code body.
        Label push_approx_pc;
        __ call(&push_approx_pc);
        __ bind(&push_approx_pc);
        // Push the continuation which was stashed were the ebp should
        // be. Replace it with the saved ebp.
        __ push(MemOperand(esp, 3 * kPointerSize));
        __ mov(MemOperand(esp, 4 * kPointerSize), ebp);
        __ lea(ebp, MemOperand(esp, 4 * kPointerSize));
        __ ret(0);  // Call the continuation without clobbering registers.
      }
    } else {
      __ call(entry, RelocInfo::RUNTIME_ENTRY);
    }
  }
  return !is_aborted();
}


bool LCodeGen::GenerateDeferredCode() {
  DCHECK(is_generating());
  if (deferred_.length() > 0) {
    for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
      LDeferredCode* code = deferred_[i];
      X87Stack copy(code->x87_stack());
      x87_stack_ = copy;

      HValue* value =
          instructions_->at(code->instruction_index())->hydrogen_value();
      RecordAndWritePosition(
          chunk()->graph()->SourcePositionToScriptPosition(value->position()));

      Comment(";;; <@%d,#%d> "
              "-------------------- Deferred %s --------------------",
              code->instruction_index(),
              code->instr()->hydrogen_value()->id(),
              code->instr()->Mnemonic());
      __ bind(code->entry());
      if (NeedsDeferredFrame()) {
        Comment(";;; Build frame");
        DCHECK(!frame_is_built_);
        DCHECK(info()->IsStub());
        frame_is_built_ = true;
        // Build the frame in such a way that esi isn't trashed.
        __ push(ebp);  // Caller's frame pointer.
        __ push(Operand(ebp, StandardFrameConstants::kContextOffset));
        __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
        __ lea(ebp, Operand(esp, 2 * kPointerSize));
        Comment(";;; Deferred code");
      }
      code->Generate();
      if (NeedsDeferredFrame()) {
        __ bind(code->done());
        Comment(";;; Destroy frame");
        DCHECK(frame_is_built_);
        frame_is_built_ = false;
        __ mov(esp, ebp);
        __ pop(ebp);
      }
      __ jmp(code->exit());
    }
  }

  // Deferred code is the last part of the instruction sequence. Mark
  // the generated code as done unless we bailed out.
  if (!is_aborted()) status_ = DONE;
  return !is_aborted();
}


bool LCodeGen::GenerateSafepointTable() {
  DCHECK(is_done());
  if (!info()->IsStub()) {
    // For lazy deoptimization we need space to patch a call after every call.
    // Ensure there is always space for such patching, even if the code ends
    // in a call.
    int target_offset = masm()->pc_offset() + Deoptimizer::patch_size();
    while (masm()->pc_offset() < target_offset) {
      masm()->nop();
    }
  }
  safepoints_.Emit(masm(), GetStackSlotCount());
  return !is_aborted();
}


Register LCodeGen::ToRegister(int index) const {
  return Register::FromAllocationIndex(index);
}


X87Register LCodeGen::ToX87Register(int index) const {
  return X87Register::FromAllocationIndex(index);
}


void LCodeGen::X87LoadForUsage(X87Register reg) {
  DCHECK(x87_stack_.Contains(reg));
  x87_stack_.Fxch(reg);
  x87_stack_.pop();
}


void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) {
  DCHECK(x87_stack_.Contains(reg1));
  DCHECK(x87_stack_.Contains(reg2));
  if (reg1.is(reg2) && x87_stack_.depth() == 1) {
    __ fld(x87_stack_.st(reg1));
    x87_stack_.push(reg1);
    x87_stack_.pop();
    x87_stack_.pop();
  } else {
    x87_stack_.Fxch(reg1, 1);
    x87_stack_.Fxch(reg2);
    x87_stack_.pop();
    x87_stack_.pop();
  }
}


int LCodeGen::X87Stack::GetLayout() {
  int layout = stack_depth_;
  for (int i = 0; i < stack_depth_; i++) {
    layout |= (stack_[stack_depth_ - 1 - i].code() << ((i + 1) * 3));
  }

  return layout;
}


void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
  DCHECK(is_mutable_);
  DCHECK(Contains(reg) && stack_depth_ > other_slot);
  int i  = ArrayIndex(reg);
  int st = st2idx(i);
  if (st != other_slot) {
    int other_i = st2idx(other_slot);
    X87Register other = stack_[other_i];
    stack_[other_i]   = reg;
    stack_[i]         = other;
    if (st == 0) {
      __ fxch(other_slot);
    } else if (other_slot == 0) {
      __ fxch(st);
    } else {
      __ fxch(st);
      __ fxch(other_slot);
      __ fxch(st);
    }
  }
}


int LCodeGen::X87Stack::st2idx(int pos) {
  return stack_depth_ - pos - 1;
}


int LCodeGen::X87Stack::ArrayIndex(X87Register reg) {
  for (int i = 0; i < stack_depth_; i++) {
    if (stack_[i].is(reg)) return i;
  }
  UNREACHABLE();
  return -1;
}


bool LCodeGen::X87Stack::Contains(X87Register reg) {
  for (int i = 0; i < stack_depth_; i++) {
    if (stack_[i].is(reg)) return true;
  }
  return false;
}


void LCodeGen::X87Stack::Free(X87Register reg) {
  DCHECK(is_mutable_);
  DCHECK(Contains(reg));
  int i  = ArrayIndex(reg);
  int st = st2idx(i);
  if (st > 0) {
    // keep track of how fstp(i) changes the order of elements
    int tos_i = st2idx(0);
    stack_[i] = stack_[tos_i];
  }
  pop();
  __ fstp(st);
}


void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
  if (x87_stack_.Contains(dst)) {
    x87_stack_.Fxch(dst);
    __ fstp(0);
  } else {
    x87_stack_.push(dst);
  }
  X87Fld(src, opts);
}


void LCodeGen::X87Mov(X87Register dst, X87Register src, X87OperandType opts) {
  if (x87_stack_.Contains(dst)) {
    x87_stack_.Fxch(dst);
    __ fstp(0);
    x87_stack_.pop();
    // Push ST(i) onto the FPU register stack
    __ fld(x87_stack_.st(src));
    x87_stack_.push(dst);
  } else {
    // Push ST(i) onto the FPU register stack
    __ fld(x87_stack_.st(src));
    x87_stack_.push(dst);
  }
}


void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
  DCHECK(!src.is_reg_only());
  switch (opts) {
    case kX87DoubleOperand:
      __ fld_d(src);
      break;
    case kX87FloatOperand:
      __ fld_s(src);
      break;
    case kX87IntOperand:
      __ fild_s(src);
      break;
    default:
      UNREACHABLE();
  }
}


void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
  DCHECK(!dst.is_reg_only());
  x87_stack_.Fxch(src);
  switch (opts) {
    case kX87DoubleOperand:
      __ fst_d(dst);
      break;
    case kX87FloatOperand:
      __ fst_s(dst);
      break;
    case kX87IntOperand:
      __ fist_s(dst);
      break;
    default:
      UNREACHABLE();
  }
}


void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
  DCHECK(is_mutable_);
  if (Contains(reg)) {
    Free(reg);
  }
  // Mark this register as the next register to write to
  stack_[stack_depth_] = reg;
}


void LCodeGen::X87Stack::CommitWrite(X87Register reg) {
  DCHECK(is_mutable_);
  // Assert the reg is prepared to write, but not on the virtual stack yet
  DCHECK(!Contains(reg) && stack_[stack_depth_].is(reg) &&
      stack_depth_ < X87Register::kMaxNumAllocatableRegisters);
  stack_depth_++;
}


void LCodeGen::X87PrepareBinaryOp(
    X87Register left, X87Register right, X87Register result) {
  // You need to use DefineSameAsFirst for x87 instructions
  DCHECK(result.is(left));
  x87_stack_.Fxch(right, 1);
  x87_stack_.Fxch(left);
}


void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
  if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters(isolate())) {
    bool double_inputs = instr->HasDoubleRegisterInput();

    // Flush stack from tos down, since FreeX87() will mess with tos
    for (int i = stack_depth_-1; i >= 0; i--) {
      X87Register reg = stack_[i];
      // Skip registers which contain the inputs for the next instruction
      // when flushing the stack
      if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
        continue;
      }
      Free(reg);
      if (i < stack_depth_-1) i++;
    }
  }
  if (instr->IsReturn()) {
    while (stack_depth_ > 0) {
      __ fstp(0);
      stack_depth_--;
    }
    if (FLAG_debug_code && FLAG_enable_slow_asserts) __ VerifyX87StackDepth(0);
  }
}


void LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr,
                                      LCodeGen* cgen) {
  // For going to a joined block, an explicit LClobberDoubles is inserted before
  // LGoto. Because all used x87 registers are spilled to stack slots. The
  // ResolvePhis phase of register allocator could guarantee the two input's x87
  // stacks have the same layout. So don't check stack_depth_ <= 1 here.
  int goto_block_id = goto_instr->block_id();
  if (current_block_id + 1 != goto_block_id) {
    // If we have a value on the x87 stack on leaving a block, it must be a
    // phi input. If the next block we compile is not the join block, we have
    // to discard the stack state.
    // Before discarding the stack state, we need to save it if the "goto block"
    // has unreachable last predecessor when FLAG_unreachable_code_elimination.
    if (FLAG_unreachable_code_elimination) {
      int length = goto_instr->block()->predecessors()->length();
      bool has_unreachable_last_predecessor = false;
      for (int i = 0; i < length; i++) {
        HBasicBlock* block = goto_instr->block()->predecessors()->at(i);
        if (block->IsUnreachable() &&
            (block->block_id() + 1) == goto_block_id) {
          has_unreachable_last_predecessor = true;
        }
      }
      if (has_unreachable_last_predecessor) {
        if (cgen->x87_stack_map_.find(goto_block_id) ==
            cgen->x87_stack_map_.end()) {
          X87Stack* stack = new (cgen->zone()) X87Stack(*this);
          cgen->x87_stack_map_.insert(std::make_pair(goto_block_id, stack));
        }
      }
    }

    // Discard the stack state.
    stack_depth_ = 0;
  }
}


void LCodeGen::EmitFlushX87ForDeopt() {
  // The deoptimizer does not support X87 Registers. But as long as we
  // deopt from a stub its not a problem, since we will re-materialize the
  // original stub inputs, which can't be double registers.
  // DCHECK(info()->IsStub());
  if (FLAG_debug_code && FLAG_enable_slow_asserts) {
    __ pushfd();
    __ VerifyX87StackDepth(x87_stack_.depth());
    __ popfd();
  }

  // Flush X87 stack in the deoptimizer entry.
}


Register LCodeGen::ToRegister(LOperand* op) const {
  DCHECK(op->IsRegister());
  return ToRegister(op->index());
}


X87Register LCodeGen::ToX87Register(LOperand* op) const {
  DCHECK(op->IsDoubleRegister());
  return ToX87Register(op->index());
}


int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
  return ToRepresentation(op, Representation::Integer32());
}


int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
                                   const Representation& r) const {
  HConstant* constant = chunk_->LookupConstant(op);
  int32_t value = constant->Integer32Value();
  if (r.IsInteger32()) return value;
  DCHECK(r.IsSmiOrTagged());
  return reinterpret_cast<int32_t>(Smi::FromInt(value));
}


Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
  HConstant* constant = chunk_->LookupConstant(op);
  DCHECK(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged());
  return constant->handle(isolate());
}


double LCodeGen::ToDouble(LConstantOperand* op) const {
  HConstant* constant = chunk_->LookupConstant(op);
  DCHECK(constant->HasDoubleValue());
  return constant->DoubleValue();
}


ExternalReference LCodeGen::ToExternalReference(LConstantOperand* op) const {
  HConstant* constant = chunk_->LookupConstant(op);
  DCHECK(constant->HasExternalReferenceValue());
  return constant->ExternalReferenceValue();
}


bool LCodeGen::IsInteger32(LConstantOperand* op) const {
  return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
}


bool LCodeGen::IsSmi(LConstantOperand* op) const {
  return chunk_->LookupLiteralRepresentation(op).IsSmi();
}


static int ArgumentsOffsetWithoutFrame(int index) {
  DCHECK(index < 0);
  return -(index + 1) * kPointerSize + kPCOnStackSize;
}


Operand LCodeGen::ToOperand(LOperand* op) const {
  if (op->IsRegister()) return Operand(ToRegister(op));
  DCHECK(!op->IsDoubleRegister());
  DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
  if (NeedsEagerFrame()) {
    return Operand(ebp, StackSlotOffset(op->index()));
  } else {
    // Retrieve parameter without eager stack-frame relative to the
    // stack-pointer.
    return Operand(esp, ArgumentsOffsetWithoutFrame(op->index()));
  }
}


Operand LCodeGen::HighOperand(LOperand* op) {
  DCHECK(op->IsDoubleStackSlot());
  if (NeedsEagerFrame()) {
    return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize);
  } else {
    // Retrieve parameter without eager stack-frame relative to the
    // stack-pointer.
    return Operand(
        esp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
  }
}


void LCodeGen::WriteTranslation(LEnvironment* environment,
                                Translation* translation) {
  if (environment == NULL) return;

  // The translation includes one command per value in the environment.
  int translation_size = environment->translation_size();
  // The output frame height does not include the parameters.
  int height = translation_size - environment->parameter_count();

  WriteTranslation(environment->outer(), translation);
  bool has_closure_id = !info()->closure().is_null() &&
      !info()->closure().is_identical_to(environment->closure());
  int closure_id = has_closure_id
      ? DefineDeoptimizationLiteral(environment->closure())
      : Translation::kSelfLiteralId;
  switch (environment->frame_type()) {
    case JS_FUNCTION:
      translation->BeginJSFrame(environment->ast_id(), closure_id, height);
      break;
    case JS_CONSTRUCT:
      translation->BeginConstructStubFrame(closure_id, translation_size);
      break;
    case JS_GETTER:
      DCHECK(translation_size == 1);
      DCHECK(height == 0);
      translation->BeginGetterStubFrame(closure_id);
      break;
    case JS_SETTER:
      DCHECK(translation_size == 2);
      DCHECK(height == 0);
      translation->BeginSetterStubFrame(closure_id);
      break;
    case ARGUMENTS_ADAPTOR:
      translation->BeginArgumentsAdaptorFrame(closure_id, translation_size);
      break;
    case STUB:
      translation->BeginCompiledStubFrame();
      break;
    default:
      UNREACHABLE();
  }

  int object_index = 0;
  int dematerialized_index = 0;
  for (int i = 0; i < translation_size; ++i) {
    LOperand* value = environment->values()->at(i);
    AddToTranslation(environment,
                     translation,
                     value,
                     environment->HasTaggedValueAt(i),
                     environment->HasUint32ValueAt(i),
                     &object_index,
                     &dematerialized_index);
  }
}


void LCodeGen::AddToTranslation(LEnvironment* environment,
                                Translation* translation,
                                LOperand* op,
                                bool is_tagged,
                                bool is_uint32,
                                int* object_index_pointer,
                                int* dematerialized_index_pointer) {
  if (op == LEnvironment::materialization_marker()) {
    int object_index = (*object_index_pointer)++;
    if (environment->ObjectIsDuplicateAt(object_index)) {
      int dupe_of = environment->ObjectDuplicateOfAt(object_index);
      translation->DuplicateObject(dupe_of);
      return;
    }
    int object_length = environment->ObjectLengthAt(object_index);
    if (environment->ObjectIsArgumentsAt(object_index)) {
      translation->BeginArgumentsObject(object_length);
    } else {
      translation->BeginCapturedObject(object_length);
    }
    int dematerialized_index = *dematerialized_index_pointer;
    int env_offset = environment->translation_size() + dematerialized_index;
    *dematerialized_index_pointer += object_length;
    for (int i = 0; i < object_length; ++i) {
      LOperand* value = environment->values()->at(env_offset + i);
      AddToTranslation(environment,
                       translation,
                       value,
                       environment->HasTaggedValueAt(env_offset + i),
                       environment->HasUint32ValueAt(env_offset + i),
                       object_index_pointer,
                       dematerialized_index_pointer);
    }
    return;
  }

  if (op->IsStackSlot()) {
    if (is_tagged) {
      translation->StoreStackSlot(op->index());
    } else if (is_uint32) {
      translation->StoreUint32StackSlot(op->index());
    } else {
      translation->StoreInt32StackSlot(op->index());
    }
  } else if (op->IsDoubleStackSlot()) {
    translation->StoreDoubleStackSlot(op->index());
  } else if (op->IsRegister()) {
    Register reg = ToRegister(op);
    if (is_tagged) {
      translation->StoreRegister(reg);
    } else if (is_uint32) {
      translation->StoreUint32Register(reg);
    } else {
      translation->StoreInt32Register(reg);
    }
  } else if (op->IsDoubleRegister()) {
    X87Register reg = ToX87Register(op);
    translation->StoreDoubleRegister(reg);
  } else if (op->IsConstantOperand()) {
    HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
    int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
    translation->StoreLiteral(src_index);
  } else {
    UNREACHABLE();
  }
}


void LCodeGen::CallCodeGeneric(Handle<Code> code,
                               RelocInfo::Mode mode,
                               LInstruction* instr,
                               SafepointMode safepoint_mode) {
  DCHECK(instr != NULL);
  __ call(code, mode);
  RecordSafepointWithLazyDeopt(instr, safepoint_mode);

  // Signal that we don't inline smi code before these stubs in the
  // optimizing code generator.
  if (code->kind() == Code::BINARY_OP_IC ||
      code->kind() == Code::COMPARE_IC) {
    __ nop();
  }
}


void LCodeGen::CallCode(Handle<Code> code,
                        RelocInfo::Mode mode,
                        LInstruction* instr) {
  CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
}


void LCodeGen::CallRuntime(const Runtime::Function* fun, int argc,
                           LInstruction* instr, SaveFPRegsMode save_doubles) {
  DCHECK(instr != NULL);
  DCHECK(instr->HasPointerMap());

  __ CallRuntime(fun, argc, save_doubles);

  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);

  DCHECK(info()->is_calling());
}


void LCodeGen::LoadContextFromDeferred(LOperand* context) {
  if (context->IsRegister()) {
    if (!ToRegister(context).is(esi)) {
      __ mov(esi, ToRegister(context));
    }
  } else if (context->IsStackSlot()) {
    __ mov(esi, ToOperand(context));
  } else if (context->IsConstantOperand()) {
    HConstant* constant =
        chunk_->LookupConstant(LConstantOperand::cast(context));
    __ LoadObject(esi, Handle<Object>::cast(constant->handle(isolate())));
  } else {
    UNREACHABLE();
  }
}

void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
                                       int argc,
                                       LInstruction* instr,
                                       LOperand* context) {
  LoadContextFromDeferred(context);

  __ CallRuntimeSaveDoubles(id);
  RecordSafepointWithRegisters(
      instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);

  DCHECK(info()->is_calling());
}


void LCodeGen::RegisterEnvironmentForDeoptimization(
    LEnvironment* environment, Safepoint::DeoptMode mode) {
  environment->set_has_been_used();
  if (!environment->HasBeenRegistered()) {
    // Physical stack frame layout:
    // -x ............. -4  0 ..................................... y
    // [incoming arguments] [spill slots] [pushed outgoing arguments]

    // Layout of the environment:
    // 0 ..................................................... size-1
    // [parameters] [locals] [expression stack including arguments]

    // Layout of the translation:
    // 0 ........................................................ size - 1 + 4
    // [expression stack including arguments] [locals] [4 words] [parameters]
    // |>------------  translation_size ------------<|

    int frame_count = 0;
    int jsframe_count = 0;
    for (LEnvironment* e = environment; e != NULL; e = e->outer()) {
      ++frame_count;
      if (e->frame_type() == JS_FUNCTION) {
        ++jsframe_count;
      }
    }
    Translation translation(&translations_, frame_count, jsframe_count, zone());
    WriteTranslation(environment, &translation);
    int deoptimization_index = deoptimizations_.length();
    int pc_offset = masm()->pc_offset();
    environment->Register(deoptimization_index,
                          translation.index(),
                          (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
    deoptimizations_.Add(environment, zone());
  }
}


void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
                            const char* detail,
                            Deoptimizer::BailoutType bailout_type) {
  LEnvironment* environment = instr->environment();
  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
  DCHECK(environment->HasBeenRegistered());
  int id = environment->deoptimization_index();
  DCHECK(info()->IsOptimizing() || info()->IsStub());
  Address entry =
      Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
  if (entry == NULL) {
    Abort(kBailoutWasNotPrepared);
    return;
  }

  if (DeoptEveryNTimes()) {
    ExternalReference count = ExternalReference::stress_deopt_count(isolate());
    Label no_deopt;
    __ pushfd();
    __ push(eax);
    __ mov(eax, Operand::StaticVariable(count));
    __ sub(eax, Immediate(1));
    __ j(not_zero, &no_deopt, Label::kNear);
    if (FLAG_trap_on_deopt) __ int3();
    __ mov(eax, Immediate(FLAG_deopt_every_n_times));
    __ mov(Operand::StaticVariable(count), eax);
    __ pop(eax);
    __ popfd();
    DCHECK(frame_is_built_);
    // Put the x87 stack layout in TOS.
    if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();
    __ push(Immediate(x87_stack_.GetLayout()));
    __ fild_s(MemOperand(esp, 0));
    // Don't touch eflags.
    __ lea(esp, Operand(esp, kPointerSize));
    __ call(entry, RelocInfo::RUNTIME_ENTRY);
    __ bind(&no_deopt);
    __ mov(Operand::StaticVariable(count), eax);
    __ pop(eax);
    __ popfd();
  }

  // Put the x87 stack layout in TOS, so that we can save x87 fp registers in
  // the correct location.
  {
    Label done;
    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
    if (x87_stack_.depth() > 0) EmitFlushX87ForDeopt();

    int x87_stack_layout = x87_stack_.GetLayout();
    __ push(Immediate(x87_stack_layout));
    __ fild_s(MemOperand(esp, 0));
    // Don't touch eflags.
    __ lea(esp, Operand(esp, kPointerSize));
    __ bind(&done);
  }

  if (info()->ShouldTrapOnDeopt()) {
    Label done;
    if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
    __ int3();
    __ bind(&done);
  }

  Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
                             instr->Mnemonic(), detail);
  DCHECK(info()->IsStub() || frame_is_built_);
  if (cc == no_condition && frame_is_built_) {
    DeoptComment(reason);
    __ call(entry, RelocInfo::RUNTIME_ENTRY);
  } else {
    Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type,
                                            !frame_is_built_);
    // We often have several deopts to the same entry, reuse the last
    // jump entry if this is the case.
    if (jump_table_.is_empty() ||
        !table_entry.IsEquivalentTo(jump_table_.last())) {
      jump_table_.Add(table_entry, zone());
    }
    if (cc == no_condition) {
      __ jmp(&jump_table_.last().label);
    } else {
      __ j(cc, &jump_table_.last().label);
    }
  }
}


void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
                            const char* detail) {
  Deoptimizer::BailoutType bailout_type = info()->IsStub()
      ? Deoptimizer::LAZY
      : Deoptimizer::EAGER;
  DeoptimizeIf(cc, instr, detail, bailout_type);
}


void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
  int length = deoptimizations_.length();
  if (length == 0) return;
  Handle<DeoptimizationInputData> data =
      DeoptimizationInputData::New(isolate(), length, TENURED);

  Handle<ByteArray> translations =
      translations_.CreateByteArray(isolate()->factory());
  data->SetTranslationByteArray(*translations);
  data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_));
  data->SetOptimizationId(Smi::FromInt(info_->optimization_id()));
  if (info_->IsOptimizing()) {
    // Reference to shared function info does not change between phases.
    AllowDeferredHandleDereference allow_handle_dereference;
    data->SetSharedFunctionInfo(*info_->shared_info());
  } else {
    data->SetSharedFunctionInfo(Smi::FromInt(0));
  }

  Handle<FixedArray> literals =
      factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
  { AllowDeferredHandleDereference copy_handles;
    for (int i = 0; i < deoptimization_literals_.length(); i++) {
      literals->set(i, *deoptimization_literals_[i]);
    }
    data->SetLiteralArray(*literals);
  }

  data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
  data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));

  // Populate the deoptimization entries.
  for (int i = 0; i < length; i++) {
    LEnvironment* env = deoptimizations_[i];
    data->SetAstId(i, env->ast_id());
    data->SetTranslationIndex(i, Smi::FromInt(env->translation_index()));
    data->SetArgumentsStackHeight(i,
                                  Smi::FromInt(env->arguments_stack_height()));
    data->SetPc(i, Smi::FromInt(env->pc_offset()));
  }
  code->set_deoptimization_data(*data);
}


int LCodeGen::DefineDeoptimizationLiteral(Handle<Object> literal) {
  int result = deoptimization_literals_.length();
  for (int i = 0; i < deoptimization_literals_.length(); ++i) {
    if (deoptimization_literals_[i].is_identical_to(literal)) return i;
  }
  deoptimization_literals_.Add(literal, zone());
  return result;
}


void LCodeGen::PopulateDeoptimizationLiteralsWithInlinedFunctions() {
  DCHECK(deoptimization_literals_.length() == 0);

  const ZoneList<Handle<JSFunction> >* inlined_closures =
      chunk()->inlined_closures();

  for (int i = 0, length = inlined_closures->length();
       i < length;
       i++) {
    DefineDeoptimizationLiteral(inlined_closures->at(i));
  }

  inlined_function_count_ = deoptimization_literals_.length();
}


void LCodeGen::RecordSafepointWithLazyDeopt(
    LInstruction* instr, SafepointMode safepoint_mode) {
  if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
    RecordSafepoint(instr->pointer_map(), Safepoint::kLazyDeopt);
  } else {
    DCHECK(safepoint_mode == RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
    RecordSafepointWithRegisters(
        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
  }
}


void LCodeGen::RecordSafepoint(
    LPointerMap* pointers,
    Safepoint::Kind kind,
    int arguments,
    Safepoint::DeoptMode deopt_mode) {
  DCHECK(kind == expected_safepoint_kind_);
  const ZoneList<LOperand*>* operands = pointers->GetNormalizedOperands();
  Safepoint safepoint =
      safepoints_.DefineSafepoint(masm(), kind, arguments, deopt_mode);
  for (int i = 0; i < operands->length(); i++) {
    LOperand* pointer = operands->at(i);
    if (pointer->IsStackSlot()) {
      safepoint.DefinePointerSlot(pointer->index(), zone());
    } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) {
      safepoint.DefinePointerRegister(ToRegister(pointer), zone());
    }
  }
}


void LCodeGen::RecordSafepoint(LPointerMap* pointers,
                               Safepoint::DeoptMode mode) {
  RecordSafepoint(pointers, Safepoint::kSimple, 0, mode);
}


void LCodeGen::RecordSafepoint(Safepoint::DeoptMode mode) {
  LPointerMap empty_pointers(zone());
  RecordSafepoint(&empty_pointers, mode);
}


void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers,
                                            int arguments,
                                            Safepoint::DeoptMode mode) {
  RecordSafepoint(pointers, Safepoint::kWithRegisters, arguments, mode);
}


void LCodeGen::RecordAndWritePosition(int position) {
  if (position == RelocInfo::kNoPosition) return;
  masm()->positions_recorder()->RecordPosition(position);
  masm()->positions_recorder()->WriteRecordedPositions();
}


static const char* LabelType(LLabel* label) {
  if (label->is_loop_header()) return " (loop header)";
  if (label->is_osr_entry()) return " (OSR entry)";
  return "";
}


void LCodeGen::DoLabel(LLabel* label) {
  Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------",
          current_instruction_,
          label->hydrogen_value()->id(),
          label->block_id(),
          LabelType(label));
  __ bind(label->label());
  current_block_ = label->block_id();
  if (label->block()->predecessors()->length() > 1) {
    // A join block's x87 stack is that of its last visited predecessor.
    // If the last visited predecessor block is unreachable, the stack state
    // will be wrong. In such case, use the x87 stack of reachable predecessor.
    X87StackMap::const_iterator it = x87_stack_map_.find(current_block_);
    // Restore x87 stack.
    if (it != x87_stack_map_.end()) {
      x87_stack_ = *(it->second);
    }
  }
  DoGap(label);
}


void LCodeGen::DoParallelMove(LParallelMove* move) {
  resolver_.Resolve(move);
}


void LCodeGen::DoGap(LGap* gap) {
  for (int i = LGap::FIRST_INNER_POSITION;
       i <= LGap::LAST_INNER_POSITION;
       i++) {
    LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i);
    LParallelMove* move = gap->GetParallelMove(inner_pos);
    if (move != NULL) DoParallelMove(move);
  }
}


void LCodeGen::DoInstructionGap(LInstructionGap* instr) {
  DoGap(instr);
}


void LCodeGen::DoParameter(LParameter* instr) {
  // Nothing to do.
}


void LCodeGen::DoCallStub(LCallStub* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->result()).is(eax));
  switch (instr->hydrogen()->major_key()) {
    case CodeStub::RegExpExec: {
      RegExpExecStub stub(isolate());
      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
      break;
    }
    case CodeStub::SubString: {
      SubStringStub stub(isolate());
      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
      break;
    }
    case CodeStub::StringCompare: {
      StringCompareStub stub(isolate());
      CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
      break;
    }
    default:
      UNREACHABLE();
  }
}


void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
  GenerateOsrPrologue();
}


void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
  Register dividend = ToRegister(instr->dividend());
  int32_t divisor = instr->divisor();
  DCHECK(dividend.is(ToRegister(instr->result())));

  // Theoretically, a variation of the branch-free code for integer division by
  // a power of 2 (calculating the remainder via an additional multiplication
  // (which gets simplified to an 'and') and subtraction) should be faster, and
  // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
  // indicate that positive dividends are heavily favored, so the branching
  // version performs better.
  HMod* hmod = instr->hydrogen();
  int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
  Label dividend_is_not_negative, done;
  if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
    __ test(dividend, dividend);
    __ j(not_sign, &dividend_is_not_negative, Label::kNear);
    // Note that this is correct even for kMinInt operands.
    __ neg(dividend);
    __ and_(dividend, mask);
    __ neg(dividend);
    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
      DeoptimizeIf(zero, instr, "minus zero");
    }
    __ jmp(&done, Label::kNear);
  }

  __ bind(&dividend_is_not_negative);
  __ and_(dividend, mask);
  __ bind(&done);
}


void LCodeGen::DoModByConstI(LModByConstI* instr) {
  Register dividend = ToRegister(instr->dividend());
  int32_t divisor = instr->divisor();
  DCHECK(ToRegister(instr->result()).is(eax));

  if (divisor == 0) {
    DeoptimizeIf(no_condition, instr, "division by zero");
    return;
  }

  __ TruncatingDiv(dividend, Abs(divisor));
  __ imul(edx, edx, Abs(divisor));
  __ mov(eax, dividend);
  __ sub(eax, edx);

  // Check for negative zero.
  HMod* hmod = instr->hydrogen();
  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
    Label remainder_not_zero;
    __ j(not_zero, &remainder_not_zero, Label::kNear);
    __ cmp(dividend, Immediate(0));
    DeoptimizeIf(less, instr, "minus zero");
    __ bind(&remainder_not_zero);
  }
}


void LCodeGen::DoModI(LModI* instr) {
  HMod* hmod = instr->hydrogen();

  Register left_reg = ToRegister(instr->left());
  DCHECK(left_reg.is(eax));
  Register right_reg = ToRegister(instr->right());
  DCHECK(!right_reg.is(eax));
  DCHECK(!right_reg.is(edx));
  Register result_reg = ToRegister(instr->result());
  DCHECK(result_reg.is(edx));

  Label done;
  // Check for x % 0, idiv would signal a divide error. We have to
  // deopt in this case because we can't return a NaN.
  if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
    __ test(right_reg, Operand(right_reg));
    DeoptimizeIf(zero, instr, "division by zero");
  }

  // Check for kMinInt % -1, idiv would signal a divide error. We
  // have to deopt if we care about -0, because we can't return that.
  if (hmod->CheckFlag(HValue::kCanOverflow)) {
    Label no_overflow_possible;
    __ cmp(left_reg, kMinInt);
    __ j(not_equal, &no_overflow_possible, Label::kNear);
    __ cmp(right_reg, -1);
    if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
      DeoptimizeIf(equal, instr, "minus zero");
    } else {
      __ j(not_equal, &no_overflow_possible, Label::kNear);
      __ Move(result_reg, Immediate(0));
      __ jmp(&done, Label::kNear);
    }
    __ bind(&no_overflow_possible);
  }

  // Sign extend dividend in eax into edx:eax.
  __ cdq();

  // If we care about -0, test if the dividend is <0 and the result is 0.
  if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
    Label positive_left;
    __ test(left_reg, Operand(left_reg));
    __ j(not_sign, &positive_left, Label::kNear);
    __ idiv(right_reg);
    __ test(result_reg, Operand(result_reg));
    DeoptimizeIf(zero, instr, "minus zero");
    __ jmp(&done, Label::kNear);
    __ bind(&positive_left);
  }
  __ idiv(right_reg);
  __ bind(&done);
}


void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
  Register dividend = ToRegister(instr->dividend());
  int32_t divisor = instr->divisor();
  Register result = ToRegister(instr->result());
  DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
  DCHECK(!result.is(dividend));

  // Check for (0 / -x) that will produce negative zero.
  HDiv* hdiv = instr->hydrogen();
  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
    __ test(dividend, dividend);
    DeoptimizeIf(zero, instr, "minus zero");
  }
  // Check for (kMinInt / -1).
  if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
    __ cmp(dividend, kMinInt);
    DeoptimizeIf(zero, instr, "overflow");
  }
  // Deoptimize if remainder will not be 0.
  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
      divisor != 1 && divisor != -1) {
    int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
    __ test(dividend, Immediate(mask));
    DeoptimizeIf(not_zero, instr, "lost precision");
  }
  __ Move(result, dividend);
  int32_t shift = WhichPowerOf2Abs(divisor);
  if (shift > 0) {
    // The arithmetic shift is always OK, the 'if' is an optimization only.
    if (shift > 1) __ sar(result, 31);
    __ shr(result, 32 - shift);
    __ add(result, dividend);
    __ sar(result, shift);
  }
  if (divisor < 0) __ neg(result);
}


void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
  Register dividend = ToRegister(instr->dividend());
  int32_t divisor = instr->divisor();
  DCHECK(ToRegister(instr->result()).is(edx));

  if (divisor == 0) {
    DeoptimizeIf(no_condition, instr, "division by zero");
    return;
  }

  // Check for (0 / -x) that will produce negative zero.
  HDiv* hdiv = instr->hydrogen();
  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
    __ test(dividend, dividend);
    DeoptimizeIf(zero, instr, "minus zero");
  }

  __ TruncatingDiv(dividend, Abs(divisor));
  if (divisor < 0) __ neg(edx);

  if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
    __ mov(eax, edx);
    __ imul(eax, eax, divisor);
    __ sub(eax, dividend);
    DeoptimizeIf(not_equal, instr, "lost precision");
  }
}


// TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
void LCodeGen::DoDivI(LDivI* instr) {
  HBinaryOperation* hdiv = instr->hydrogen();
  Register dividend = ToRegister(instr->dividend());
  Register divisor = ToRegister(instr->divisor());
  Register remainder = ToRegister(instr->temp());
  DCHECK(dividend.is(eax));
  DCHECK(remainder.is(edx));
  DCHECK(ToRegister(instr->result()).is(eax));
  DCHECK(!divisor.is(eax));
  DCHECK(!divisor.is(edx));

  // Check for x / 0.
  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
    __ test(divisor, divisor);
    DeoptimizeIf(zero, instr, "division by zero");
  }

  // Check for (0 / -x) that will produce negative zero.
  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
    Label dividend_not_zero;
    __ test(dividend, dividend);
    __ j(not_zero, &dividend_not_zero, Label::kNear);
    __ test(divisor, divisor);
    DeoptimizeIf(sign, instr, "minus zero");
    __ bind(&dividend_not_zero);
  }

  // Check for (kMinInt / -1).
  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
    Label dividend_not_min_int;
    __ cmp(dividend, kMinInt);
    __ j(not_zero, &dividend_not_min_int, Label::kNear);
    __ cmp(divisor, -1);
    DeoptimizeIf(zero, instr, "overflow");
    __ bind(&dividend_not_min_int);
  }

  // Sign extend to edx (= remainder).
  __ cdq();
  __ idiv(divisor);

  if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
    // Deoptimize if remainder is not 0.
    __ test(remainder, remainder);
    DeoptimizeIf(not_zero, instr, "lost precision");
  }
}


void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
  Register dividend = ToRegister(instr->dividend());
  int32_t divisor = instr->divisor();
  DCHECK(dividend.is(ToRegister(instr->result())));

  // If the divisor is positive, things are easy: There can be no deopts and we
  // can simply do an arithmetic right shift.
  if (divisor == 1) return;
  int32_t shift = WhichPowerOf2Abs(divisor);
  if (divisor > 1) {
    __ sar(dividend, shift);
    return;
  }

  // If the divisor is negative, we have to negate and handle edge cases.
  __ neg(dividend);
  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    DeoptimizeIf(zero, instr, "minus zero");
  }

  // Dividing by -1 is basically negation, unless we overflow.
  if (divisor == -1) {
    if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
      DeoptimizeIf(overflow, instr, "overflow");
    }
    return;
  }

  // If the negation could not overflow, simply shifting is OK.
  if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
    __ sar(dividend, shift);
    return;
  }

  Label not_kmin_int, done;
  __ j(no_overflow, &not_kmin_int, Label::kNear);
  __ mov(dividend, Immediate(kMinInt / divisor));
  __ jmp(&done, Label::kNear);
  __ bind(&not_kmin_int);
  __ sar(dividend, shift);
  __ bind(&done);
}


void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
  Register dividend = ToRegister(instr->dividend());
  int32_t divisor = instr->divisor();
  DCHECK(ToRegister(instr->result()).is(edx));

  if (divisor == 0) {
    DeoptimizeIf(no_condition, instr, "division by zero");
    return;
  }

  // Check for (0 / -x) that will produce negative zero.
  HMathFloorOfDiv* hdiv = instr->hydrogen();
  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
    __ test(dividend, dividend);
    DeoptimizeIf(zero, instr, "minus zero");
  }

  // Easy case: We need no dynamic check for the dividend and the flooring
  // division is the same as the truncating division.
  if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
      (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
    __ TruncatingDiv(dividend, Abs(divisor));
    if (divisor < 0) __ neg(edx);
    return;
  }

  // In the general case we may need to adjust before and after the truncating
  // division to get a flooring division.
  Register temp = ToRegister(instr->temp3());
  DCHECK(!temp.is(dividend) && !temp.is(eax) && !temp.is(edx));
  Label needs_adjustment, done;
  __ cmp(dividend, Immediate(0));
  __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear);
  __ TruncatingDiv(dividend, Abs(divisor));
  if (divisor < 0) __ neg(edx);
  __ jmp(&done, Label::kNear);
  __ bind(&needs_adjustment);
  __ lea(temp, Operand(dividend, divisor > 0 ? 1 : -1));
  __ TruncatingDiv(temp, Abs(divisor));
  if (divisor < 0) __ neg(edx);
  __ dec(edx);
  __ bind(&done);
}


// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
  HBinaryOperation* hdiv = instr->hydrogen();
  Register dividend = ToRegister(instr->dividend());
  Register divisor = ToRegister(instr->divisor());
  Register remainder = ToRegister(instr->temp());
  Register result = ToRegister(instr->result());
  DCHECK(dividend.is(eax));
  DCHECK(remainder.is(edx));
  DCHECK(result.is(eax));
  DCHECK(!divisor.is(eax));
  DCHECK(!divisor.is(edx));

  // Check for x / 0.
  if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
    __ test(divisor, divisor);
    DeoptimizeIf(zero, instr, "division by zero");
  }

  // Check for (0 / -x) that will produce negative zero.
  if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
    Label dividend_not_zero;
    __ test(dividend, dividend);
    __ j(not_zero, &dividend_not_zero, Label::kNear);
    __ test(divisor, divisor);
    DeoptimizeIf(sign, instr, "minus zero");
    __ bind(&dividend_not_zero);
  }

  // Check for (kMinInt / -1).
  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
    Label dividend_not_min_int;
    __ cmp(dividend, kMinInt);
    __ j(not_zero, &dividend_not_min_int, Label::kNear);
    __ cmp(divisor, -1);
    DeoptimizeIf(zero, instr, "overflow");
    __ bind(&dividend_not_min_int);
  }

  // Sign extend to edx (= remainder).
  __ cdq();
  __ idiv(divisor);

  Label done;
  __ test(remainder, remainder);
  __ j(zero, &done, Label::kNear);
  __ xor_(remainder, divisor);
  __ sar(remainder, 31);
  __ add(result, remainder);
  __ bind(&done);
}


void LCodeGen::DoMulI(LMulI* instr) {
  Register left = ToRegister(instr->left());
  LOperand* right = instr->right();

  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    __ mov(ToRegister(instr->temp()), left);
  }

  if (right->IsConstantOperand()) {
    // Try strength reductions on the multiplication.
    // All replacement instructions are at most as long as the imul
    // and have better latency.
    int constant = ToInteger32(LConstantOperand::cast(right));
    if (constant == -1) {
      __ neg(left);
    } else if (constant == 0) {
      __ xor_(left, Operand(left));
    } else if (constant == 2) {
      __ add(left, Operand(left));
    } else if (!instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
      // If we know that the multiplication can't overflow, it's safe to
      // use instructions that don't set the overflow flag for the
      // multiplication.
      switch (constant) {
        case 1:
          // Do nothing.
          break;
        case 3:
          __ lea(left, Operand(left, left, times_2, 0));
          break;
        case 4:
          __ shl(left, 2);
          break;
        case 5:
          __ lea(left, Operand(left, left, times_4, 0));
          break;
        case 8:
          __ shl(left, 3);
          break;
        case 9:
          __ lea(left, Operand(left, left, times_8, 0));
          break;
        case 16:
          __ shl(left, 4);
          break;
        default:
          __ imul(left, left, constant);
          break;
      }
    } else {
      __ imul(left, left, constant);
    }
  } else {
    if (instr->hydrogen()->representation().IsSmi()) {
      __ SmiUntag(left);
    }
    __ imul(left, ToOperand(right));
  }

  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
    DeoptimizeIf(overflow, instr, "overflow");
  }

  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    // Bail out if the result is supposed to be negative zero.
    Label done;
    __ test(left, Operand(left));
    __ j(not_zero, &done);
    if (right->IsConstantOperand()) {
      if (ToInteger32(LConstantOperand::cast(right)) < 0) {
        DeoptimizeIf(no_condition, instr, "minus zero");
      } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
        __ cmp(ToRegister(instr->temp()), Immediate(0));
        DeoptimizeIf(less, instr, "minus zero");
      }
    } else {
      // Test the non-zero operand for negative sign.
      __ or_(ToRegister(instr->temp()), ToOperand(right));
      DeoptimizeIf(sign, instr, "minus zero");
    }
    __ bind(&done);
  }
}


void LCodeGen::DoBitI(LBitI* instr) {
  LOperand* left = instr->left();
  LOperand* right = instr->right();
  DCHECK(left->Equals(instr->result()));
  DCHECK(left->IsRegister());

  if (right->IsConstantOperand()) {
    int32_t right_operand =
        ToRepresentation(LConstantOperand::cast(right),
                         instr->hydrogen()->representation());
    switch (instr->op()) {
      case Token::BIT_AND:
        __ and_(ToRegister(left), right_operand);
        break;
      case Token::BIT_OR:
        __ or_(ToRegister(left), right_operand);
        break;
      case Token::BIT_XOR:
        if (right_operand == int32_t(~0)) {
          __ not_(ToRegister(left));
        } else {
          __ xor_(ToRegister(left), right_operand);
        }
        break;
      default:
        UNREACHABLE();
        break;
    }
  } else {
    switch (instr->op()) {
      case Token::BIT_AND:
        __ and_(ToRegister(left), ToOperand(right));
        break;
      case Token::BIT_OR:
        __ or_(ToRegister(left), ToOperand(right));
        break;
      case Token::BIT_XOR:
        __ xor_(ToRegister(left), ToOperand(right));
        break;
      default:
        UNREACHABLE();
        break;
    }
  }
}


void LCodeGen::DoShiftI(LShiftI* instr) {
  LOperand* left = instr->left();
  LOperand* right = instr->right();
  DCHECK(left->Equals(instr->result()));
  DCHECK(left->IsRegister());
  if (right->IsRegister()) {
    DCHECK(ToRegister(right).is(ecx));

    switch (instr->op()) {
      case Token::ROR:
        __ ror_cl(ToRegister(left));
        break;
      case Token::SAR:
        __ sar_cl(ToRegister(left));
        break;
      case Token::SHR:
        __ shr_cl(ToRegister(left));
        if (instr->can_deopt()) {
          __ test(ToRegister(left), ToRegister(left));
          DeoptimizeIf(sign, instr, "negative value");
        }
        break;
      case Token::SHL:
        __ shl_cl(ToRegister(left));
        break;
      default:
        UNREACHABLE();
        break;
    }
  } else {
    int value = ToInteger32(LConstantOperand::cast(right));
    uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
    switch (instr->op()) {
      case Token::ROR:
        if (shift_count == 0 && instr->can_deopt()) {
          __ test(ToRegister(left), ToRegister(left));
          DeoptimizeIf(sign, instr, "negative value");
        } else {
          __ ror(ToRegister(left), shift_count);
        }
        break;
      case Token::SAR:
        if (shift_count != 0) {
          __ sar(ToRegister(left), shift_count);
        }
        break;
      case Token::SHR:
        if (shift_count != 0) {
          __ shr(ToRegister(left), shift_count);
        } else if (instr->can_deopt()) {
          __ test(ToRegister(left), ToRegister(left));
          DeoptimizeIf(sign, instr, "negative value");
        }
        break;
      case Token::SHL:
        if (shift_count != 0) {
          if (instr->hydrogen_value()->representation().IsSmi() &&
              instr->can_deopt()) {
            if (shift_count != 1) {
              __ shl(ToRegister(left), shift_count - 1);
            }
            __ SmiTag(ToRegister(left));
            DeoptimizeIf(overflow, instr, "overflow");
          } else {
            __ shl(ToRegister(left), shift_count);
          }
        }
        break;
      default:
        UNREACHABLE();
        break;
    }
  }
}


void LCodeGen::DoSubI(LSubI* instr) {
  LOperand* left = instr->left();
  LOperand* right = instr->right();
  DCHECK(left->Equals(instr->result()));

  if (right->IsConstantOperand()) {
    __ sub(ToOperand(left),
           ToImmediate(right, instr->hydrogen()->representation()));
  } else {
    __ sub(ToRegister(left), ToOperand(right));
  }
  if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
    DeoptimizeIf(overflow, instr, "overflow");
  }
}


void LCodeGen::DoConstantI(LConstantI* instr) {
  __ Move(ToRegister(instr->result()), Immediate(instr->value()));
}


void LCodeGen::DoConstantS(LConstantS* instr) {
  __ Move(ToRegister(instr->result()), Immediate(instr->value()));
}


void LCodeGen::DoConstantD(LConstantD* instr) {
  double v = instr->value();
  uint64_t int_val = bit_cast<uint64_t, double>(v);
  int32_t lower = static_cast<int32_t>(int_val);
  int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
  DCHECK(instr->result()->IsDoubleRegister());

  __ push(Immediate(upper));
  __ push(Immediate(lower));
  X87Register reg = ToX87Register(instr->result());
  X87Mov(reg, Operand(esp, 0));
  __ add(Operand(esp), Immediate(kDoubleSize));
}


void LCodeGen::DoConstantE(LConstantE* instr) {
  __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value()));
}


void LCodeGen::DoConstantT(LConstantT* instr) {
  Register reg = ToRegister(instr->result());
  Handle<Object> object = instr->value(isolate());
  AllowDeferredHandleDereference smi_check;
  __ LoadObject(reg, object);
}


void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) {
  Register result = ToRegister(instr->result());
  Register map = ToRegister(instr->value());
  __ EnumLength(result, map);
}


void LCodeGen::DoDateField(LDateField* instr) {
  Register object = ToRegister(instr->date());
  Register result = ToRegister(instr->result());
  Register scratch = ToRegister(instr->temp());
  Smi* index = instr->index();
  Label runtime, done;
  DCHECK(object.is(result));
  DCHECK(object.is(eax));

  __ test(object, Immediate(kSmiTagMask));
  DeoptimizeIf(zero, instr, "Smi");
  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
  DeoptimizeIf(not_equal, instr, "not a date object");

  if (index->value() == 0) {
    __ mov(result, FieldOperand(object, JSDate::kValueOffset));
  } else {
    if (index->value() < JSDate::kFirstUncachedField) {
      ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
      __ mov(scratch, Operand::StaticVariable(stamp));
      __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
      __ j(not_equal, &runtime, Label::kNear);
      __ mov(result, FieldOperand(object, JSDate::kValueOffset +
                                          kPointerSize * index->value()));
      __ jmp(&done, Label::kNear);
    }
    __ bind(&runtime);
    __ PrepareCallCFunction(2, scratch);
    __ mov(Operand(esp, 0), object);
    __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
    __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
    __ bind(&done);
  }
}


Operand LCodeGen::BuildSeqStringOperand(Register string,
                                        LOperand* index,
                                        String::Encoding encoding) {
  if (index->IsConstantOperand()) {
    int offset = ToRepresentation(LConstantOperand::cast(index),
                                  Representation::Integer32());
    if (encoding == String::TWO_BYTE_ENCODING) {
      offset *= kUC16Size;
    }
    STATIC_ASSERT(kCharSize == 1);
    return FieldOperand(string, SeqString::kHeaderSize + offset);
  }
  return FieldOperand(
      string, ToRegister(index),
      encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2,
      SeqString::kHeaderSize);
}


void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) {
  String::Encoding encoding = instr->hydrogen()->encoding();
  Register result = ToRegister(instr->result());
  Register string = ToRegister(instr->string());

  if (FLAG_debug_code) {
    __ push(string);
    __ mov(string, FieldOperand(string, HeapObject::kMapOffset));
    __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));

    __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
    __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING
                             ? one_byte_seq_type : two_byte_seq_type));
    __ Check(equal, kUnexpectedStringType);
    __ pop(string);
  }

  Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
  if (encoding == String::ONE_BYTE_ENCODING) {
    __ movzx_b(result, operand);
  } else {
    __ movzx_w(result, operand);
  }
}


void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
  String::Encoding encoding = instr->hydrogen()->encoding();
  Register string = ToRegister(instr->string());

  if (FLAG_debug_code) {
    Register value = ToRegister(instr->value());
    Register index = ToRegister(instr->index());
    static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
    static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
    int encoding_mask =
        instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
        ? one_byte_seq_type : two_byte_seq_type;
    __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
  }

  Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
  if (instr->value()->IsConstantOperand()) {
    int value = ToRepresentation(LConstantOperand::cast(instr->value()),
                                 Representation::Integer32());
    DCHECK_LE(0, value);
    if (encoding == String::ONE_BYTE_ENCODING) {
      DCHECK_LE(value, String::kMaxOneByteCharCode);
      __ mov_b(operand, static_cast<int8_t>(value));
    } else {
      DCHECK_LE(value, String::kMaxUtf16CodeUnit);
      __ mov_w(operand, static_cast<int16_t>(value));
    }
  } else {
    Register value = ToRegister(instr->value());
    if (encoding == String::ONE_BYTE_ENCODING) {
      __ mov_b(operand, value);
    } else {
      __ mov_w(operand, value);
    }
  }
}


void LCodeGen::DoAddI(LAddI* instr) {
  LOperand* left = instr->left();
  LOperand* right = instr->right();

  if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
    if (right->IsConstantOperand()) {
      int32_t offset = ToRepresentation(LConstantOperand::cast(right),
                                        instr->hydrogen()->representation());
      __ lea(ToRegister(instr->result()), MemOperand(ToRegister(left), offset));
    } else {
      Operand address(ToRegister(left), ToRegister(right), times_1, 0);
      __ lea(ToRegister(instr->result()), address);
    }
  } else {
    if (right->IsConstantOperand()) {
      __ add(ToOperand(left),
             ToImmediate(right, instr->hydrogen()->representation()));
    } else {
      __ add(ToRegister(left), ToOperand(right));
    }
    if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
      DeoptimizeIf(overflow, instr, "overflow");
    }
  }
}


void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
  LOperand* left = instr->left();
  LOperand* right = instr->right();
  DCHECK(left->Equals(instr->result()));
  HMathMinMax::Operation operation = instr->hydrogen()->operation();
  if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
    Label return_left;
    Condition condition = (operation == HMathMinMax::kMathMin)
        ? less_equal
        : greater_equal;
    if (right->IsConstantOperand()) {
      Operand left_op = ToOperand(left);
      Immediate immediate = ToImmediate(LConstantOperand::cast(instr->right()),
                                        instr->hydrogen()->representation());
      __ cmp(left_op, immediate);
      __ j(condition, &return_left, Label::kNear);
      __ mov(left_op, immediate);
    } else {
      Register left_reg = ToRegister(left);
      Operand right_op = ToOperand(right);
      __ cmp(left_reg, right_op);
      __ j(condition, &return_left, Label::kNear);
      __ mov(left_reg, right_op);
    }
    __ bind(&return_left);
  } else {
    DCHECK(instr->hydrogen()->representation().IsDouble());
    Label check_nan_left, check_zero, return_left, return_right;
    Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
    X87Register left_reg = ToX87Register(left);
    X87Register right_reg = ToX87Register(right);

    X87PrepareBinaryOp(left_reg, right_reg, ToX87Register(instr->result()));
    __ fld(1);
    __ fld(1);
    __ FCmp();
    __ j(parity_even, &check_nan_left, Label::kNear);  // At least one NaN.
    __ j(equal, &check_zero, Label::kNear);            // left == right.
    __ j(condition, &return_left, Label::kNear);
    __ jmp(&return_right, Label::kNear);

    __ bind(&check_zero);
    __ fld(0);
    __ fldz();
    __ FCmp();
    __ j(not_equal, &return_left, Label::kNear);  // left == right != 0.
    // At this point, both left and right are either 0 or -0.
    if (operation == HMathMinMax::kMathMin) {
      // Push st0 and st1 to stack, then pop them to temp registers and OR them,
      // load it to left.
      Register scratch_reg = ToRegister(instr->temp());
      __ fld(1);
      __ fld(1);
      __ sub(esp, Immediate(2 * kPointerSize));
      __ fstp_s(MemOperand(esp, 0));
      __ fstp_s(MemOperand(esp, kPointerSize));
      __ pop(scratch_reg);
      __ xor_(MemOperand(esp, 0), scratch_reg);
      X87Mov(left_reg, MemOperand(esp, 0), kX87FloatOperand);
      __ pop(scratch_reg);  // restore esp
    } else {
      // Since we operate on +0 and/or -0, addsd and andsd have the same effect.
      X87Fxch(left_reg);
      __ fadd(1);
    }
    __ jmp(&return_left, Label::kNear);

    __ bind(&check_nan_left);
    __ fld(0);
    __ fld(0);
    __ FCmp();                                      // NaN check.
    __ j(parity_even, &return_left, Label::kNear);  // left == NaN.

    __ bind(&return_right);
    X87Fxch(left_reg);
    X87Mov(left_reg, right_reg);

    __ bind(&return_left);
  }
}


void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
  X87Register left = ToX87Register(instr->left());
  X87Register right = ToX87Register(instr->right());
  X87Register result = ToX87Register(instr->result());
  if (instr->op() != Token::MOD) {
    X87PrepareBinaryOp(left, right, result);
  }
  // Set the precision control to double-precision.
  __ X87SetFPUCW(0x027F);
  switch (instr->op()) {
    case Token::ADD:
      __ fadd_i(1);
      break;
    case Token::SUB:
      __ fsub_i(1);
      break;
    case Token::MUL:
      __ fmul_i(1);
      break;
    case Token::DIV:
      __ fdiv_i(1);
      break;
    case Token::MOD: {
      // Pass two doubles as arguments on the stack.
      __ PrepareCallCFunction(4, eax);
      X87Mov(Operand(esp, 1 * kDoubleSize), right);
      X87Mov(Operand(esp, 0), left);
      X87Free(right);
      DCHECK(left.is(result));
      X87PrepareToWrite(result);
      __ CallCFunction(
          ExternalReference::mod_two_doubles_operation(isolate()),
          4);

      // Return value is in st(0) on ia32.
      X87CommitWrite(result);
      break;
    }
    default:
      UNREACHABLE();
      break;
  }

  // Restore the default value of control word.
  __ X87SetFPUCW(0x037F);
}


void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->left()).is(edx));
  DCHECK(ToRegister(instr->right()).is(eax));
  DCHECK(ToRegister(instr->result()).is(eax));

  Handle<Code> code =
      CodeFactory::BinaryOpIC(isolate(), instr->op(), NO_OVERWRITE).code();
  CallCode(code, RelocInfo::CODE_TARGET, instr);
}


template<class InstrType>
void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
  int left_block = instr->TrueDestination(chunk_);
  int right_block = instr->FalseDestination(chunk_);

  int next_block = GetNextEmittedBlock();

  if (right_block == left_block || cc == no_condition) {
    EmitGoto(left_block);
  } else if (left_block == next_block) {
    __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
  } else if (right_block == next_block) {
    __ j(cc, chunk_->GetAssemblyLabel(left_block));
  } else {
    __ j(cc, chunk_->GetAssemblyLabel(left_block));
    __ jmp(chunk_->GetAssemblyLabel(right_block));
  }
}


template<class InstrType>
void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
  int false_block = instr->FalseDestination(chunk_);
  if (cc == no_condition) {
    __ jmp(chunk_->GetAssemblyLabel(false_block));
  } else {
    __ j(cc, chunk_->GetAssemblyLabel(false_block));
  }
}


void LCodeGen::DoBranch(LBranch* instr) {
  Representation r = instr->hydrogen()->value()->representation();
  if (r.IsSmiOrInteger32()) {
    Register reg = ToRegister(instr->value());
    __ test(reg, Operand(reg));
    EmitBranch(instr, not_zero);
  } else if (r.IsDouble()) {
    X87Register reg = ToX87Register(instr->value());
    X87LoadForUsage(reg);
    __ fldz();
    __ FCmp();
    EmitBranch(instr, not_zero);
  } else {
    DCHECK(r.IsTagged());
    Register reg = ToRegister(instr->value());
    HType type = instr->hydrogen()->value()->type();
    if (type.IsBoolean()) {
      DCHECK(!info()->IsStub());
      __ cmp(reg, factory()->true_value());
      EmitBranch(instr, equal);
    } else if (type.IsSmi()) {
      DCHECK(!info()->IsStub());
      __ test(reg, Operand(reg));
      EmitBranch(instr, not_equal);
    } else if (type.IsJSArray()) {
      DCHECK(!info()->IsStub());
      EmitBranch(instr, no_condition);
    } else if (type.IsHeapNumber()) {
      UNREACHABLE();
    } else if (type.IsString()) {
      DCHECK(!info()->IsStub());
      __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
      EmitBranch(instr, not_equal);
    } else {
      ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
      if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();

      if (expected.Contains(ToBooleanStub::UNDEFINED)) {
        // undefined -> false.
        __ cmp(reg, factory()->undefined_value());
        __ j(equal, instr->FalseLabel(chunk_));
      }
      if (expected.Contains(ToBooleanStub::BOOLEAN)) {
        // true -> true.
        __ cmp(reg, factory()->true_value());
        __ j(equal, instr->TrueLabel(chunk_));
        // false -> false.
        __ cmp(reg, factory()->false_value());
        __ j(equal, instr->FalseLabel(chunk_));
      }
      if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
        // 'null' -> false.
        __ cmp(reg, factory()->null_value());
        __ j(equal, instr->FalseLabel(chunk_));
      }

      if (expected.Contains(ToBooleanStub::SMI)) {
        // Smis: 0 -> false, all other -> true.
        __ test(reg, Operand(reg));
        __ j(equal, instr->FalseLabel(chunk_));
        __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
      } else if (expected.NeedsMap()) {
        // If we need a map later and have a Smi -> deopt.
        __ test(reg, Immediate(kSmiTagMask));
        DeoptimizeIf(zero, instr, "Smi");
      }

      Register map = no_reg;  // Keep the compiler happy.
      if (expected.NeedsMap()) {
        map = ToRegister(instr->temp());
        DCHECK(!map.is(reg));
        __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));

        if (expected.CanBeUndetectable()) {
          // Undetectable -> false.
          __ test_b(FieldOperand(map, Map::kBitFieldOffset),
                    1 << Map::kIsUndetectable);
          __ j(not_zero, instr->FalseLabel(chunk_));
        }
      }

      if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
        // spec object -> true.
        __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
        __ j(above_equal, instr->TrueLabel(chunk_));
      }

      if (expected.Contains(ToBooleanStub::STRING)) {
        // String value -> false iff empty.
        Label not_string;
        __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
        __ j(above_equal, &not_string, Label::kNear);
        __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
        __ j(not_zero, instr->TrueLabel(chunk_));
        __ jmp(instr->FalseLabel(chunk_));
        __ bind(&not_string);
      }

      if (expected.Contains(ToBooleanStub::SYMBOL)) {
        // Symbol value -> true.
        __ CmpInstanceType(map, SYMBOL_TYPE);
        __ j(equal, instr->TrueLabel(chunk_));
      }

      if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
        // heap number -> false iff +0, -0, or NaN.
        Label not_heap_number;
        __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
               factory()->heap_number_map());
        __ j(not_equal, &not_heap_number, Label::kNear);
        __ fldz();
        __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
        __ FCmp();
        __ j(zero, instr->FalseLabel(chunk_));
        __ jmp(instr->TrueLabel(chunk_));
        __ bind(&not_heap_number);
      }

      if (!expected.IsGeneric()) {
        // We've seen something for the first time -> deopt.
        // This can only happen if we are not generic already.
        DeoptimizeIf(no_condition, instr, "unexpected object");
      }
    }
  }
}


void LCodeGen::EmitGoto(int block) {
  if (!IsNextEmittedBlock(block)) {
    __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
  }
}


void LCodeGen::DoClobberDoubles(LClobberDoubles* instr) {
}


void LCodeGen::DoGoto(LGoto* instr) {
  EmitGoto(instr->block_id());
}


Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
  Condition cond = no_condition;
  switch (op) {
    case Token::EQ:
    case Token::EQ_STRICT:
      cond = equal;
      break;
    case Token::NE:
    case Token::NE_STRICT:
      cond = not_equal;
      break;
    case Token::LT:
      cond = is_unsigned ? below : less;
      break;
    case Token::GT:
      cond = is_unsigned ? above : greater;
      break;
    case Token::LTE:
      cond = is_unsigned ? below_equal : less_equal;
      break;
    case Token::GTE:
      cond = is_unsigned ? above_equal : greater_equal;
      break;
    case Token::IN:
    case Token::INSTANCEOF:
    default:
      UNREACHABLE();
  }
  return cond;
}


void LCodeGen::DoCompareNumericAndBranch(LCompareNumericAndBranch* instr) {
  LOperand* left = instr->left();
  LOperand* right = instr->right();
  bool is_unsigned =
      instr->is_double() ||
      instr->hydrogen()->left()->CheckFlag(HInstruction::kUint32) ||
      instr->hydrogen()->right()->CheckFlag(HInstruction::kUint32);
  Condition cc = TokenToCondition(instr->op(), is_unsigned);

  if (left->IsConstantOperand() && right->IsConstantOperand()) {
    // We can statically evaluate the comparison.
    double left_val = ToDouble(LConstantOperand::cast(left));
    double right_val = ToDouble(LConstantOperand::cast(right));
    int next_block = EvalComparison(instr->op(), left_val, right_val) ?
        instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
    EmitGoto(next_block);
  } else {
    if (instr->is_double()) {
      X87LoadForUsage(ToX87Register(right), ToX87Register(left));
      __ FCmp();
      // Don't base result on EFLAGS when a NaN is involved. Instead
      // jump to the false block.
      __ j(parity_even, instr->FalseLabel(chunk_));
    } else {
      if (right->IsConstantOperand()) {
        __ cmp(ToOperand(left),
               ToImmediate(right, instr->hydrogen()->representation()));
      } else if (left->IsConstantOperand()) {
        __ cmp(ToOperand(right),
               ToImmediate(left, instr->hydrogen()->representation()));
        // We commuted the operands, so commute the condition.
        cc = CommuteCondition(cc);
      } else {
        __ cmp(ToRegister(left), ToOperand(right));
      }
    }
    EmitBranch(instr, cc);
  }
}


void LCodeGen::DoCmpObjectEqAndBranch(LCmpObjectEqAndBranch* instr) {
  Register left = ToRegister(instr->left());

  if (instr->right()->IsConstantOperand()) {
    Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
    __ CmpObject(left, right);
  } else {
    Operand right = ToOperand(instr->right());
    __ cmp(left, right);
  }
  EmitBranch(instr, equal);
}


void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
  if (instr->hydrogen()->representation().IsTagged()) {
    Register input_reg = ToRegister(instr->object());
    __ cmp(input_reg, factory()->the_hole_value());
    EmitBranch(instr, equal);
    return;
  }

  // Put the value to the top of stack
  X87Register src = ToX87Register(instr->object());
  X87LoadForUsage(src);
  __ fld(0);
  __ fld(0);
  __ FCmp();
  Label ok;
  __ j(parity_even, &ok, Label::kNear);
  __ fstp(0);
  EmitFalseBranch(instr, no_condition);
  __ bind(&ok);


  __ sub(esp, Immediate(kDoubleSize));
  __ fstp_d(MemOperand(esp, 0));

  __ add(esp, Immediate(kDoubleSize));
  int offset = sizeof(kHoleNanUpper32);
  __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
  EmitBranch(instr, equal);
}


void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
  Representation rep = instr->hydrogen()->value()->representation();
  DCHECK(!rep.IsInteger32());

  if (rep.IsDouble()) {
    X87Register input = ToX87Register(instr->value());
    X87LoadForUsage(input);
    __ FXamMinusZero();
    EmitBranch(instr, equal);
  } else {
    Register value = ToRegister(instr->value());
    Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
    __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
    __ cmp(FieldOperand(value, HeapNumber::kExponentOffset),
           Immediate(0x1));
    EmitFalseBranch(instr, no_overflow);
    __ cmp(FieldOperand(value, HeapNumber::kMantissaOffset),
           Immediate(0x00000000));
    EmitBranch(instr, equal);
  }
}


Condition LCodeGen::EmitIsObject(Register input,
                                 Register temp1,
                                 Label* is_not_object,
                                 Label* is_object) {
  __ JumpIfSmi(input, is_not_object);

  __ cmp(input, isolate()->factory()->null_value());
  __ j(equal, is_object);

  __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
  // Undetectable objects behave like undefined.
  __ test_b(FieldOperand(temp1, Map::kBitFieldOffset),
            1 << Map::kIsUndetectable);
  __ j(not_zero, is_not_object);

  __ movzx_b(temp1, FieldOperand(temp1, Map::kInstanceTypeOffset));
  __ cmp(temp1, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
  __ j(below, is_not_object);
  __ cmp(temp1, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
  return below_equal;
}


void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
  Register reg = ToRegister(instr->value());
  Register temp = ToRegister(instr->temp());

  Condition true_cond = EmitIsObject(
      reg, temp, instr->FalseLabel(chunk_), instr->TrueLabel(chunk_));

  EmitBranch(instr, true_cond);
}


Condition LCodeGen::EmitIsString(Register input,
                                 Register temp1,
                                 Label* is_not_string,
                                 SmiCheck check_needed = INLINE_SMI_CHECK) {
  if (check_needed == INLINE_SMI_CHECK) {
    __ JumpIfSmi(input, is_not_string);
  }

  Condition cond = masm_->IsObjectStringType(input, temp1, temp1);

  return cond;
}


void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
  Register reg = ToRegister(instr->value());
  Register temp = ToRegister(instr->temp());

  SmiCheck check_needed =
      instr->hydrogen()->value()->type().IsHeapObject()
          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;

  Condition true_cond = EmitIsString(
      reg, temp, instr->FalseLabel(chunk_), check_needed);

  EmitBranch(instr, true_cond);
}


void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
  Operand input = ToOperand(instr->value());

  __ test(input, Immediate(kSmiTagMask));
  EmitBranch(instr, zero);
}


void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
  Register input = ToRegister(instr->value());
  Register temp = ToRegister(instr->temp());

  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
    STATIC_ASSERT(kSmiTag == 0);
    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
  }
  __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
  __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
            1 << Map::kIsUndetectable);
  EmitBranch(instr, not_zero);
}


static Condition ComputeCompareCondition(Token::Value op) {
  switch (op) {
    case Token::EQ_STRICT:
    case Token::EQ:
      return equal;
    case Token::LT:
      return less;
    case Token::GT:
      return greater;
    case Token::LTE:
      return less_equal;
    case Token::GTE:
      return greater_equal;
    default:
      UNREACHABLE();
      return no_condition;
  }
}


void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
  Token::Value op = instr->op();

  Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
  CallCode(ic, RelocInfo::CODE_TARGET, instr);

  Condition condition = ComputeCompareCondition(op);
  __ test(eax, Operand(eax));

  EmitBranch(instr, condition);
}


static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
  InstanceType from = instr->from();
  InstanceType to = instr->to();
  if (from == FIRST_TYPE) return to;
  DCHECK(from == to || to == LAST_TYPE);
  return from;
}


static Condition BranchCondition(HHasInstanceTypeAndBranch* instr) {
  InstanceType from = instr->from();
  InstanceType to = instr->to();
  if (from == to) return equal;
  if (to == LAST_TYPE) return above_equal;
  if (from == FIRST_TYPE) return below_equal;
  UNREACHABLE();
  return equal;
}


void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) {
  Register input = ToRegister(instr->value());
  Register temp = ToRegister(instr->temp());

  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
    __ JumpIfSmi(input, instr->FalseLabel(chunk_));
  }

  __ CmpObjectType(input, TestType(instr->hydrogen()), temp);
  EmitBranch(instr, BranchCondition(instr->hydrogen()));
}


void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
  Register input = ToRegister(instr->value());
  Register result = ToRegister(instr->result());

  __ AssertString(input);

  __ mov(result, FieldOperand(input, String::kHashFieldOffset));
  __ IndexFromHash(result, result);
}


void LCodeGen::DoHasCachedArrayIndexAndBranch(
    LHasCachedArrayIndexAndBranch* instr) {
  Register input = ToRegister(instr->value());

  __ test(FieldOperand(input, String::kHashFieldOffset),
          Immediate(String::kContainsCachedArrayIndexMask));
  EmitBranch(instr, equal);
}


// Branches to a label or falls through with the answer in the z flag.  Trashes
// the temp registers, but not the input.
void LCodeGen::EmitClassOfTest(Label* is_true,
                               Label* is_false,
                               Handle<String>class_name,
                               Register input,
                               Register temp,
                               Register temp2) {
  DCHECK(!input.is(temp));
  DCHECK(!input.is(temp2));
  DCHECK(!temp.is(temp2));
  __ JumpIfSmi(input, is_false);

  if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
    // Assuming the following assertions, we can use the same compares to test
    // for both being a function type and being in the object type range.
    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
    STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE ==
                  FIRST_SPEC_OBJECT_TYPE + 1);
    STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE ==
                  LAST_SPEC_OBJECT_TYPE - 1);
    STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
    __ CmpObjectType(input, FIRST_SPEC_OBJECT_TYPE, temp);
    __ j(below, is_false);
    __ j(equal, is_true);
    __ CmpInstanceType(temp, LAST_SPEC_OBJECT_TYPE);
    __ j(equal, is_true);
  } else {
    // Faster code path to avoid two compares: subtract lower bound from the
    // actual type and do a signed compare with the width of the type range.
    __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
    __ movzx_b(temp2, FieldOperand(temp, Map::kInstanceTypeOffset));
    __ sub(Operand(temp2), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
    __ cmp(Operand(temp2), Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE -
                                     FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
    __ j(above, is_false);
  }

  // Now we are in the FIRST-LAST_NONCALLABLE_SPEC_OBJECT_TYPE range.
  // Check if the constructor in the map is a function.
  __ mov(temp, FieldOperand(temp, Map::kConstructorOffset));
  // Objects with a non-function constructor have class 'Object'.
  __ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2);
  if (String::Equals(class_name, isolate()->factory()->Object_string())) {
    __ j(not_equal, is_true);
  } else {
    __ j(not_equal, is_false);
  }

  // temp now contains the constructor function. Grab the
  // instance class name from there.
  __ mov(temp, FieldOperand(temp, JSFunction::kSharedFunctionInfoOffset));
  __ mov(temp, FieldOperand(temp,
                            SharedFunctionInfo::kInstanceClassNameOffset));
  // The class name we are testing against is internalized since it's a literal.
  // The name in the constructor is internalized because of the way the context
  // is booted.  This routine isn't expected to work for random API-created
  // classes and it doesn't have to because you can't access it with natives
  // syntax.  Since both sides are internalized it is sufficient to use an
  // identity comparison.
  __ cmp(temp, class_name);
  // End with the answer in the z flag.
}


void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
  Register input = ToRegister(instr->value());
  Register temp = ToRegister(instr->temp());
  Register temp2 = ToRegister(instr->temp2());

  Handle<String> class_name = instr->hydrogen()->class_name();

  EmitClassOfTest(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
      class_name, input, temp, temp2);

  EmitBranch(instr, equal);
}


void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
  Register reg = ToRegister(instr->value());
  __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map());
  EmitBranch(instr, equal);
}


void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
  // Object and function are in fixed registers defined by the stub.
  DCHECK(ToRegister(instr->context()).is(esi));
  InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters);
  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);

  Label true_value, done;
  __ test(eax, Operand(eax));
  __ j(zero, &true_value, Label::kNear);
  __ mov(ToRegister(instr->result()), factory()->false_value());
  __ jmp(&done, Label::kNear);
  __ bind(&true_value);
  __ mov(ToRegister(instr->result()), factory()->true_value());
  __ bind(&done);
}


void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
  class DeferredInstanceOfKnownGlobal FINAL : public LDeferredCode {
   public:
    DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
                                  LInstanceOfKnownGlobal* instr,
                                  const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE {
      codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
    }
    LInstruction* instr() OVERRIDE { return instr_; }
    Label* map_check() { return &map_check_; }
   private:
    LInstanceOfKnownGlobal* instr_;
    Label map_check_;
  };

  DeferredInstanceOfKnownGlobal* deferred;
  deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_);

  Label done, false_result;
  Register object = ToRegister(instr->value());
  Register temp = ToRegister(instr->temp());

  // A Smi is not an instance of anything.
  __ JumpIfSmi(object, &false_result, Label::kNear);

  // This is the inlined call site instanceof cache. The two occurences of the
  // hole value will be patched to the last map/result pair generated by the
  // instanceof stub.
  Label cache_miss;
  Register map = ToRegister(instr->temp());
  __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
  __ bind(deferred->map_check());  // Label for calculating code patching.
  Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value());
  __ cmp(map, Operand::ForCell(cache_cell));  // Patched to cached map.
  __ j(not_equal, &cache_miss, Label::kNear);
  __ mov(eax, factory()->the_hole_value());  // Patched to either true or false.
  __ jmp(&done, Label::kNear);

  // The inlined call site cache did not match. Check for null and string
  // before calling the deferred code.
  __ bind(&cache_miss);
  // Null is not an instance of anything.
  __ cmp(object, factory()->null_value());
  __ j(equal, &false_result, Label::kNear);

  // String values are not instances of anything.
  Condition is_string = masm_->IsObjectStringType(object, temp, temp);
  __ j(is_string, &false_result, Label::kNear);

  // Go to the deferred code.
  __ jmp(deferred->entry());

  __ bind(&false_result);
  __ mov(ToRegister(instr->result()), factory()->false_value());

  // Here result has either true or false. Deferred code also produces true or
  // false object.
  __ bind(deferred->exit());
  __ bind(&done);
}


void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
                                               Label* map_check) {
  PushSafepointRegistersScope scope(this);

  InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
  flags = static_cast<InstanceofStub::Flags>(
      flags | InstanceofStub::kArgsInRegisters);
  flags = static_cast<InstanceofStub::Flags>(
      flags | InstanceofStub::kCallSiteInlineCheck);
  flags = static_cast<InstanceofStub::Flags>(
      flags | InstanceofStub::kReturnTrueFalseObject);
  InstanceofStub stub(isolate(), flags);

  // Get the temp register reserved by the instruction. This needs to be a
  // register which is pushed last by PushSafepointRegisters as top of the
  // stack is used to pass the offset to the location of the map check to
  // the stub.
  Register temp = ToRegister(instr->temp());
  DCHECK(MacroAssembler::SafepointRegisterStackIndex(temp) == 0);
  __ LoadHeapObject(InstanceofStub::right(), instr->function());
  static const int kAdditionalDelta = 13;
  int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
  __ mov(temp, Immediate(delta));
  __ StoreToSafepointRegisterSlot(temp, temp);
  CallCodeGeneric(stub.GetCode(),
                  RelocInfo::CODE_TARGET,
                  instr,
                  RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
  // Get the deoptimization index of the LLazyBailout-environment that
  // corresponds to this instruction.
  LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());

  // Put the result value into the eax slot and restore all registers.
  __ StoreToSafepointRegisterSlot(eax, eax);
}


void LCodeGen::DoCmpT(LCmpT* instr) {
  Token::Value op = instr->op();

  Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
  CallCode(ic, RelocInfo::CODE_TARGET, instr);

  Condition condition = ComputeCompareCondition(op);
  Label true_value, done;
  __ test(eax, Operand(eax));
  __ j(condition, &true_value, Label::kNear);
  __ mov(ToRegister(instr->result()), factory()->false_value());
  __ jmp(&done, Label::kNear);
  __ bind(&true_value);
  __ mov(ToRegister(instr->result()), factory()->true_value());
  __ bind(&done);
}


void LCodeGen::EmitReturn(LReturn* instr, bool dynamic_frame_alignment) {
  int extra_value_count = dynamic_frame_alignment ? 2 : 1;

  if (instr->has_constant_parameter_count()) {
    int parameter_count = ToInteger32(instr->constant_parameter_count());
    if (dynamic_frame_alignment && FLAG_debug_code) {
      __ cmp(Operand(esp,
                     (parameter_count + extra_value_count) * kPointerSize),
             Immediate(kAlignmentZapValue));
      __ Assert(equal, kExpectedAlignmentMarker);
    }
    __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx);
  } else {
    DCHECK(info()->IsStub());  // Functions would need to drop one more value.
    Register reg = ToRegister(instr->parameter_count());
    // The argument count parameter is a smi
    __ SmiUntag(reg);
    Register return_addr_reg = reg.is(ecx) ? ebx : ecx;
    if (dynamic_frame_alignment && FLAG_debug_code) {
      DCHECK(extra_value_count == 2);
      __ cmp(Operand(esp, reg, times_pointer_size,
                     extra_value_count * kPointerSize),
             Immediate(kAlignmentZapValue));
      __ Assert(equal, kExpectedAlignmentMarker);
    }

    // emit code to restore stack based on instr->parameter_count()
    __ pop(return_addr_reg);  // save return address
    if (dynamic_frame_alignment) {
      __ inc(reg);  // 1 more for alignment
    }
    __ shl(reg, kPointerSizeLog2);
    __ add(esp, reg);
    __ jmp(return_addr_reg);
  }
}


void LCodeGen::DoReturn(LReturn* instr) {
  if (FLAG_trace && info()->IsOptimizing()) {
    // Preserve the return value on the stack and rely on the runtime call
    // to return the value in the same register.  We're leaving the code
    // managed by the register allocator and tearing down the frame, it's
    // safe to write to the context register.
    __ push(eax);
    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
    __ CallRuntime(Runtime::kTraceExit, 1);
  }
  if (dynamic_frame_alignment_) {
    // Fetch the state of the dynamic frame alignment.
    __ mov(edx, Operand(ebp,
      JavaScriptFrameConstants::kDynamicAlignmentStateOffset));
  }
  int no_frame_start = -1;
  if (NeedsEagerFrame()) {
    __ mov(esp, ebp);
    __ pop(ebp);
    no_frame_start = masm_->pc_offset();
  }
  if (dynamic_frame_alignment_) {
    Label no_padding;
    __ cmp(edx, Immediate(kNoAlignmentPadding));
    __ j(equal, &no_padding, Label::kNear);

    EmitReturn(instr, true);
    __ bind(&no_padding);
  }

  EmitReturn(instr, false);
  if (no_frame_start != -1) {
    info()->AddNoFrameRange(no_frame_start, masm_->pc_offset());
  }
}


void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
  Register result = ToRegister(instr->result());
  __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle()));
  if (instr->hydrogen()->RequiresHoleCheck()) {
    __ cmp(result, factory()->the_hole_value());
    DeoptimizeIf(equal, instr, "hole");
  }
}


template <class T>
void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
  DCHECK(FLAG_vector_ics);
  Register vector_register = ToRegister(instr->temp_vector());
  Register slot_register = VectorLoadICDescriptor::SlotRegister();
  DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
  DCHECK(slot_register.is(eax));

  AllowDeferredHandleDereference vector_structure_check;
  Handle<TypeFeedbackVector> vector = instr->hydrogen()->feedback_vector();
  __ mov(vector_register, vector);
  // No need to allocate this register.
  FeedbackVectorICSlot slot = instr->hydrogen()->slot();
  int index = vector->GetIndex(slot);
  __ mov(slot_register, Immediate(Smi::FromInt(index)));
}


void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->global_object())
             .is(LoadDescriptor::ReceiverRegister()));
  DCHECK(ToRegister(instr->result()).is(eax));

  __ mov(LoadDescriptor::NameRegister(), instr->name());
  if (FLAG_vector_ics) {
    EmitVectorLoadICRegisters<LLoadGlobalGeneric>(instr);
  }
  ContextualMode mode = instr->for_typeof() ? NOT_CONTEXTUAL : CONTEXTUAL;
  Handle<Code> ic = CodeFactory::LoadICInOptimizedCode(isolate(), mode).code();
  CallCode(ic, RelocInfo::CODE_TARGET, instr);
}


void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) {
  Register value = ToRegister(instr->value());
  Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle();

  // If the cell we are storing to contains the hole it could have
  // been deleted from the property dictionary. In that case, we need
  // to update the property details in the property dictionary to mark
  // it as no longer deleted. We deoptimize in that case.
  if (instr->hydrogen()->RequiresHoleCheck()) {
    __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value());
    DeoptimizeIf(equal, instr, "hole");
  }

  // Store the value.
  __ mov(Operand::ForCell(cell_handle), value);
  // Cells are always rescanned, so no write barrier here.
}


void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
  Register context = ToRegister(instr->context());
  Register result = ToRegister(instr->result());
  __ mov(result, ContextOperand(context, instr->slot_index()));

  if (instr->hydrogen()->RequiresHoleCheck()) {
    __ cmp(result, factory()->the_hole_value());
    if (instr->hydrogen()->DeoptimizesOnHole()) {
      DeoptimizeIf(equal, instr, "hole");
    } else {
      Label is_not_hole;
      __ j(not_equal, &is_not_hole, Label::kNear);
      __ mov(result, factory()->undefined_value());
      __ bind(&is_not_hole);
    }
  }
}


void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
  Register context = ToRegister(instr->context());
  Register value = ToRegister(instr->value());

  Label skip_assignment;

  Operand target = ContextOperand(context, instr->slot_index());
  if (instr->hydrogen()->RequiresHoleCheck()) {
    __ cmp(target, factory()->the_hole_value());
    if (instr->hydrogen()->DeoptimizesOnHole()) {
      DeoptimizeIf(equal, instr, "hole");
    } else {
      __ j(not_equal, &skip_assignment, Label::kNear);
    }
  }

  __ mov(target, value);
  if (instr->hydrogen()->NeedsWriteBarrier()) {
    SmiCheck check_needed =
        instr->hydrogen()->value()->type().IsHeapObject()
            ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
    Register temp = ToRegister(instr->temp());
    int offset = Context::SlotOffset(instr->slot_index());
    __ RecordWriteContextSlot(context, offset, value, temp, kSaveFPRegs,
                              EMIT_REMEMBERED_SET, check_needed);
  }

  __ bind(&skip_assignment);
}


void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
  HObjectAccess access = instr->hydrogen()->access();
  int offset = access.offset();

  if (access.IsExternalMemory()) {
    Register result = ToRegister(instr->result());
    MemOperand operand = instr->object()->IsConstantOperand()
        ? MemOperand::StaticVariable(ToExternalReference(
                LConstantOperand::cast(instr->object())))
        : MemOperand(ToRegister(instr->object()), offset);
    __ Load(result, operand, access.representation());
    return;
  }

  Register object = ToRegister(instr->object());
  if (instr->hydrogen()->representation().IsDouble()) {
    X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
    return;
  }

  Register result = ToRegister(instr->result());
  if (!access.IsInobject()) {
    __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
    object = result;
  }
  __ Load(result, FieldOperand(object, offset), access.representation());
}


void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
  DCHECK(!operand->IsDoubleRegister());
  if (operand->IsConstantOperand()) {
    Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
    AllowDeferredHandleDereference smi_check;
    if (object->IsSmi()) {
      __ Push(Handle<Smi>::cast(object));
    } else {
      __ PushHeapObject(Handle<HeapObject>::cast(object));
    }
  } else if (operand->IsRegister()) {
    __ push(ToRegister(operand));
  } else {
    __ push(ToOperand(operand));
  }
}


void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
  DCHECK(ToRegister(instr->result()).is(eax));

  __ mov(LoadDescriptor::NameRegister(), instr->name());
  if (FLAG_vector_ics) {
    EmitVectorLoadICRegisters<LLoadNamedGeneric>(instr);
  }
  Handle<Code> ic =
      CodeFactory::LoadICInOptimizedCode(isolate(), NOT_CONTEXTUAL).code();
  CallCode(ic, RelocInfo::CODE_TARGET, instr);
}


void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
  Register function = ToRegister(instr->function());
  Register temp = ToRegister(instr->temp());
  Register result = ToRegister(instr->result());

  // Get the prototype or initial map from the function.
  __ mov(result,
         FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));

  // Check that the function has a prototype or an initial map.
  __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
  DeoptimizeIf(equal, instr, "hole");

  // If the function does not have an initial map, we're done.
  Label done;
  __ CmpObjectType(result, MAP_TYPE, temp);
  __ j(not_equal, &done, Label::kNear);

  // Get the prototype from the initial map.
  __ mov(result, FieldOperand(result, Map::kPrototypeOffset));

  // All done.
  __ bind(&done);
}


void LCodeGen::DoLoadRoot(LLoadRoot* instr) {
  Register result = ToRegister(instr->result());
  __ LoadRoot(result, instr->index());
}


void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) {
  Register arguments = ToRegister(instr->arguments());
  Register result = ToRegister(instr->result());
  if (instr->length()->IsConstantOperand() &&
      instr->index()->IsConstantOperand()) {
    int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
    int const_length = ToInteger32(LConstantOperand::cast(instr->length()));
    int index = (const_length - const_index) + 1;
    __ mov(result, Operand(arguments, index * kPointerSize));
  } else {
    Register length = ToRegister(instr->length());
    Operand index = ToOperand(instr->index());
    // There are two words between the frame pointer and the last argument.
    // Subtracting from length accounts for one of them add one more.
    __ sub(length, index);
    __ mov(result, Operand(arguments, length, times_4, kPointerSize));
  }
}


void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) {
  ElementsKind elements_kind = instr->elements_kind();
  LOperand* key = instr->key();
  if (!key->IsConstantOperand() &&
      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
                                  elements_kind)) {
    __ SmiUntag(ToRegister(key));
  }
  Operand operand(BuildFastArrayOperand(
      instr->elements(),
      key,
      instr->hydrogen()->key()->representation(),
      elements_kind,
      instr->base_offset()));
  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
      elements_kind == FLOAT32_ELEMENTS) {
    X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
             elements_kind == FLOAT64_ELEMENTS) {
    X87Mov(ToX87Register(instr->result()), operand);
  } else {
    Register result(ToRegister(instr->result()));
    switch (elements_kind) {
      case EXTERNAL_INT8_ELEMENTS:
      case INT8_ELEMENTS:
        __ movsx_b(result, operand);
        break;
      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
      case EXTERNAL_UINT8_ELEMENTS:
      case UINT8_ELEMENTS:
      case UINT8_CLAMPED_ELEMENTS:
        __ movzx_b(result, operand);
        break;
      case EXTERNAL_INT16_ELEMENTS:
      case INT16_ELEMENTS:
        __ movsx_w(result, operand);
        break;
      case EXTERNAL_UINT16_ELEMENTS:
      case UINT16_ELEMENTS:
        __ movzx_w(result, operand);
        break;
      case EXTERNAL_INT32_ELEMENTS:
      case INT32_ELEMENTS:
        __ mov(result, operand);
        break;
      case EXTERNAL_UINT32_ELEMENTS:
      case UINT32_ELEMENTS:
        __ mov(result, operand);
        if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
          __ test(result, Operand(result));
          DeoptimizeIf(negative, instr, "negative value");
        }
        break;
      case EXTERNAL_FLOAT32_ELEMENTS:
      case EXTERNAL_FLOAT64_ELEMENTS:
      case FLOAT32_ELEMENTS:
      case FLOAT64_ELEMENTS:
      case FAST_SMI_ELEMENTS:
      case FAST_ELEMENTS:
      case FAST_DOUBLE_ELEMENTS:
      case FAST_HOLEY_SMI_ELEMENTS:
      case FAST_HOLEY_ELEMENTS:
      case FAST_HOLEY_DOUBLE_ELEMENTS:
      case DICTIONARY_ELEMENTS:
      case SLOPPY_ARGUMENTS_ELEMENTS:
        UNREACHABLE();
        break;
    }
  }
}


void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
  if (instr->hydrogen()->RequiresHoleCheck()) {
    Operand hole_check_operand = BuildFastArrayOperand(
        instr->elements(), instr->key(),
        instr->hydrogen()->key()->representation(),
        FAST_DOUBLE_ELEMENTS,
        instr->base_offset() + sizeof(kHoleNanLower32));
    __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
    DeoptimizeIf(equal, instr, "hole");
  }

  Operand double_load_operand = BuildFastArrayOperand(
      instr->elements(),
      instr->key(),
      instr->hydrogen()->key()->representation(),
      FAST_DOUBLE_ELEMENTS,
      instr->base_offset());
  X87Mov(ToX87Register(instr->result()), double_load_operand);
}


void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
  Register result = ToRegister(instr->result());

  // Load the result.
  __ mov(result,
         BuildFastArrayOperand(instr->elements(), instr->key(),
                               instr->hydrogen()->key()->representation(),
                               FAST_ELEMENTS, instr->base_offset()));

  // Check for the hole value.
  if (instr->hydrogen()->RequiresHoleCheck()) {
    if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
      __ test(result, Immediate(kSmiTagMask));
      DeoptimizeIf(not_equal, instr, "not a Smi");
    } else {
      __ cmp(result, factory()->the_hole_value());
      DeoptimizeIf(equal, instr, "hole");
    }
  }
}


void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
  if (instr->is_typed_elements()) {
    DoLoadKeyedExternalArray(instr);
  } else if (instr->hydrogen()->representation().IsDouble()) {
    DoLoadKeyedFixedDoubleArray(instr);
  } else {
    DoLoadKeyedFixedArray(instr);
  }
}


Operand LCodeGen::BuildFastArrayOperand(
    LOperand* elements_pointer,
    LOperand* key,
    Representation key_representation,
    ElementsKind elements_kind,
    uint32_t base_offset) {
  Register elements_pointer_reg = ToRegister(elements_pointer);
  int element_shift_size = ElementsKindToShiftSize(elements_kind);
  int shift_size = element_shift_size;
  if (key->IsConstantOperand()) {
    int constant_value = ToInteger32(LConstantOperand::cast(key));
    if (constant_value & 0xF0000000) {
      Abort(kArrayIndexConstantValueTooBig);
    }
    return Operand(elements_pointer_reg,
                   ((constant_value) << shift_size)
                       + base_offset);
  } else {
    // Take the tag bit into account while computing the shift size.
    if (key_representation.IsSmi() && (shift_size >= 1)) {
      shift_size -= kSmiTagSize;
    }
    ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
    return Operand(elements_pointer_reg,
                   ToRegister(key),
                   scale_factor,
                   base_offset);
  }
}


void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->object()).is(LoadDescriptor::ReceiverRegister()));
  DCHECK(ToRegister(instr->key()).is(LoadDescriptor::NameRegister()));

  if (FLAG_vector_ics) {
    EmitVectorLoadICRegisters<LLoadKeyedGeneric>(instr);
  }

  Handle<Code> ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate()).code();
  CallCode(ic, RelocInfo::CODE_TARGET, instr);
}


void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) {
  Register result = ToRegister(instr->result());

  if (instr->hydrogen()->from_inlined()) {
    __ lea(result, Operand(esp, -2 * kPointerSize));
  } else {
    // Check for arguments adapter frame.
    Label done, adapted;
    __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
    __ mov(result, Operand(result, StandardFrameConstants::kContextOffset));
    __ cmp(Operand(result),
           Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
    __ j(equal, &adapted, Label::kNear);

    // No arguments adaptor frame.
    __ mov(result, Operand(ebp));
    __ jmp(&done, Label::kNear);

    // Arguments adaptor frame present.
    __ bind(&adapted);
    __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));

    // Result is the frame pointer for the frame if not adapted and for the real
    // frame below the adaptor frame if adapted.
    __ bind(&done);
  }
}


void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
  Operand elem = ToOperand(instr->elements());
  Register result = ToRegister(instr->result());

  Label done;

  // If no arguments adaptor frame the number of arguments is fixed.
  __ cmp(ebp, elem);
  __ mov(result, Immediate(scope()->num_parameters()));
  __ j(equal, &done, Label::kNear);

  // Arguments adaptor frame present. Get argument length from there.
  __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
  __ mov(result, Operand(result,
                         ArgumentsAdaptorFrameConstants::kLengthOffset));
  __ SmiUntag(result);

  // Argument length is in result register.
  __ bind(&done);
}


void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) {
  Register receiver = ToRegister(instr->receiver());
  Register function = ToRegister(instr->function());

  // If the receiver is null or undefined, we have to pass the global
  // object as a receiver to normal functions. Values have to be
  // passed unchanged to builtins and strict-mode functions.
  Label receiver_ok, global_object;
  Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
  Register scratch = ToRegister(instr->temp());

  if (!instr->hydrogen()->known_function()) {
    // Do not transform the receiver to object for strict mode
    // functions.
    __ mov(scratch,
           FieldOperand(function, JSFunction::kSharedFunctionInfoOffset));
    __ test_b(FieldOperand(scratch, SharedFunctionInfo::kStrictModeByteOffset),
              1 << SharedFunctionInfo::kStrictModeBitWithinByte);
    __ j(not_equal, &receiver_ok, dist);

    // Do not transform the receiver to object for builtins.
    __ test_b(FieldOperand(scratch, SharedFunctionInfo::kNativeByteOffset),
              1 << SharedFunctionInfo::kNativeBitWithinByte);
    __ j(not_equal, &receiver_ok, dist);
  }

  // Normal function. Replace undefined or null with global receiver.
  __ cmp(receiver, factory()->null_value());
  __ j(equal, &global_object, Label::kNear);
  __ cmp(receiver, factory()->undefined_value());
  __ j(equal, &global_object, Label::kNear);

  // The receiver should be a JS object.
  __ test(receiver, Immediate(kSmiTagMask));
  DeoptimizeIf(equal, instr, "Smi");
  __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch);
  DeoptimizeIf(below, instr, "not a JavaScript object");

  __ jmp(&receiver_ok, Label::kNear);
  __ bind(&global_object);
  __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
  const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
  __ mov(receiver, Operand(receiver, global_offset));
  const int proxy_offset = GlobalObject::kGlobalProxyOffset;
  __ mov(receiver, FieldOperand(receiver, proxy_offset));
  __ bind(&receiver_ok);
}


void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
  Register receiver = ToRegister(instr->receiver());
  Register function = ToRegister(instr->function());
  Register length = ToRegister(instr->length());
  Register elements = ToRegister(instr->elements());
  DCHECK(receiver.is(eax));  // Used for parameter count.
  DCHECK(function.is(edi));  // Required by InvokeFunction.
  DCHECK(ToRegister(instr->result()).is(eax));

  // Copy the arguments to this function possibly from the
  // adaptor frame below it.
  const uint32_t kArgumentsLimit = 1 * KB;
  __ cmp(length, kArgumentsLimit);
  DeoptimizeIf(above, instr, "too many arguments");

  __ push(receiver);
  __ mov(receiver, length);

  // Loop through the arguments pushing them onto the execution
  // stack.
  Label invoke, loop;
  // length is a small non-negative integer, due to the test above.
  __ test(length, Operand(length));
  __ j(zero, &invoke, Label::kNear);
  __ bind(&loop);
  __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
  __ dec(length);
  __ j(not_zero, &loop);

  // Invoke the function.
  __ bind(&invoke);
  DCHECK(instr->HasPointerMap());
  LPointerMap* pointers = instr->pointer_map();
  SafepointGenerator safepoint_generator(
      this, pointers, Safepoint::kLazyDeopt);
  ParameterCount actual(eax);
  __ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
}


void LCodeGen::DoDebugBreak(LDebugBreak* instr) {
  __ int3();
}


void LCodeGen::DoPushArgument(LPushArgument* instr) {
  LOperand* argument = instr->value();
  EmitPushTaggedOperand(argument);
}


void LCodeGen::DoDrop(LDrop* instr) {
  __ Drop(instr->count());
}


void LCodeGen::DoThisFunction(LThisFunction* instr) {
  Register result = ToRegister(instr->result());
  __ mov(result, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
}


void LCodeGen::DoContext(LContext* instr) {
  Register result = ToRegister(instr->result());
  if (info()->IsOptimizing()) {
    __ mov(result, Operand(ebp, StandardFrameConstants::kContextOffset));
  } else {
    // If there is no frame, the context must be in esi.
    DCHECK(result.is(esi));
  }
}


void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  __ push(esi);  // The context is the first argument.
  __ push(Immediate(instr->hydrogen()->pairs()));
  __ push(Immediate(Smi::FromInt(instr->hydrogen()->flags())));
  CallRuntime(Runtime::kDeclareGlobals, 3, instr);
}


void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
                                 int formal_parameter_count,
                                 int arity,
                                 LInstruction* instr,
                                 EDIState edi_state) {
  bool dont_adapt_arguments =
      formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
  bool can_invoke_directly =
      dont_adapt_arguments || formal_parameter_count == arity;

  if (can_invoke_directly) {
    if (edi_state == EDI_UNINITIALIZED) {
      __ LoadHeapObject(edi, function);
    }

    // Change context.
    __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));

    // Set eax to arguments count if adaption is not needed. Assumes that eax
    // is available to write to at this point.
    if (dont_adapt_arguments) {
      __ mov(eax, arity);
    }

    // Invoke function directly.
    if (function.is_identical_to(info()->closure())) {
      __ CallSelf();
    } else {
      __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
    }
    RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
  } else {
    // We need to adapt arguments.
    LPointerMap* pointers = instr->pointer_map();
    SafepointGenerator generator(
        this, pointers, Safepoint::kLazyDeopt);
    ParameterCount count(arity);
    ParameterCount expected(formal_parameter_count);
    __ InvokeFunction(function, expected, count, CALL_FUNCTION, generator);
  }
}


void LCodeGen::DoTailCallThroughMegamorphicCache(
    LTailCallThroughMegamorphicCache* instr) {
  Register receiver = ToRegister(instr->receiver());
  Register name = ToRegister(instr->name());
  DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
  DCHECK(name.is(LoadDescriptor::NameRegister()));
  Register slot = FLAG_vector_ics ? ToRegister(instr->slot()) : no_reg;
  Register vector = FLAG_vector_ics ? ToRegister(instr->vector()) : no_reg;

  Register scratch = ebx;
  Register extra = edi;
  DCHECK(!extra.is(slot) && !extra.is(vector));
  DCHECK(!scratch.is(receiver) && !scratch.is(name));
  DCHECK(!extra.is(receiver) && !extra.is(name));

  // Important for the tail-call.
  bool must_teardown_frame = NeedsEagerFrame();

  if (!instr->hydrogen()->is_just_miss()) {
    if (FLAG_vector_ics) {
      __ push(slot);
      __ push(vector);
    }

    // The probe will tail call to a handler if found.
    // If --vector-ics is on, then it knows to pop the two args first.
    DCHECK(!instr->hydrogen()->is_keyed_load());
    isolate()->stub_cache()->GenerateProbe(
        masm(), Code::LOAD_IC, instr->hydrogen()->flags(), must_teardown_frame,
        receiver, name, scratch, extra);

    if (FLAG_vector_ics) {
      __ pop(vector);
      __ pop(slot);
    }
  }

  // Tail call to miss if we ended up here.
  if (must_teardown_frame) __ leave();
  if (instr->hydrogen()->is_keyed_load()) {
    KeyedLoadIC::GenerateMiss(masm());
  } else {
    LoadIC::GenerateMiss(masm());
  }
}


void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
  DCHECK(ToRegister(instr->result()).is(eax));

  if (instr->hydrogen()->IsTailCall()) {
    if (NeedsEagerFrame()) __ leave();

    if (instr->target()->IsConstantOperand()) {
      LConstantOperand* target = LConstantOperand::cast(instr->target());
      Handle<Code> code = Handle<Code>::cast(ToHandle(target));
      __ jmp(code, RelocInfo::CODE_TARGET);
    } else {
      DCHECK(instr->target()->IsRegister());
      Register target = ToRegister(instr->target());
      __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
      __ jmp(target);
    }
  } else {
    LPointerMap* pointers = instr->pointer_map();
    SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);

    if (instr->target()->IsConstantOperand()) {
      LConstantOperand* target = LConstantOperand::cast(instr->target());
      Handle<Code> code = Handle<Code>::cast(ToHandle(target));
      generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
      __ call(code, RelocInfo::CODE_TARGET);
    } else {
      DCHECK(instr->target()->IsRegister());
      Register target = ToRegister(instr->target());
      generator.BeforeCall(__ CallSize(Operand(target)));
      __ add(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
      __ call(target);
    }
    generator.AfterCall();
  }
}


void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
  DCHECK(ToRegister(instr->function()).is(edi));
  DCHECK(ToRegister(instr->result()).is(eax));

  if (instr->hydrogen()->pass_argument_count()) {
    __ mov(eax, instr->arity());
  }

  // Change context.
  __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));

  bool is_self_call = false;
  if (instr->hydrogen()->function()->IsConstant()) {
    HConstant* fun_const = HConstant::cast(instr->hydrogen()->function());
    Handle<JSFunction> jsfun =
      Handle<JSFunction>::cast(fun_const->handle(isolate()));
    is_self_call = jsfun.is_identical_to(info()->closure());
  }

  if (is_self_call) {
    __ CallSelf();
  } else {
    __ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
  }

  RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
}


void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
  Register input_reg = ToRegister(instr->value());
  __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
         factory()->heap_number_map());
  DeoptimizeIf(not_equal, instr, "not a heap number");

  Label slow, allocated, done;
  Register tmp = input_reg.is(eax) ? ecx : eax;
  Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx;

  // Preserve the value of all registers.
  PushSafepointRegistersScope scope(this);

  __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
  // Check the sign of the argument. If the argument is positive, just
  // return it. We do not need to patch the stack since |input| and
  // |result| are the same register and |input| will be restored
  // unchanged by popping safepoint registers.
  __ test(tmp, Immediate(HeapNumber::kSignMask));
  __ j(zero, &done, Label::kNear);

  __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow);
  __ jmp(&allocated, Label::kNear);

  // Slow case: Call the runtime system to do the number allocation.
  __ bind(&slow);
  CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0,
                          instr, instr->context());
  // Set the pointer to the new heap number in tmp.
  if (!tmp.is(eax)) __ mov(tmp, eax);
  // Restore input_reg after call to runtime.
  __ LoadFromSafepointRegisterSlot(input_reg, input_reg);

  __ bind(&allocated);
  __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset));
  __ and_(tmp2, ~HeapNumber::kSignMask);
  __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2);
  __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
  __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2);
  __ StoreToSafepointRegisterSlot(input_reg, tmp);

  __ bind(&done);
}


void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
  Register input_reg = ToRegister(instr->value());
  __ test(input_reg, Operand(input_reg));
  Label is_positive;
  __ j(not_sign, &is_positive, Label::kNear);
  __ neg(input_reg);  // Sets flags.
  DeoptimizeIf(negative, instr, "overflow");
  __ bind(&is_positive);
}


void LCodeGen::DoMathAbs(LMathAbs* instr) {
  // Class for deferred case.
  class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
   public:
    DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
                                    LMathAbs* instr,
                                    const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE {
      codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
    }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LMathAbs* instr_;
  };

  DCHECK(instr->value()->Equals(instr->result()));
  Representation r = instr->hydrogen()->value()->representation();

  if (r.IsDouble()) {
    X87Register value = ToX87Register(instr->value());
    X87Fxch(value);
    __ fabs();
  } else if (r.IsSmiOrInteger32()) {
    EmitIntegerMathAbs(instr);
  } else {  // Tagged case.
    DeferredMathAbsTaggedHeapNumber* deferred =
        new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_);
    Register input_reg = ToRegister(instr->value());
    // Smi check.
    __ JumpIfNotSmi(input_reg, deferred->entry());
    EmitIntegerMathAbs(instr);
    __ bind(deferred->exit());
  }
}


void LCodeGen::DoMathFloor(LMathFloor* instr) {
  Register output_reg = ToRegister(instr->result());
  X87Register input_reg = ToX87Register(instr->value());
  X87Fxch(input_reg);

  Label not_minus_zero, done;
  // Deoptimize on unordered.
  __ fldz();
  __ fld(1);
  __ FCmp();
  DeoptimizeIf(parity_even, instr, "NaN");
  __ j(below, &not_minus_zero, Label::kNear);

  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    // Check for negative zero.
    __ j(not_equal, &not_minus_zero, Label::kNear);
    // +- 0.0.
    __ fld(0);
    __ FXamSign();
    DeoptimizeIf(not_zero, instr, "minus zero");
    __ Move(output_reg, Immediate(0));
    __ jmp(&done, Label::kFar);
  }

  // Positive input.
  // rc=01B, round down.
  __ bind(&not_minus_zero);
  __ fnclex();
  __ X87SetRC(0x0400);
  __ sub(esp, Immediate(kPointerSize));
  __ fist_s(Operand(esp, 0));
  __ pop(output_reg);
  __ X87CheckIA();
  DeoptimizeIf(equal, instr, "overflow");
  __ fnclex();
  __ X87SetRC(0x0000);
  __ bind(&done);
}


void LCodeGen::DoMathRound(LMathRound* instr) {
  X87Register input_reg = ToX87Register(instr->value());
  Register result = ToRegister(instr->result());
  X87Fxch(input_reg);
  Label below_one_half, below_minus_one_half, done;

  ExternalReference one_half = ExternalReference::address_of_one_half();
  ExternalReference minus_one_half =
      ExternalReference::address_of_minus_one_half();

  __ fld_d(Operand::StaticVariable(one_half));
  __ fld(1);
  __ FCmp();
  __ j(carry, &below_one_half);

  // Use rounds towards zero, since 0.5 <= x, we use floor(0.5 + x)
  __ fld(0);
  __ fadd_d(Operand::StaticVariable(one_half));
  // rc=11B, round toward zero.
  __ X87SetRC(0x0c00);
  __ sub(esp, Immediate(kPointerSize));
  // Clear exception bits.
  __ fnclex();
  __ fistp_s(MemOperand(esp, 0));
  // Check overflow.
  __ X87CheckIA();
  __ pop(result);
  DeoptimizeIf(equal, instr, "conversion overflow");
  __ fnclex();
  // Restore round mode.
  __ X87SetRC(0x0000);
  __ jmp(&done);

  __ bind(&below_one_half);
  __ fld_d(Operand::StaticVariable(minus_one_half));
  __ fld(1);
  __ FCmp();
  __ j(carry, &below_minus_one_half);
  // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
  // we can ignore the difference between a result of -0 and +0.
  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
    // If the sign is positive, we return +0.
    __ fld(0);
    __ FXamSign();
    DeoptimizeIf(not_zero, instr, "minus zero");
  }
  __ Move(result, Immediate(0));
  __ jmp(&done);

  __ bind(&below_minus_one_half);
  __ fld(0);
  __ fadd_d(Operand::StaticVariable(one_half));
  // rc=01B, round down.
  __ X87SetRC(0x0400);
  __ sub(esp, Immediate(kPointerSize));
  // Clear exception bits.
  __ fnclex();
  __ fistp_s(MemOperand(esp, 0));
  // Check overflow.
  __ X87CheckIA();
  __ pop(result);
  DeoptimizeIf(equal, instr, "conversion overflow");
  __ fnclex();
  // Restore round mode.
  __ X87SetRC(0x0000);

  __ bind(&done);
}


void LCodeGen::DoMathFround(LMathFround* instr) {
  X87Register input_reg = ToX87Register(instr->value());
  X87Fxch(input_reg);
  __ sub(esp, Immediate(kPointerSize));
  __ fstp_s(MemOperand(esp, 0));
  X87Fld(MemOperand(esp, 0), kX87FloatOperand);
  __ add(esp, Immediate(kPointerSize));
}


void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
  X87Register input = ToX87Register(instr->value());
  X87Register result_reg = ToX87Register(instr->result());
  Register temp_result = ToRegister(instr->temp1());
  Register temp = ToRegister(instr->temp2());
  Label slow, done, smi, finish;
  DCHECK(result_reg.is(input));

  // Store input into Heap number and call runtime function kMathExpRT.
  if (FLAG_inline_new) {
    __ AllocateHeapNumber(temp_result, temp, no_reg, &slow);
    __ jmp(&done, Label::kNear);
  }

  // Slow case: Call the runtime system to do the number allocation.
  __ bind(&slow);
  {
    // TODO(3095996): Put a valid pointer value in the stack slot where the
    // result register is stored, as this register is in the pointer map, but
    // contains an integer value.
    __ Move(temp_result, Immediate(0));

    // Preserve the value of all registers.
    PushSafepointRegistersScope scope(this);

    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
    RecordSafepointWithRegisters(
       instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
    __ StoreToSafepointRegisterSlot(temp_result, eax);
  }
  __ bind(&done);
  X87LoadForUsage(input);
  __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset));

  {
    // Preserve the value of all registers.
    PushSafepointRegistersScope scope(this);

    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
    __ push(temp_result);
    __ CallRuntimeSaveDoubles(Runtime::kMathSqrtRT);
    RecordSafepointWithRegisters(instr->pointer_map(), 1,
                                 Safepoint::kNoLazyDeopt);
    __ StoreToSafepointRegisterSlot(temp_result, eax);
  }
  X87PrepareToWrite(result_reg);
  // return value of MathExpRT is Smi or Heap Number.
  __ JumpIfSmi(temp_result, &smi);
  // Heap number(double)
  __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
  __ jmp(&finish);
  // SMI
  __ bind(&smi);
  __ SmiUntag(temp_result);
  __ push(temp_result);
  __ fild_s(MemOperand(esp, 0));
  __ pop(temp_result);
  __ bind(&finish);
  X87CommitWrite(result_reg);
}


void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
  X87Register input_reg = ToX87Register(instr->value());
  DCHECK(ToX87Register(instr->result()).is(input_reg));
  X87Fxch(input_reg);
  // Note that according to ECMA-262 15.8.2.13:
  // Math.pow(-Infinity, 0.5) == Infinity
  // Math.sqrt(-Infinity) == NaN
  Label done, sqrt;
  // Check base for -Infinity. C3 == 0, C2 == 1, C1 == 1 and C0 == 1
  __ fxam();
  __ push(eax);
  __ fnstsw_ax();
  __ and_(eax, Immediate(0x4700));
  __ cmp(eax, Immediate(0x0700));
  __ j(not_equal, &sqrt, Label::kNear);
  // If input is -Infinity, return Infinity.
  __ fchs();
  __ jmp(&done, Label::kNear);

  // Square root.
  __ bind(&sqrt);
  __ fldz();
  __ faddp();  // Convert -0 to +0.
  __ fsqrt();
  __ bind(&done);
  __ pop(eax);
}


void LCodeGen::DoPower(LPower* instr) {
  Representation exponent_type = instr->hydrogen()->right()->representation();
  X87Register result = ToX87Register(instr->result());
  // Having marked this as a call, we can use any registers.
  X87Register base = ToX87Register(instr->left());
  ExternalReference one_half = ExternalReference::address_of_one_half();

  if (exponent_type.IsSmi()) {
    Register exponent = ToRegister(instr->right());
    X87LoadForUsage(base);
    __ SmiUntag(exponent);
    __ push(exponent);
    __ fild_s(MemOperand(esp, 0));
    __ pop(exponent);
  } else if (exponent_type.IsTagged()) {
    Register exponent = ToRegister(instr->right());
    Register temp = exponent.is(ecx) ? eax : ecx;
    Label no_deopt, done;
    X87LoadForUsage(base);
    __ JumpIfSmi(exponent, &no_deopt);
    __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, temp);
    DeoptimizeIf(not_equal, instr, "not a heap number");
    // Heap number(double)
    __ fld_d(FieldOperand(exponent, HeapNumber::kValueOffset));
    __ jmp(&done);
    // SMI
    __ bind(&no_deopt);
    __ SmiUntag(exponent);
    __ push(exponent);
    __ fild_s(MemOperand(esp, 0));
    __ pop(exponent);
    __ bind(&done);
  } else if (exponent_type.IsInteger32()) {
    Register exponent = ToRegister(instr->right());
    X87LoadForUsage(base);
    __ push(exponent);
    __ fild_s(MemOperand(esp, 0));
    __ pop(exponent);
  } else {
    DCHECK(exponent_type.IsDouble());
    X87Register exponent_double = ToX87Register(instr->right());
    X87LoadForUsage(base, exponent_double);
  }

  // FP data stack {base, exponent(TOS)}.
  // Handle (exponent==+-0.5 && base == -0).
  Label not_plus_0;
  __ fld(0);
  __ fabs();
  X87Fld(Operand::StaticVariable(one_half), kX87DoubleOperand);
  __ FCmp();
  __ j(parity_even, &not_plus_0, Label::kNear);  // NaN.
  __ j(not_equal, &not_plus_0, Label::kNear);
  __ fldz();
  // FP data stack {base, exponent(TOS), zero}.
  __ faddp(2);
  __ bind(&not_plus_0);

  {
    __ PrepareCallCFunction(4, eax);
    __ fstp_d(MemOperand(esp, kDoubleSize));  // Exponent value.
    __ fstp_d(MemOperand(esp, 0));            // Base value.
    X87PrepareToWrite(result);
    __ CallCFunction(ExternalReference::power_double_double_function(isolate()),
                     4);
    // Return value is in st(0) on ia32.
    X87CommitWrite(result);
  }
}


void LCodeGen::DoMathLog(LMathLog* instr) {
  DCHECK(instr->value()->Equals(instr->result()));
  X87Register input_reg = ToX87Register(instr->value());
  X87Fxch(input_reg);

  Label positive, done, zero, nan_result;
  __ fldz();
  __ fld(1);
  __ FCmp();
  __ j(below, &nan_result, Label::kNear);
  __ j(equal, &zero, Label::kNear);
  // Positive input.
  // {input, ln2}.
  __ fldln2();
  // {ln2, input}.
  __ fxch();
  // {result}.
  __ fyl2x();
  __ jmp(&done, Label::kNear);

  __ bind(&nan_result);
  ExternalReference nan =
      ExternalReference::address_of_canonical_non_hole_nan();
  X87PrepareToWrite(input_reg);
  __ fld_d(Operand::StaticVariable(nan));
  X87CommitWrite(input_reg);
  __ jmp(&done, Label::kNear);

  __ bind(&zero);
  ExternalReference ninf = ExternalReference::address_of_negative_infinity();
  X87PrepareToWrite(input_reg);
  __ fld_d(Operand::StaticVariable(ninf));
  X87CommitWrite(input_reg);

  __ bind(&done);
}


void LCodeGen::DoMathClz32(LMathClz32* instr) {
  Register input = ToRegister(instr->value());
  Register result = ToRegister(instr->result());
  Label not_zero_input;
  __ bsr(result, input);

  __ j(not_zero, &not_zero_input);
  __ Move(result, Immediate(63));  // 63^31 == 32

  __ bind(&not_zero_input);
  __ xor_(result, Immediate(31));  // for x in [0..31], 31^x == 31-x.
}


void LCodeGen::DoMathExp(LMathExp* instr) {
  X87Register input = ToX87Register(instr->value());
  X87Register result_reg = ToX87Register(instr->result());
  Register temp_result = ToRegister(instr->temp1());
  Register temp = ToRegister(instr->temp2());
  Label slow, done, smi, finish;
  DCHECK(result_reg.is(input));

  // Store input into Heap number and call runtime function kMathExpRT.
  if (FLAG_inline_new) {
    __ AllocateHeapNumber(temp_result, temp, no_reg, &slow);
    __ jmp(&done, Label::kNear);
  }

  // Slow case: Call the runtime system to do the number allocation.
  __ bind(&slow);
  {
    // TODO(3095996): Put a valid pointer value in the stack slot where the
    // result register is stored, as this register is in the pointer map, but
    // contains an integer value.
    __ Move(temp_result, Immediate(0));

    // Preserve the value of all registers.
    PushSafepointRegistersScope scope(this);

    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
    RecordSafepointWithRegisters(instr->pointer_map(), 0,
                                 Safepoint::kNoLazyDeopt);
    __ StoreToSafepointRegisterSlot(temp_result, eax);
  }
  __ bind(&done);
  X87LoadForUsage(input);
  __ fstp_d(FieldOperand(temp_result, HeapNumber::kValueOffset));

  {
    // Preserve the value of all registers.
    PushSafepointRegistersScope scope(this);

    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
    __ push(temp_result);
    __ CallRuntimeSaveDoubles(Runtime::kMathExpRT);
    RecordSafepointWithRegisters(instr->pointer_map(), 1,
                                 Safepoint::kNoLazyDeopt);
    __ StoreToSafepointRegisterSlot(temp_result, eax);
  }
  X87PrepareToWrite(result_reg);
  // return value of MathExpRT is Smi or Heap Number.
  __ JumpIfSmi(temp_result, &smi);
  // Heap number(double)
  __ fld_d(FieldOperand(temp_result, HeapNumber::kValueOffset));
  __ jmp(&finish);
  // SMI
  __ bind(&smi);
  __ SmiUntag(temp_result);
  __ push(temp_result);
  __ fild_s(MemOperand(esp, 0));
  __ pop(temp_result);
  __ bind(&finish);
  X87CommitWrite(result_reg);
}


void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->function()).is(edi));
  DCHECK(instr->HasPointerMap());

  Handle<JSFunction> known_function = instr->hydrogen()->known_function();
  if (known_function.is_null()) {
    LPointerMap* pointers = instr->pointer_map();
    SafepointGenerator generator(
        this, pointers, Safepoint::kLazyDeopt);
    ParameterCount count(instr->arity());
    __ InvokeFunction(edi, count, CALL_FUNCTION, generator);
  } else {
    CallKnownFunction(known_function,
                      instr->hydrogen()->formal_parameter_count(),
                      instr->arity(),
                      instr,
                      EDI_CONTAINS_TARGET);
  }
}


void LCodeGen::DoCallFunction(LCallFunction* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->function()).is(edi));
  DCHECK(ToRegister(instr->result()).is(eax));

  int arity = instr->arity();
  CallFunctionStub stub(isolate(), arity, instr->hydrogen()->function_flags());
  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
}


void LCodeGen::DoCallNew(LCallNew* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->constructor()).is(edi));
  DCHECK(ToRegister(instr->result()).is(eax));

  // No cell in ebx for construct type feedback in optimized code
  __ mov(ebx, isolate()->factory()->undefined_value());
  CallConstructStub stub(isolate(), NO_CALL_CONSTRUCTOR_FLAGS);
  __ Move(eax, Immediate(instr->arity()));
  CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
}


void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->constructor()).is(edi));
  DCHECK(ToRegister(instr->result()).is(eax));

  __ Move(eax, Immediate(instr->arity()));
  __ mov(ebx, isolate()->factory()->undefined_value());
  ElementsKind kind = instr->hydrogen()->elements_kind();
  AllocationSiteOverrideMode override_mode =
      (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
          ? DISABLE_ALLOCATION_SITES
          : DONT_OVERRIDE;

  if (instr->arity() == 0) {
    ArrayNoArgumentConstructorStub stub(isolate(), kind, override_mode);
    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
  } else if (instr->arity() == 1) {
    Label done;
    if (IsFastPackedElementsKind(kind)) {
      Label packed_case;
      // We might need a change here
      // look at the first argument
      __ mov(ecx, Operand(esp, 0));
      __ test(ecx, ecx);
      __ j(zero, &packed_case, Label::kNear);

      ElementsKind holey_kind = GetHoleyElementsKind(kind);
      ArraySingleArgumentConstructorStub stub(isolate(),
                                              holey_kind,
                                              override_mode);
      CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
      __ jmp(&done, Label::kNear);
      __ bind(&packed_case);
    }

    ArraySingleArgumentConstructorStub stub(isolate(), kind, override_mode);
    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
    __ bind(&done);
  } else {
    ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
    CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
  }
}


void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles());
}


void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
  Register function = ToRegister(instr->function());
  Register code_object = ToRegister(instr->code_object());
  __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
  __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
}


void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
  Register result = ToRegister(instr->result());
  Register base = ToRegister(instr->base_object());
  if (instr->offset()->IsConstantOperand()) {
    LConstantOperand* offset = LConstantOperand::cast(instr->offset());
    __ lea(result, Operand(base, ToInteger32(offset)));
  } else {
    Register offset = ToRegister(instr->offset());
    __ lea(result, Operand(base, offset, times_1, 0));
  }
}


void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
  Representation representation = instr->hydrogen()->field_representation();

  HObjectAccess access = instr->hydrogen()->access();
  int offset = access.offset();

  if (access.IsExternalMemory()) {
    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
    MemOperand operand = instr->object()->IsConstantOperand()
        ? MemOperand::StaticVariable(
            ToExternalReference(LConstantOperand::cast(instr->object())))
        : MemOperand(ToRegister(instr->object()), offset);
    if (instr->value()->IsConstantOperand()) {
      LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
      __ mov(operand, Immediate(ToInteger32(operand_value)));
    } else {
      Register value = ToRegister(instr->value());
      __ Store(value, operand, representation);
    }
    return;
  }

  Register object = ToRegister(instr->object());
  __ AssertNotSmi(object);
  DCHECK(!representation.IsSmi() ||
         !instr->value()->IsConstantOperand() ||
         IsSmi(LConstantOperand::cast(instr->value())));
  if (representation.IsDouble()) {
    DCHECK(access.IsInobject());
    DCHECK(!instr->hydrogen()->has_transition());
    DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
    X87Register value = ToX87Register(instr->value());
    X87Mov(FieldOperand(object, offset), value);
    return;
  }

  if (instr->hydrogen()->has_transition()) {
    Handle<Map> transition = instr->hydrogen()->transition_map();
    AddDeprecationDependency(transition);
    __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
    if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
      Register temp = ToRegister(instr->temp());
      Register temp_map = ToRegister(instr->temp_map());
      __ mov(temp_map, transition);
      __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map);
      // Update the write barrier for the map field.
      __ RecordWriteForMap(object, transition, temp_map, temp, kSaveFPRegs);
    }
  }

  // Do the store.
  Register write_register = object;
  if (!access.IsInobject()) {
    write_register = ToRegister(instr->temp());
    __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
  }

  MemOperand operand = FieldOperand(write_register, offset);
  if (instr->value()->IsConstantOperand()) {
    LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
    if (operand_value->IsRegister()) {
      Register value = ToRegister(operand_value);
      __ Store(value, operand, representation);
    } else if (representation.IsInteger32()) {
      Immediate immediate = ToImmediate(operand_value, representation);
      DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
      __ mov(operand, immediate);
    } else {
      Handle<Object> handle_value = ToHandle(operand_value);
      DCHECK(!instr->hydrogen()->NeedsWriteBarrier());
      __ mov(operand, handle_value);
    }
  } else {
    Register value = ToRegister(instr->value());
    __ Store(value, operand, representation);
  }

  if (instr->hydrogen()->NeedsWriteBarrier()) {
    Register value = ToRegister(instr->value());
    Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
    // Update the write barrier for the object for in-object properties.
    __ RecordWriteField(write_register, offset, value, temp, kSaveFPRegs,
                        EMIT_REMEMBERED_SET,
                        instr->hydrogen()->SmiCheckForWriteBarrier(),
                        instr->hydrogen()->PointersToHereCheckForValue());
  }
}


void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
  DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));

  __ mov(StoreDescriptor::NameRegister(), instr->name());
  Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
  CallCode(ic, RelocInfo::CODE_TARGET, instr);
}


void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
  Condition cc = instr->hydrogen()->allow_equality() ? above : above_equal;
  if (instr->index()->IsConstantOperand()) {
    __ cmp(ToOperand(instr->length()),
           ToImmediate(LConstantOperand::cast(instr->index()),
                       instr->hydrogen()->length()->representation()));
    cc = CommuteCondition(cc);
  } else if (instr->length()->IsConstantOperand()) {
    __ cmp(ToOperand(instr->index()),
           ToImmediate(LConstantOperand::cast(instr->length()),
                       instr->hydrogen()->index()->representation()));
  } else {
    __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
  }
  if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
    Label done;
    __ j(NegateCondition(cc), &done, Label::kNear);
    __ int3();
    __ bind(&done);
  } else {
    DeoptimizeIf(cc, instr, "out of bounds");
  }
}


void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
  ElementsKind elements_kind = instr->elements_kind();
  LOperand* key = instr->key();
  if (!key->IsConstantOperand() &&
      ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
                                  elements_kind)) {
    __ SmiUntag(ToRegister(key));
  }
  Operand operand(BuildFastArrayOperand(
      instr->elements(),
      key,
      instr->hydrogen()->key()->representation(),
      elements_kind,
      instr->base_offset()));
  if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
      elements_kind == FLOAT32_ELEMENTS) {
    X87Mov(operand, ToX87Register(instr->value()), kX87FloatOperand);
  } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
             elements_kind == FLOAT64_ELEMENTS) {
    X87Mov(operand, ToX87Register(instr->value()));
  } else {
    Register value = ToRegister(instr->value());
    switch (elements_kind) {
      case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
      case EXTERNAL_UINT8_ELEMENTS:
      case EXTERNAL_INT8_ELEMENTS:
      case UINT8_ELEMENTS:
      case INT8_ELEMENTS:
      case UINT8_CLAMPED_ELEMENTS:
        __ mov_b(operand, value);
        break;
      case EXTERNAL_INT16_ELEMENTS:
      case EXTERNAL_UINT16_ELEMENTS:
      case UINT16_ELEMENTS:
      case INT16_ELEMENTS:
        __ mov_w(operand, value);
        break;
      case EXTERNAL_INT32_ELEMENTS:
      case EXTERNAL_UINT32_ELEMENTS:
      case UINT32_ELEMENTS:
      case INT32_ELEMENTS:
        __ mov(operand, value);
        break;
      case EXTERNAL_FLOAT32_ELEMENTS:
      case EXTERNAL_FLOAT64_ELEMENTS:
      case FLOAT32_ELEMENTS:
      case FLOAT64_ELEMENTS:
      case FAST_SMI_ELEMENTS:
      case FAST_ELEMENTS:
      case FAST_DOUBLE_ELEMENTS:
      case FAST_HOLEY_SMI_ELEMENTS:
      case FAST_HOLEY_ELEMENTS:
      case FAST_HOLEY_DOUBLE_ELEMENTS:
      case DICTIONARY_ELEMENTS:
      case SLOPPY_ARGUMENTS_ELEMENTS:
        UNREACHABLE();
        break;
    }
  }
}


void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
  ExternalReference canonical_nan_reference =
      ExternalReference::address_of_canonical_non_hole_nan();
  Operand double_store_operand = BuildFastArrayOperand(
      instr->elements(),
      instr->key(),
      instr->hydrogen()->key()->representation(),
      FAST_DOUBLE_ELEMENTS,
      instr->base_offset());

  // Can't use SSE2 in the serializer
  if (instr->hydrogen()->IsConstantHoleStore()) {
    // This means we should store the (double) hole. No floating point
    // registers required.
    double nan_double = FixedDoubleArray::hole_nan_as_double();
    uint64_t int_val = bit_cast<uint64_t, double>(nan_double);
    int32_t lower = static_cast<int32_t>(int_val);
    int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));

    __ mov(double_store_operand, Immediate(lower));
    Operand double_store_operand2 = BuildFastArrayOperand(
        instr->elements(),
        instr->key(),
        instr->hydrogen()->key()->representation(),
        FAST_DOUBLE_ELEMENTS,
        instr->base_offset() + kPointerSize);
    __ mov(double_store_operand2, Immediate(upper));
  } else {
    Label no_special_nan_handling;
    X87Register value = ToX87Register(instr->value());
    X87Fxch(value);

    if (instr->NeedsCanonicalization()) {
      __ fld(0);
      __ fld(0);
      __ FCmp();

      __ j(parity_odd, &no_special_nan_handling, Label::kNear);
      __ sub(esp, Immediate(kDoubleSize));
      __ fst_d(MemOperand(esp, 0));
      __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
             Immediate(kHoleNanUpper32));
      __ add(esp, Immediate(kDoubleSize));
      Label canonicalize;
      __ j(not_equal, &canonicalize, Label::kNear);
      __ jmp(&no_special_nan_handling, Label::kNear);
      __ bind(&canonicalize);
      __ fstp(0);
      __ fld_d(Operand::StaticVariable(canonical_nan_reference));
    }

    __ bind(&no_special_nan_handling);
    __ fst_d(double_store_operand);
  }
}


void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
  Register elements = ToRegister(instr->elements());
  Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;

  Operand operand = BuildFastArrayOperand(
      instr->elements(),
      instr->key(),
      instr->hydrogen()->key()->representation(),
      FAST_ELEMENTS,
      instr->base_offset());
  if (instr->value()->IsRegister()) {
    __ mov(operand, ToRegister(instr->value()));
  } else {
    LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
    if (IsSmi(operand_value)) {
      Immediate immediate = ToImmediate(operand_value, Representation::Smi());
      __ mov(operand, immediate);
    } else {
      DCHECK(!IsInteger32(operand_value));
      Handle<Object> handle_value = ToHandle(operand_value);
      __ mov(operand, handle_value);
    }
  }

  if (instr->hydrogen()->NeedsWriteBarrier()) {
    DCHECK(instr->value()->IsRegister());
    Register value = ToRegister(instr->value());
    DCHECK(!instr->key()->IsConstantOperand());
    SmiCheck check_needed =
        instr->hydrogen()->value()->type().IsHeapObject()
          ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
    // Compute address of modified element and store it into key register.
    __ lea(key, operand);
    __ RecordWrite(elements, key, value, kSaveFPRegs, EMIT_REMEMBERED_SET,
                   check_needed,
                   instr->hydrogen()->PointersToHereCheckForValue());
  }
}


void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
  // By cases...external, fast-double, fast
  if (instr->is_typed_elements()) {
    DoStoreKeyedExternalArray(instr);
  } else if (instr->hydrogen()->value()->representation().IsDouble()) {
    DoStoreKeyedFixedDoubleArray(instr);
  } else {
    DoStoreKeyedFixedArray(instr);
  }
}


void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->object()).is(StoreDescriptor::ReceiverRegister()));
  DCHECK(ToRegister(instr->key()).is(StoreDescriptor::NameRegister()));
  DCHECK(ToRegister(instr->value()).is(StoreDescriptor::ValueRegister()));

  Handle<Code> ic =
      CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code();
  CallCode(ic, RelocInfo::CODE_TARGET, instr);
}


void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
  Register object = ToRegister(instr->object());
  Register temp = ToRegister(instr->temp());
  Label no_memento_found;
  __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
  DeoptimizeIf(equal, instr, "memento found");
  __ bind(&no_memento_found);
}


void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
  Register object_reg = ToRegister(instr->object());

  Handle<Map> from_map = instr->original_map();
  Handle<Map> to_map = instr->transitioned_map();
  ElementsKind from_kind = instr->from_kind();
  ElementsKind to_kind = instr->to_kind();

  Label not_applicable;
  bool is_simple_map_transition =
      IsSimpleMapChangeTransition(from_kind, to_kind);
  Label::Distance branch_distance =
      is_simple_map_transition ? Label::kNear : Label::kFar;
  __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
  __ j(not_equal, &not_applicable, branch_distance);
  if (is_simple_map_transition) {
    Register new_map_reg = ToRegister(instr->new_map_temp());
    __ mov(FieldOperand(object_reg, HeapObject::kMapOffset),
           Immediate(to_map));
    // Write barrier.
    DCHECK_NE(instr->temp(), NULL);
    __ RecordWriteForMap(object_reg, to_map, new_map_reg,
                         ToRegister(instr->temp()), kDontSaveFPRegs);
  } else {
    DCHECK(ToRegister(instr->context()).is(esi));
    DCHECK(object_reg.is(eax));
    PushSafepointRegistersScope scope(this);
    __ mov(ebx, to_map);
    bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
    TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
    __ CallStub(&stub);
    RecordSafepointWithLazyDeopt(instr,
        RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
  }
  __ bind(&not_applicable);
}


void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
  class DeferredStringCharCodeAt FINAL : public LDeferredCode {
   public:
    DeferredStringCharCodeAt(LCodeGen* codegen,
                             LStringCharCodeAt* instr,
                             const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE { codegen()->DoDeferredStringCharCodeAt(instr_); }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LStringCharCodeAt* instr_;
  };

  DeferredStringCharCodeAt* deferred =
      new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_);

  StringCharLoadGenerator::Generate(masm(),
                                    factory(),
                                    ToRegister(instr->string()),
                                    ToRegister(instr->index()),
                                    ToRegister(instr->result()),
                                    deferred->entry());
  __ bind(deferred->exit());
}


void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
  Register string = ToRegister(instr->string());
  Register result = ToRegister(instr->result());

  // TODO(3095996): Get rid of this. For now, we need to make the
  // result register contain a valid pointer because it is already
  // contained in the register pointer map.
  __ Move(result, Immediate(0));

  PushSafepointRegistersScope scope(this);
  __ push(string);
  // Push the index as a smi. This is safe because of the checks in
  // DoStringCharCodeAt above.
  STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue);
  if (instr->index()->IsConstantOperand()) {
    Immediate immediate = ToImmediate(LConstantOperand::cast(instr->index()),
                                      Representation::Smi());
    __ push(immediate);
  } else {
    Register index = ToRegister(instr->index());
    __ SmiTag(index);
    __ push(index);
  }
  CallRuntimeFromDeferred(Runtime::kStringCharCodeAtRT, 2,
                          instr, instr->context());
  __ AssertSmi(eax);
  __ SmiUntag(eax);
  __ StoreToSafepointRegisterSlot(result, eax);
}


void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
  class DeferredStringCharFromCode FINAL : public LDeferredCode {
   public:
    DeferredStringCharFromCode(LCodeGen* codegen,
                               LStringCharFromCode* instr,
                               const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE {
      codegen()->DoDeferredStringCharFromCode(instr_);
    }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LStringCharFromCode* instr_;
  };

  DeferredStringCharFromCode* deferred =
      new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_);

  DCHECK(instr->hydrogen()->value()->representation().IsInteger32());
  Register char_code = ToRegister(instr->char_code());
  Register result = ToRegister(instr->result());
  DCHECK(!char_code.is(result));

  __ cmp(char_code, String::kMaxOneByteCharCode);
  __ j(above, deferred->entry());
  __ Move(result, Immediate(factory()->single_character_string_cache()));
  __ mov(result, FieldOperand(result,
                              char_code, times_pointer_size,
                              FixedArray::kHeaderSize));
  __ cmp(result, factory()->undefined_value());
  __ j(equal, deferred->entry());
  __ bind(deferred->exit());
}


void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
  Register char_code = ToRegister(instr->char_code());
  Register result = ToRegister(instr->result());

  // TODO(3095996): Get rid of this. For now, we need to make the
  // result register contain a valid pointer because it is already
  // contained in the register pointer map.
  __ Move(result, Immediate(0));

  PushSafepointRegistersScope scope(this);
  __ SmiTag(char_code);
  __ push(char_code);
  CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context());
  __ StoreToSafepointRegisterSlot(result, eax);
}


void LCodeGen::DoStringAdd(LStringAdd* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  DCHECK(ToRegister(instr->left()).is(edx));
  DCHECK(ToRegister(instr->right()).is(eax));
  StringAddStub stub(isolate(),
                     instr->hydrogen()->flags(),
                     instr->hydrogen()->pretenure_flag());
  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
}


void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
  LOperand* input = instr->value();
  LOperand* output = instr->result();
  DCHECK(input->IsRegister() || input->IsStackSlot());
  DCHECK(output->IsDoubleRegister());
  if (input->IsRegister()) {
    Register input_reg = ToRegister(input);
    __ push(input_reg);
    X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand);
    __ pop(input_reg);
  } else {
    X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
  }
}


void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
  LOperand* input = instr->value();
  LOperand* output = instr->result();
  X87Register res = ToX87Register(output);
  X87PrepareToWrite(res);
  __ LoadUint32NoSSE2(ToRegister(input));
  X87CommitWrite(res);
}


void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
  class DeferredNumberTagI FINAL : public LDeferredCode {
   public:
    DeferredNumberTagI(LCodeGen* codegen,
                       LNumberTagI* instr,
                       const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE {
      codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
                                       SIGNED_INT32);
    }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LNumberTagI* instr_;
  };

  LOperand* input = instr->value();
  DCHECK(input->IsRegister() && input->Equals(instr->result()));
  Register reg = ToRegister(input);

  DeferredNumberTagI* deferred =
      new(zone()) DeferredNumberTagI(this, instr, x87_stack_);
  __ SmiTag(reg);
  __ j(overflow, deferred->entry());
  __ bind(deferred->exit());
}


void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
  class DeferredNumberTagU FINAL : public LDeferredCode {
   public:
    DeferredNumberTagU(LCodeGen* codegen,
                       LNumberTagU* instr,
                       const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE {
      codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
                                       UNSIGNED_INT32);
    }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LNumberTagU* instr_;
  };

  LOperand* input = instr->value();
  DCHECK(input->IsRegister() && input->Equals(instr->result()));
  Register reg = ToRegister(input);

  DeferredNumberTagU* deferred =
      new(zone()) DeferredNumberTagU(this, instr, x87_stack_);
  __ cmp(reg, Immediate(Smi::kMaxValue));
  __ j(above, deferred->entry());
  __ SmiTag(reg);
  __ bind(deferred->exit());
}


void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
                                     LOperand* value,
                                     LOperand* temp,
                                     IntegerSignedness signedness) {
  Label done, slow;
  Register reg = ToRegister(value);
  Register tmp = ToRegister(temp);

  if (signedness == SIGNED_INT32) {
    // There was overflow, so bits 30 and 31 of the original integer
    // disagree. Try to allocate a heap number in new space and store
    // the value in there. If that fails, call the runtime system.
    __ SmiUntag(reg);
    __ xor_(reg, 0x80000000);
    __ push(reg);
    __ fild_s(Operand(esp, 0));
    __ pop(reg);
  } else {
    // There's no fild variant for unsigned values, so zero-extend to a 64-bit
    // int manually.
    __ push(Immediate(0));
    __ push(reg);
    __ fild_d(Operand(esp, 0));
    __ pop(reg);
    __ pop(reg);
  }

  if (FLAG_inline_new) {
    __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
    __ jmp(&done, Label::kNear);
  }

  // Slow case: Call the runtime system to do the number allocation.
  __ bind(&slow);
  {
    // TODO(3095996): Put a valid pointer value in the stack slot where the
    // result register is stored, as this register is in the pointer map, but
    // contains an integer value.
    __ Move(reg, Immediate(0));

    // Preserve the value of all registers.
    PushSafepointRegistersScope scope(this);

    // NumberTagI and NumberTagD use the context from the frame, rather than
    // the environment's HContext or HInlinedContext value.
    // They only call Runtime::kAllocateHeapNumber.
    // The corresponding HChange instructions are added in a phase that does
    // not have easy access to the local context.
    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
    __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
    RecordSafepointWithRegisters(
        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
    __ StoreToSafepointRegisterSlot(reg, eax);
  }

  __ bind(&done);
  __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
}


void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
  class DeferredNumberTagD FINAL : public LDeferredCode {
   public:
    DeferredNumberTagD(LCodeGen* codegen,
                       LNumberTagD* instr,
                       const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE { codegen()->DoDeferredNumberTagD(instr_); }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LNumberTagD* instr_;
  };

  Register reg = ToRegister(instr->result());

  // Put the value to the top of stack
  X87Register src = ToX87Register(instr->value());
  // Don't use X87LoadForUsage here, which is only used by Instruction which
  // clobbers fp registers.
  x87_stack_.Fxch(src);

  DeferredNumberTagD* deferred =
      new(zone()) DeferredNumberTagD(this, instr, x87_stack_);
  if (FLAG_inline_new) {
    Register tmp = ToRegister(instr->temp());
    __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
  } else {
    __ jmp(deferred->entry());
  }
  __ bind(deferred->exit());
  __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset));
}


void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
  // TODO(3095996): Get rid of this. For now, we need to make the
  // result register contain a valid pointer because it is already
  // contained in the register pointer map.
  Register reg = ToRegister(instr->result());
  __ Move(reg, Immediate(0));

  PushSafepointRegistersScope scope(this);
  // NumberTagI and NumberTagD use the context from the frame, rather than
  // the environment's HContext or HInlinedContext value.
  // They only call Runtime::kAllocateHeapNumber.
  // The corresponding HChange instructions are added in a phase that does
  // not have easy access to the local context.
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
  __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
  RecordSafepointWithRegisters(
      instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
  __ StoreToSafepointRegisterSlot(reg, eax);
}


void LCodeGen::DoSmiTag(LSmiTag* instr) {
  HChange* hchange = instr->hydrogen();
  Register input = ToRegister(instr->value());
  if (hchange->CheckFlag(HValue::kCanOverflow) &&
      hchange->value()->CheckFlag(HValue::kUint32)) {
    __ test(input, Immediate(0xc0000000));
    DeoptimizeIf(not_zero, instr, "overflow");
  }
  __ SmiTag(input);
  if (hchange->CheckFlag(HValue::kCanOverflow) &&
      !hchange->value()->CheckFlag(HValue::kUint32)) {
    DeoptimizeIf(overflow, instr, "overflow");
  }
}


void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
  LOperand* input = instr->value();
  Register result = ToRegister(input);
  DCHECK(input->IsRegister() && input->Equals(instr->result()));
  if (instr->needs_check()) {
    __ test(result, Immediate(kSmiTagMask));
    DeoptimizeIf(not_zero, instr, "not a Smi");
  } else {
    __ AssertSmi(result);
  }
  __ SmiUntag(result);
}


void LCodeGen::EmitNumberUntagDNoSSE2(LNumberUntagD* instr, Register input_reg,
                                      Register temp_reg, X87Register res_reg,
                                      NumberUntagDMode mode) {
  bool can_convert_undefined_to_nan =
      instr->hydrogen()->can_convert_undefined_to_nan();
  bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();

  Label load_smi, done;

  X87PrepareToWrite(res_reg);
  if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
    // Smi check.
    __ JumpIfSmi(input_reg, &load_smi);

    // Heap number map check.
    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
           factory()->heap_number_map());
    if (!can_convert_undefined_to_nan) {
      DeoptimizeIf(not_equal, instr, "not a heap number");
    } else {
      Label heap_number, convert;
      __ j(equal, &heap_number);

      // Convert undefined (or hole) to NaN.
      __ cmp(input_reg, factory()->undefined_value());
      DeoptimizeIf(not_equal, instr, "not a heap number/undefined");

      __ bind(&convert);
      ExternalReference nan =
          ExternalReference::address_of_canonical_non_hole_nan();
      __ fld_d(Operand::StaticVariable(nan));
      __ jmp(&done, Label::kNear);

      __ bind(&heap_number);
    }
    // Heap number to x87 conversion.
    __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
    if (deoptimize_on_minus_zero) {
      __ fldz();
      __ FCmp();
      __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
      __ j(not_zero, &done, Label::kNear);

      // Use general purpose registers to check if we have -0.0
      __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
      __ test(temp_reg, Immediate(HeapNumber::kSignMask));
      __ j(zero, &done, Label::kNear);

      // Pop FPU stack before deoptimizing.
      __ fstp(0);
      DeoptimizeIf(not_zero, instr, "minus zero");
    }
    __ jmp(&done, Label::kNear);
  } else {
    DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
  }

  __ bind(&load_smi);
  // Clobbering a temp is faster than re-tagging the
  // input register since we avoid dependencies.
  __ mov(temp_reg, input_reg);
  __ SmiUntag(temp_reg);  // Untag smi before converting to float.
  __ push(temp_reg);
  __ fild_s(Operand(esp, 0));
  __ add(esp, Immediate(kPointerSize));
  __ bind(&done);
  X87CommitWrite(res_reg);
}


void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
  Register input_reg = ToRegister(instr->value());

  // The input was optimistically untagged; revert it.
  STATIC_ASSERT(kSmiTagSize == 1);
  __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag));

  if (instr->truncating()) {
    Label no_heap_number, check_bools, check_false;

    // Heap number map check.
    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
           factory()->heap_number_map());
    __ j(not_equal, &no_heap_number, Label::kNear);
    __ TruncateHeapNumberToI(input_reg, input_reg);
    __ jmp(done);

    __ bind(&no_heap_number);
    // Check for Oddballs. Undefined/False is converted to zero and True to one
    // for truncating conversions.
    __ cmp(input_reg, factory()->undefined_value());
    __ j(not_equal, &check_bools, Label::kNear);
    __ Move(input_reg, Immediate(0));
    __ jmp(done);

    __ bind(&check_bools);
    __ cmp(input_reg, factory()->true_value());
    __ j(not_equal, &check_false, Label::kNear);
    __ Move(input_reg, Immediate(1));
    __ jmp(done);

    __ bind(&check_false);
    __ cmp(input_reg, factory()->false_value());
    DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
    __ Move(input_reg, Immediate(0));
  } else {
    // TODO(olivf) Converting a number on the fpu is actually quite slow. We
    // should first try a fast conversion and then bailout to this slow case.
    __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
           isolate()->factory()->heap_number_map());
    DeoptimizeIf(not_equal, instr, "not a heap number");

    __ sub(esp, Immediate(kPointerSize));
    __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));

    if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
      Label no_precision_lost, not_nan, zero_check;
      __ fld(0);

      __ fist_s(MemOperand(esp, 0));
      __ fild_s(MemOperand(esp, 0));
      __ FCmp();
      __ pop(input_reg);

      __ j(equal, &no_precision_lost, Label::kNear);
      __ fstp(0);
      DeoptimizeIf(no_condition, instr, "lost precision");
      __ bind(&no_precision_lost);

      __ j(parity_odd, &not_nan);
      __ fstp(0);
      DeoptimizeIf(no_condition, instr, "NaN");
      __ bind(&not_nan);

      __ test(input_reg, Operand(input_reg));
      __ j(zero, &zero_check, Label::kNear);
      __ fstp(0);
      __ jmp(done);

      __ bind(&zero_check);
      // To check for minus zero, we load the value again as float, and check
      // if that is still 0.
      __ sub(esp, Immediate(kPointerSize));
      __ fstp_s(Operand(esp, 0));
      __ pop(input_reg);
      __ test(input_reg, Operand(input_reg));
      DeoptimizeIf(not_zero, instr, "minus zero");
    } else {
      __ fist_s(MemOperand(esp, 0));
      __ fild_s(MemOperand(esp, 0));
      __ FCmp();
      __ pop(input_reg);
      DeoptimizeIf(not_equal, instr, "lost precision");
      DeoptimizeIf(parity_even, instr, "NaN");
    }
  }
}


void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
  class DeferredTaggedToI FINAL : public LDeferredCode {
   public:
    DeferredTaggedToI(LCodeGen* codegen,
                      LTaggedToI* instr,
                      const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE { codegen()->DoDeferredTaggedToI(instr_, done()); }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LTaggedToI* instr_;
  };

  LOperand* input = instr->value();
  DCHECK(input->IsRegister());
  Register input_reg = ToRegister(input);
  DCHECK(input_reg.is(ToRegister(instr->result())));

  if (instr->hydrogen()->value()->representation().IsSmi()) {
    __ SmiUntag(input_reg);
  } else {
    DeferredTaggedToI* deferred =
        new(zone()) DeferredTaggedToI(this, instr, x87_stack_);
    // Optimistically untag the input.
    // If the input is a HeapObject, SmiUntag will set the carry flag.
    STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
    __ SmiUntag(input_reg);
    // Branch to deferred code if the input was tagged.
    // The deferred code will take care of restoring the tag.
    __ j(carry, deferred->entry());
    __ bind(deferred->exit());
  }
}


void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
  LOperand* input = instr->value();
  DCHECK(input->IsRegister());
  LOperand* temp = instr->temp();
  DCHECK(temp->IsRegister());
  LOperand* result = instr->result();
  DCHECK(result->IsDoubleRegister());

  Register input_reg = ToRegister(input);
  Register temp_reg = ToRegister(temp);

  HValue* value = instr->hydrogen()->value();
  NumberUntagDMode mode = value->representation().IsSmi()
      ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;

  EmitNumberUntagDNoSSE2(instr, input_reg, temp_reg, ToX87Register(result),
                         mode);
}


void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
  LOperand* input = instr->value();
  DCHECK(input->IsDoubleRegister());
  LOperand* result = instr->result();
  DCHECK(result->IsRegister());
  Register result_reg = ToRegister(result);

  if (instr->truncating()) {
    X87Register input_reg = ToX87Register(input);
    X87Fxch(input_reg);
    __ TruncateX87TOSToI(result_reg);
  } else {
    Label lost_precision, is_nan, minus_zero, done;
    X87Register input_reg = ToX87Register(input);
    X87Fxch(input_reg);
    __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
                 &lost_precision, &is_nan, &minus_zero);
    __ jmp(&done);
    __ bind(&lost_precision);
    DeoptimizeIf(no_condition, instr, "lost precision");
    __ bind(&is_nan);
    DeoptimizeIf(no_condition, instr, "NaN");
    __ bind(&minus_zero);
    DeoptimizeIf(no_condition, instr, "minus zero");
    __ bind(&done);
  }
}


void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
  LOperand* input = instr->value();
  DCHECK(input->IsDoubleRegister());
  LOperand* result = instr->result();
  DCHECK(result->IsRegister());
  Register result_reg = ToRegister(result);

  Label lost_precision, is_nan, minus_zero, done;
  X87Register input_reg = ToX87Register(input);
  X87Fxch(input_reg);
  __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
               &lost_precision, &is_nan, &minus_zero);
  __ jmp(&done);
  __ bind(&lost_precision);
  DeoptimizeIf(no_condition, instr, "lost precision");
  __ bind(&is_nan);
  DeoptimizeIf(no_condition, instr, "NaN");
  __ bind(&minus_zero);
  DeoptimizeIf(no_condition, instr, "minus zero");
  __ bind(&done);
  __ SmiTag(result_reg);
  DeoptimizeIf(overflow, instr, "overflow");
}


void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
  LOperand* input = instr->value();
  __ test(ToOperand(input), Immediate(kSmiTagMask));
  DeoptimizeIf(not_zero, instr, "not a Smi");
}


void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
  if (!instr->hydrogen()->value()->type().IsHeapObject()) {
    LOperand* input = instr->value();
    __ test(ToOperand(input), Immediate(kSmiTagMask));
    DeoptimizeIf(zero, instr, "Smi");
  }
}


void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
  Register input = ToRegister(instr->value());
  Register temp = ToRegister(instr->temp());

  __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));

  if (instr->hydrogen()->is_interval_check()) {
    InstanceType first;
    InstanceType last;
    instr->hydrogen()->GetCheckInterval(&first, &last);

    __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
            static_cast<int8_t>(first));

    // If there is only one type in the interval check for equality.
    if (first == last) {
      DeoptimizeIf(not_equal, instr, "wrong instance type");
    } else {
      DeoptimizeIf(below, instr, "wrong instance type");
      // Omit check for the last type.
      if (last != LAST_TYPE) {
        __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset),
                static_cast<int8_t>(last));
        DeoptimizeIf(above, instr, "wrong instance type");
      }
    }
  } else {
    uint8_t mask;
    uint8_t tag;
    instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);

    if (base::bits::IsPowerOfTwo32(mask)) {
      DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
      __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask);
      DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
    } else {
      __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
      __ and_(temp, mask);
      __ cmp(temp, tag);
      DeoptimizeIf(not_equal, instr, "wrong instance type");
    }
  }
}


void LCodeGen::DoCheckValue(LCheckValue* instr) {
  Handle<HeapObject> object = instr->hydrogen()->object().handle();
  if (instr->hydrogen()->object_in_new_space()) {
    Register reg = ToRegister(instr->value());
    Handle<Cell> cell = isolate()->factory()->NewCell(object);
    __ cmp(reg, Operand::ForCell(cell));
  } else {
    Operand operand = ToOperand(instr->value());
    __ cmp(operand, object);
  }
  DeoptimizeIf(not_equal, instr, "value mismatch");
}


void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
  {
    PushSafepointRegistersScope scope(this);
    __ push(object);
    __ xor_(esi, esi);
    __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
    RecordSafepointWithRegisters(
        instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);

    __ test(eax, Immediate(kSmiTagMask));
  }
  DeoptimizeIf(zero, instr, "instance migration failed");
}


void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
  class DeferredCheckMaps FINAL : public LDeferredCode {
   public:
    DeferredCheckMaps(LCodeGen* codegen,
                      LCheckMaps* instr,
                      Register object,
                      const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) {
      SetExit(check_maps());
    }
    void Generate() OVERRIDE {
      codegen()->DoDeferredInstanceMigration(instr_, object_);
    }
    Label* check_maps() { return &check_maps_; }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LCheckMaps* instr_;
    Label check_maps_;
    Register object_;
  };

  if (instr->hydrogen()->IsStabilityCheck()) {
    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
    for (int i = 0; i < maps->size(); ++i) {
      AddStabilityDependency(maps->at(i).handle());
    }
    return;
  }

  LOperand* input = instr->value();
  DCHECK(input->IsRegister());
  Register reg = ToRegister(input);

  DeferredCheckMaps* deferred = NULL;
  if (instr->hydrogen()->HasMigrationTarget()) {
    deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
    __ bind(deferred->check_maps());
  }

  const UniqueSet<Map>* maps = instr->hydrogen()->maps();
  Label success;
  for (int i = 0; i < maps->size() - 1; i++) {
    Handle<Map> map = maps->at(i).handle();
    __ CompareMap(reg, map);
    __ j(equal, &success, Label::kNear);
  }

  Handle<Map> map = maps->at(maps->size() - 1).handle();
  __ CompareMap(reg, map);
  if (instr->hydrogen()->HasMigrationTarget()) {
    __ j(not_equal, deferred->entry());
  } else {
    DeoptimizeIf(not_equal, instr, "wrong map");
  }

  __ bind(&success);
}


void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
  X87Register value_reg = ToX87Register(instr->unclamped());
  Register result_reg = ToRegister(instr->result());
  X87Fxch(value_reg);
  __ ClampTOSToUint8(result_reg);
}


void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
  DCHECK(instr->unclamped()->Equals(instr->result()));
  Register value_reg = ToRegister(instr->result());
  __ ClampUint8(value_reg);
}


void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
  Register input_reg = ToRegister(instr->unclamped());
  Register result_reg = ToRegister(instr->result());
  Register scratch = ToRegister(instr->scratch());
  Register scratch2 = ToRegister(instr->scratch2());
  Register scratch3 = ToRegister(instr->scratch3());
  Label is_smi, done, heap_number, valid_exponent,
      largest_value, zero_result, maybe_nan_or_infinity;

  __ JumpIfSmi(input_reg, &is_smi);

  // Check for heap number
  __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
         factory()->heap_number_map());
  __ j(equal, &heap_number, Label::kNear);

  // Check for undefined. Undefined is converted to zero for clamping
  // conversions.
  __ cmp(input_reg, factory()->undefined_value());
  DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
  __ jmp(&zero_result, Label::kNear);

  // Heap number
  __ bind(&heap_number);

  // Surprisingly, all of the hand-crafted bit-manipulations below are much
  // faster than the x86 FPU built-in instruction, especially since "banker's
  // rounding" would be additionally very expensive

  // Get exponent word.
  __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
  __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));

  // Test for negative values --> clamp to zero
  __ test(scratch, scratch);
  __ j(negative, &zero_result, Label::kNear);

  // Get exponent alone in scratch2.
  __ mov(scratch2, scratch);
  __ and_(scratch2, HeapNumber::kExponentMask);
  __ shr(scratch2, HeapNumber::kExponentShift);
  __ j(zero, &zero_result, Label::kNear);
  __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
  __ j(negative, &zero_result, Label::kNear);

  const uint32_t non_int8_exponent = 7;
  __ cmp(scratch2, Immediate(non_int8_exponent + 1));
  // If the exponent is too big, check for special values.
  __ j(greater, &maybe_nan_or_infinity, Label::kNear);

  __ bind(&valid_exponent);
  // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
  // < 7. The shift bias is the number of bits to shift the mantissa such that
  // with an exponent of 7 such the that top-most one is in bit 30, allowing
  // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to
  // 1).
  int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1;
  __ lea(result_reg, MemOperand(scratch2, shift_bias));
  // Here result_reg (ecx) is the shift, scratch is the exponent word.  Get the
  // top bits of the mantissa.
  __ and_(scratch, HeapNumber::kMantissaMask);
  // Put back the implicit 1 of the mantissa
  __ or_(scratch, 1 << HeapNumber::kExponentShift);
  // Shift up to round
  __ shl_cl(scratch);
  // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
  // use the bit in the "ones" place and add it to the "halves" place, which has
  // the effect of rounding to even.
  __ mov(scratch2, scratch);
  const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
  const uint32_t one_bit_shift = one_half_bit_shift + 1;
  __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
  __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
  Label no_round;
  __ j(less, &no_round, Label::kNear);
  Label round_up;
  __ mov(scratch2, Immediate(1 << one_half_bit_shift));
  __ j(greater, &round_up, Label::kNear);
  __ test(scratch3, scratch3);
  __ j(not_zero, &round_up, Label::kNear);
  __ mov(scratch2, scratch);
  __ and_(scratch2, Immediate(1 << one_bit_shift));
  __ shr(scratch2, 1);
  __ bind(&round_up);
  __ add(scratch, scratch2);
  __ j(overflow, &largest_value, Label::kNear);
  __ bind(&no_round);
  __ shr(scratch, 23);
  __ mov(result_reg, scratch);
  __ jmp(&done, Label::kNear);

  __ bind(&maybe_nan_or_infinity);
  // Check for NaN/Infinity, all other values map to 255
  __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
  __ j(not_equal, &largest_value, Label::kNear);

  // Check for NaN, which differs from Infinity in that at least one mantissa
  // bit is set.
  __ and_(scratch, HeapNumber::kMantissaMask);
  __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
  __ j(not_zero, &zero_result, Label::kNear);  // M!=0 --> NaN
  // Infinity -> Fall through to map to 255.

  __ bind(&largest_value);
  __ mov(result_reg, Immediate(255));
  __ jmp(&done, Label::kNear);

  __ bind(&zero_result);
  __ xor_(result_reg, result_reg);
  __ jmp(&done, Label::kNear);

  // smi
  __ bind(&is_smi);
  if (!input_reg.is(result_reg)) {
    __ mov(result_reg, input_reg);
  }
  __ SmiUntag(result_reg);
  __ ClampUint8(result_reg);
  __ bind(&done);
}


void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
  X87Register value_reg = ToX87Register(instr->value());
  Register result_reg = ToRegister(instr->result());
  X87Fxch(value_reg);
  __ sub(esp, Immediate(kDoubleSize));
  __ fst_d(Operand(esp, 0));
  if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
    __ mov(result_reg, Operand(esp, kPointerSize));
  } else {
    __ mov(result_reg, Operand(esp, 0));
  }
  __ add(esp, Immediate(kDoubleSize));
}


void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
  Register hi_reg = ToRegister(instr->hi());
  Register lo_reg = ToRegister(instr->lo());
  X87Register result_reg = ToX87Register(instr->result());
  // Follow below pattern to write a x87 fp register.
  X87PrepareToWrite(result_reg);
  __ sub(esp, Immediate(kDoubleSize));
  __ mov(Operand(esp, 0), lo_reg);
  __ mov(Operand(esp, kPointerSize), hi_reg);
  __ fld_d(Operand(esp, 0));
  __ add(esp, Immediate(kDoubleSize));
  X87CommitWrite(result_reg);
}


void LCodeGen::DoAllocate(LAllocate* instr) {
  class DeferredAllocate FINAL : public LDeferredCode {
   public:
    DeferredAllocate(LCodeGen* codegen,
                     LAllocate* instr,
                     const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE { codegen()->DoDeferredAllocate(instr_); }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LAllocate* instr_;
  };

  DeferredAllocate* deferred =
      new(zone()) DeferredAllocate(this, instr, x87_stack_);

  Register result = ToRegister(instr->result());
  Register temp = ToRegister(instr->temp());

  // Allocate memory for the object.
  AllocationFlags flags = TAG_OBJECT;
  if (instr->hydrogen()->MustAllocateDoubleAligned()) {
    flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
  }
  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
    DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation());
    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
    flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
    flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_DATA_SPACE);
  }

  if (instr->size()->IsConstantOperand()) {
    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
    if (size <= Page::kMaxRegularHeapObjectSize) {
      __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
    } else {
      __ jmp(deferred->entry());
    }
  } else {
    Register size = ToRegister(instr->size());
    __ Allocate(size, result, temp, no_reg, deferred->entry(), flags);
  }

  __ bind(deferred->exit());

  if (instr->hydrogen()->MustPrefillWithFiller()) {
    if (instr->size()->IsConstantOperand()) {
      int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
      __ mov(temp, (size / kPointerSize) - 1);
    } else {
      temp = ToRegister(instr->size());
      __ shr(temp, kPointerSizeLog2);
      __ dec(temp);
    }
    Label loop;
    __ bind(&loop);
    __ mov(FieldOperand(result, temp, times_pointer_size, 0),
        isolate()->factory()->one_pointer_filler_map());
    __ dec(temp);
    __ j(not_zero, &loop);
  }
}


void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
  Register result = ToRegister(instr->result());

  // TODO(3095996): Get rid of this. For now, we need to make the
  // result register contain a valid pointer because it is already
  // contained in the register pointer map.
  __ Move(result, Immediate(Smi::FromInt(0)));

  PushSafepointRegistersScope scope(this);
  if (instr->size()->IsRegister()) {
    Register size = ToRegister(instr->size());
    DCHECK(!size.is(result));
    __ SmiTag(ToRegister(instr->size()));
    __ push(size);
  } else {
    int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
    if (size >= 0 && size <= Smi::kMaxValue) {
      __ push(Immediate(Smi::FromInt(size)));
    } else {
      // We should never get here at runtime => abort
      __ int3();
      return;
    }
  }

  int flags = AllocateDoubleAlignFlag::encode(
      instr->hydrogen()->MustAllocateDoubleAligned());
  if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
    DCHECK(!instr->hydrogen()->IsOldDataSpaceAllocation());
    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
    flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE);
  } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
    DCHECK(!instr->hydrogen()->IsNewSpaceAllocation());
    flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE);
  } else {
    flags = AllocateTargetSpace::update(flags, NEW_SPACE);
  }
  __ push(Immediate(Smi::FromInt(flags)));

  CallRuntimeFromDeferred(
      Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
  __ StoreToSafepointRegisterSlot(result, eax);
}


void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
  DCHECK(ToRegister(instr->value()).is(eax));
  __ push(eax);
  CallRuntime(Runtime::kToFastProperties, 1, instr);
}


void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  Label materialized;
  // Registers will be used as follows:
  // ecx = literals array.
  // ebx = regexp literal.
  // eax = regexp literal clone.
  // esi = context.
  int literal_offset =
      FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index());
  __ LoadHeapObject(ecx, instr->hydrogen()->literals());
  __ mov(ebx, FieldOperand(ecx, literal_offset));
  __ cmp(ebx, factory()->undefined_value());
  __ j(not_equal, &materialized, Label::kNear);

  // Create regexp literal using runtime function
  // Result will be in eax.
  __ push(ecx);
  __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
  __ push(Immediate(instr->hydrogen()->pattern()));
  __ push(Immediate(instr->hydrogen()->flags()));
  CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr);
  __ mov(ebx, eax);

  __ bind(&materialized);
  int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
  Label allocated, runtime_allocate;
  __ Allocate(size, eax, ecx, edx, &runtime_allocate, TAG_OBJECT);
  __ jmp(&allocated, Label::kNear);

  __ bind(&runtime_allocate);
  __ push(ebx);
  __ push(Immediate(Smi::FromInt(size)));
  CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
  __ pop(ebx);

  __ bind(&allocated);
  // Copy the content into the newly allocated memory.
  // (Unroll copy loop once for better throughput).
  for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) {
    __ mov(edx, FieldOperand(ebx, i));
    __ mov(ecx, FieldOperand(ebx, i + kPointerSize));
    __ mov(FieldOperand(eax, i), edx);
    __ mov(FieldOperand(eax, i + kPointerSize), ecx);
  }
  if ((size % (2 * kPointerSize)) != 0) {
    __ mov(edx, FieldOperand(ebx, size - kPointerSize));
    __ mov(FieldOperand(eax, size - kPointerSize), edx);
  }
}


void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  // Use the fast case closure allocation code that allocates in new
  // space for nested functions that don't need literals cloning.
  bool pretenure = instr->hydrogen()->pretenure();
  if (!pretenure && instr->hydrogen()->has_no_literals()) {
    FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
                            instr->hydrogen()->kind());
    __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
    CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
  } else {
    __ push(esi);
    __ push(Immediate(instr->hydrogen()->shared_info()));
    __ push(Immediate(pretenure ? factory()->true_value()
                                : factory()->false_value()));
    CallRuntime(Runtime::kNewClosure, 3, instr);
  }
}


void LCodeGen::DoTypeof(LTypeof* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  LOperand* input = instr->value();
  EmitPushTaggedOperand(input);
  CallRuntime(Runtime::kTypeof, 1, instr);
}


void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
  Register input = ToRegister(instr->value());
  Condition final_branch_condition = EmitTypeofIs(instr, input);
  if (final_branch_condition != no_condition) {
    EmitBranch(instr, final_branch_condition);
  }
}


Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
  Label* true_label = instr->TrueLabel(chunk_);
  Label* false_label = instr->FalseLabel(chunk_);
  Handle<String> type_name = instr->type_literal();
  int left_block = instr->TrueDestination(chunk_);
  int right_block = instr->FalseDestination(chunk_);
  int next_block = GetNextEmittedBlock();

  Label::Distance true_distance = left_block == next_block ? Label::kNear
                                                           : Label::kFar;
  Label::Distance false_distance = right_block == next_block ? Label::kNear
                                                             : Label::kFar;
  Condition final_branch_condition = no_condition;
  if (String::Equals(type_name, factory()->number_string())) {
    __ JumpIfSmi(input, true_label, true_distance);
    __ cmp(FieldOperand(input, HeapObject::kMapOffset),
           factory()->heap_number_map());
    final_branch_condition = equal;

  } else if (String::Equals(type_name, factory()->string_string())) {
    __ JumpIfSmi(input, false_label, false_distance);
    __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
    __ j(above_equal, false_label, false_distance);
    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
              1 << Map::kIsUndetectable);
    final_branch_condition = zero;

  } else if (String::Equals(type_name, factory()->symbol_string())) {
    __ JumpIfSmi(input, false_label, false_distance);
    __ CmpObjectType(input, SYMBOL_TYPE, input);
    final_branch_condition = equal;

  } else if (String::Equals(type_name, factory()->boolean_string())) {
    __ cmp(input, factory()->true_value());
    __ j(equal, true_label, true_distance);
    __ cmp(input, factory()->false_value());
    final_branch_condition = equal;

  } else if (String::Equals(type_name, factory()->undefined_string())) {
    __ cmp(input, factory()->undefined_value());
    __ j(equal, true_label, true_distance);
    __ JumpIfSmi(input, false_label, false_distance);
    // Check for undetectable objects => true.
    __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
              1 << Map::kIsUndetectable);
    final_branch_condition = not_zero;

  } else if (String::Equals(type_name, factory()->function_string())) {
    STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
    __ JumpIfSmi(input, false_label, false_distance);
    __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
    __ j(equal, true_label, true_distance);
    __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
    final_branch_condition = equal;

  } else if (String::Equals(type_name, factory()->object_string())) {
    __ JumpIfSmi(input, false_label, false_distance);
    __ cmp(input, factory()->null_value());
    __ j(equal, true_label, true_distance);
    __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
    __ j(below, false_label, false_distance);
    __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
    __ j(above, false_label, false_distance);
    // Check for undetectable objects => false.
    __ test_b(FieldOperand(input, Map::kBitFieldOffset),
              1 << Map::kIsUndetectable);
    final_branch_condition = zero;

  } else {
    __ jmp(false_label, false_distance);
  }
  return final_branch_condition;
}


void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
  Register temp = ToRegister(instr->temp());

  EmitIsConstructCall(temp);
  EmitBranch(instr, equal);
}


void LCodeGen::EmitIsConstructCall(Register temp) {
  // Get the frame pointer for the calling frame.
  __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));

  // Skip the arguments adaptor frame if it exists.
  Label check_frame_marker;
  __ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
         Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
  __ j(not_equal, &check_frame_marker, Label::kNear);
  __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));

  // Check the marker in the calling frame.
  __ bind(&check_frame_marker);
  __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
         Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
}


void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) {
  if (!info()->IsStub()) {
    // Ensure that we have enough space after the previous lazy-bailout
    // instruction for patching the code here.
    int current_pc = masm()->pc_offset();
    if (current_pc < last_lazy_deopt_pc_ + space_needed) {
      int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
      __ Nop(padding_size);
    }
  }
  last_lazy_deopt_pc_ = masm()->pc_offset();
}


void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
  last_lazy_deopt_pc_ = masm()->pc_offset();
  DCHECK(instr->HasEnvironment());
  LEnvironment* env = instr->environment();
  RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
}


void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
  Deoptimizer::BailoutType type = instr->hydrogen()->type();
  // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
  // needed return address), even though the implementation of LAZY and EAGER is
  // now identical. When LAZY is eventually completely folded into EAGER, remove
  // the special case below.
  if (info()->IsStub() && type == Deoptimizer::EAGER) {
    type = Deoptimizer::LAZY;
  }
  DeoptimizeIf(no_condition, instr, instr->hydrogen()->reason(), type);
}


void LCodeGen::DoDummy(LDummy* instr) {
  // Nothing to see here, move on!
}


void LCodeGen::DoDummyUse(LDummyUse* instr) {
  // Nothing to see here, move on!
}


void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
  PushSafepointRegistersScope scope(this);
  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
  __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
  RecordSafepointWithLazyDeopt(
      instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
  DCHECK(instr->HasEnvironment());
  LEnvironment* env = instr->environment();
  safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
}


void LCodeGen::DoStackCheck(LStackCheck* instr) {
  class DeferredStackCheck FINAL : public LDeferredCode {
   public:
    DeferredStackCheck(LCodeGen* codegen,
                       LStackCheck* instr,
                       const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack), instr_(instr) { }
    void Generate() OVERRIDE { codegen()->DoDeferredStackCheck(instr_); }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LStackCheck* instr_;
  };

  DCHECK(instr->HasEnvironment());
  LEnvironment* env = instr->environment();
  // There is no LLazyBailout instruction for stack-checks. We have to
  // prepare for lazy deoptimization explicitly here.
  if (instr->hydrogen()->is_function_entry()) {
    // Perform stack overflow check.
    Label done;
    ExternalReference stack_limit =
        ExternalReference::address_of_stack_limit(isolate());
    __ cmp(esp, Operand::StaticVariable(stack_limit));
    __ j(above_equal, &done, Label::kNear);

    DCHECK(instr->context()->IsRegister());
    DCHECK(ToRegister(instr->context()).is(esi));
    CallCode(isolate()->builtins()->StackCheck(),
             RelocInfo::CODE_TARGET,
             instr);
    __ bind(&done);
  } else {
    DCHECK(instr->hydrogen()->is_backwards_branch());
    // Perform stack overflow check if this goto needs it before jumping.
    DeferredStackCheck* deferred_stack_check =
        new(zone()) DeferredStackCheck(this, instr, x87_stack_);
    ExternalReference stack_limit =
        ExternalReference::address_of_stack_limit(isolate());
    __ cmp(esp, Operand::StaticVariable(stack_limit));
    __ j(below, deferred_stack_check->entry());
    EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
    __ bind(instr->done_label());
    deferred_stack_check->SetExit(instr->done_label());
    RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
    // Don't record a deoptimization index for the safepoint here.
    // This will be done explicitly when emitting call and the safepoint in
    // the deferred code.
  }
}


void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
  // This is a pseudo-instruction that ensures that the environment here is
  // properly registered for deoptimization and records the assembler's PC
  // offset.
  LEnvironment* environment = instr->environment();

  // If the environment were already registered, we would have no way of
  // backpatching it with the spill slot operands.
  DCHECK(!environment->HasBeenRegistered());
  RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);

  GenerateOsrPrologue();
}


void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
  DCHECK(ToRegister(instr->context()).is(esi));
  __ cmp(eax, isolate()->factory()->undefined_value());
  DeoptimizeIf(equal, instr, "undefined");

  __ cmp(eax, isolate()->factory()->null_value());
  DeoptimizeIf(equal, instr, "null");

  __ test(eax, Immediate(kSmiTagMask));
  DeoptimizeIf(zero, instr, "Smi");

  STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
  __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx);
  DeoptimizeIf(below_equal, instr, "wrong instance type");

  Label use_cache, call_runtime;
  __ CheckEnumCache(&call_runtime);

  __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
  __ jmp(&use_cache, Label::kNear);

  // Get the set of properties to enumerate.
  __ bind(&call_runtime);
  __ push(eax);
  CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);

  __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
         isolate()->factory()->meta_map());
  DeoptimizeIf(not_equal, instr, "wrong map");
  __ bind(&use_cache);
}


void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
  Register map = ToRegister(instr->map());
  Register result = ToRegister(instr->result());
  Label load_cache, done;
  __ EnumLength(result, map);
  __ cmp(result, Immediate(Smi::FromInt(0)));
  __ j(not_equal, &load_cache, Label::kNear);
  __ mov(result, isolate()->factory()->empty_fixed_array());
  __ jmp(&done, Label::kNear);

  __ bind(&load_cache);
  __ LoadInstanceDescriptors(map, result);
  __ mov(result,
         FieldOperand(result, DescriptorArray::kEnumCacheOffset));
  __ mov(result,
         FieldOperand(result, FixedArray::SizeFor(instr->idx())));
  __ bind(&done);
  __ test(result, result);
  DeoptimizeIf(equal, instr, "no cache");
}


void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
  Register object = ToRegister(instr->value());
  __ cmp(ToRegister(instr->map()),
         FieldOperand(object, HeapObject::kMapOffset));
  DeoptimizeIf(not_equal, instr, "wrong map");
}


void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
                                           Register object,
                                           Register index) {
  PushSafepointRegistersScope scope(this);
  __ push(object);
  __ push(index);
  __ xor_(esi, esi);
  __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble);
  RecordSafepointWithRegisters(
      instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
  __ StoreToSafepointRegisterSlot(object, eax);
}


void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
  class DeferredLoadMutableDouble FINAL : public LDeferredCode {
   public:
    DeferredLoadMutableDouble(LCodeGen* codegen,
                              LLoadFieldByIndex* instr,
                              Register object,
                              Register index,
                              const X87Stack& x87_stack)
        : LDeferredCode(codegen, x87_stack),
          instr_(instr),
          object_(object),
          index_(index) {
    }
    void Generate() OVERRIDE {
      codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
    }
    LInstruction* instr() OVERRIDE { return instr_; }

   private:
    LLoadFieldByIndex* instr_;
    Register object_;
    Register index_;
  };

  Register object = ToRegister(instr->object());
  Register index = ToRegister(instr->index());

  DeferredLoadMutableDouble* deferred;
  deferred = new(zone()) DeferredLoadMutableDouble(
      this, instr, object, index, x87_stack_);

  Label out_of_object, done;
  __ test(index, Immediate(Smi::FromInt(1)));
  __ j(not_zero, deferred->entry());

  __ sar(index, 1);

  __ cmp(index, Immediate(0));
  __ j(less, &out_of_object, Label::kNear);
  __ mov(object, FieldOperand(object,
                              index,
                              times_half_pointer_size,
                              JSObject::kHeaderSize));
  __ jmp(&done, Label::kNear);

  __ bind(&out_of_object);
  __ mov(object, FieldOperand(object, JSObject::kPropertiesOffset));
  __ neg(index);
  // Index is now equal to out of object property index plus 1.
  __ mov(object, FieldOperand(object,
                              index,
                              times_half_pointer_size,
                              FixedArray::kHeaderSize - kPointerSize));
  __ bind(deferred->exit());
  __ bind(&done);
}


void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
  Register context = ToRegister(instr->context());
  __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), context);
}


void LCodeGen::DoAllocateBlockContext(LAllocateBlockContext* instr) {
  Handle<ScopeInfo> scope_info = instr->scope_info();
  __ Push(scope_info);
  __ push(ToRegister(instr->function()));
  CallRuntime(Runtime::kPushBlockContext, 2, instr);
  RecordSafepoint(Safepoint::kNoLazyDeopt);
}


#undef __

} }  // namespace v8::internal

#endif  // V8_TARGET_ARCH_X87
