Home | History | Annotate | Download | only in ia32
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/compiler/code-generator.h"
      6 
      7 #include "src/ast/scopes.h"
      8 #include "src/compiler/code-generator-impl.h"
      9 #include "src/compiler/gap-resolver.h"
     10 #include "src/compiler/node-matchers.h"
     11 #include "src/compiler/osr.h"
     12 #include "src/ia32/assembler-ia32.h"
     13 #include "src/ia32/frames-ia32.h"
     14 #include "src/ia32/macro-assembler-ia32.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 namespace compiler {
     19 
     20 #define __ masm()->
     21 
     22 
     23 #define kScratchDoubleReg xmm0
     24 
     25 
     26 // Adds IA-32 specific methods for decoding operands.
     27 class IA32OperandConverter : public InstructionOperandConverter {
     28  public:
     29   IA32OperandConverter(CodeGenerator* gen, Instruction* instr)
     30       : InstructionOperandConverter(gen, instr) {}
     31 
     32   Operand InputOperand(size_t index, int extra = 0) {
     33     return ToOperand(instr_->InputAt(index), extra);
     34   }
     35 
     36   Immediate InputImmediate(size_t index) {
     37     return ToImmediate(instr_->InputAt(index));
     38   }
     39 
     40   Operand OutputOperand() { return ToOperand(instr_->Output()); }
     41 
     42   Operand ToOperand(InstructionOperand* op, int extra = 0) {
     43     if (op->IsRegister()) {
     44       DCHECK(extra == 0);
     45       return Operand(ToRegister(op));
     46     } else if (op->IsDoubleRegister()) {
     47       DCHECK(extra == 0);
     48       return Operand(ToDoubleRegister(op));
     49     }
     50     DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
     51     FrameOffset offset = frame_access_state()->GetFrameOffset(
     52         AllocatedOperand::cast(op)->index());
     53     return Operand(offset.from_stack_pointer() ? esp : ebp,
     54                    offset.offset() + extra);
     55   }
     56 
     57   Operand ToMaterializableOperand(int materializable_offset) {
     58     FrameOffset offset = frame_access_state()->GetFrameOffset(
     59         Frame::FPOffsetToSlot(materializable_offset));
     60     return Operand(offset.from_stack_pointer() ? esp : ebp, offset.offset());
     61   }
     62 
     63   Operand HighOperand(InstructionOperand* op) {
     64     DCHECK(op->IsDoubleStackSlot());
     65     return ToOperand(op, kPointerSize);
     66   }
     67 
     68   Immediate ToImmediate(InstructionOperand* operand) {
     69     Constant constant = ToConstant(operand);
     70     switch (constant.type()) {
     71       case Constant::kInt32:
     72         return Immediate(constant.ToInt32());
     73       case Constant::kFloat32:
     74         return Immediate(
     75             isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED));
     76       case Constant::kFloat64:
     77         return Immediate(
     78             isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED));
     79       case Constant::kExternalReference:
     80         return Immediate(constant.ToExternalReference());
     81       case Constant::kHeapObject:
     82         return Immediate(constant.ToHeapObject());
     83       case Constant::kInt64:
     84         break;
     85       case Constant::kRpoNumber:
     86         return Immediate::CodeRelativeOffset(ToLabel(operand));
     87     }
     88     UNREACHABLE();
     89     return Immediate(-1);
     90   }
     91 
     92   static size_t NextOffset(size_t* offset) {
     93     size_t i = *offset;
     94     (*offset)++;
     95     return i;
     96   }
     97 
     98   static ScaleFactor ScaleFor(AddressingMode one, AddressingMode mode) {
     99     STATIC_ASSERT(0 == static_cast<int>(times_1));
    100     STATIC_ASSERT(1 == static_cast<int>(times_2));
    101     STATIC_ASSERT(2 == static_cast<int>(times_4));
    102     STATIC_ASSERT(3 == static_cast<int>(times_8));
    103     int scale = static_cast<int>(mode - one);
    104     DCHECK(scale >= 0 && scale < 4);
    105     return static_cast<ScaleFactor>(scale);
    106   }
    107 
    108   Operand MemoryOperand(size_t* offset) {
    109     AddressingMode mode = AddressingModeField::decode(instr_->opcode());
    110     switch (mode) {
    111       case kMode_MR: {
    112         Register base = InputRegister(NextOffset(offset));
    113         int32_t disp = 0;
    114         return Operand(base, disp);
    115       }
    116       case kMode_MRI: {
    117         Register base = InputRegister(NextOffset(offset));
    118         int32_t disp = InputInt32(NextOffset(offset));
    119         return Operand(base, disp);
    120       }
    121       case kMode_MR1:
    122       case kMode_MR2:
    123       case kMode_MR4:
    124       case kMode_MR8: {
    125         Register base = InputRegister(NextOffset(offset));
    126         Register index = InputRegister(NextOffset(offset));
    127         ScaleFactor scale = ScaleFor(kMode_MR1, mode);
    128         int32_t disp = 0;
    129         return Operand(base, index, scale, disp);
    130       }
    131       case kMode_MR1I:
    132       case kMode_MR2I:
    133       case kMode_MR4I:
    134       case kMode_MR8I: {
    135         Register base = InputRegister(NextOffset(offset));
    136         Register index = InputRegister(NextOffset(offset));
    137         ScaleFactor scale = ScaleFor(kMode_MR1I, mode);
    138         int32_t disp = InputInt32(NextOffset(offset));
    139         return Operand(base, index, scale, disp);
    140       }
    141       case kMode_M1:
    142       case kMode_M2:
    143       case kMode_M4:
    144       case kMode_M8: {
    145         Register index = InputRegister(NextOffset(offset));
    146         ScaleFactor scale = ScaleFor(kMode_M1, mode);
    147         int32_t disp = 0;
    148         return Operand(index, scale, disp);
    149       }
    150       case kMode_M1I:
    151       case kMode_M2I:
    152       case kMode_M4I:
    153       case kMode_M8I: {
    154         Register index = InputRegister(NextOffset(offset));
    155         ScaleFactor scale = ScaleFor(kMode_M1I, mode);
    156         int32_t disp = InputInt32(NextOffset(offset));
    157         return Operand(index, scale, disp);
    158       }
    159       case kMode_MI: {
    160         int32_t disp = InputInt32(NextOffset(offset));
    161         return Operand(Immediate(disp));
    162       }
    163       case kMode_None:
    164         UNREACHABLE();
    165         return Operand(no_reg, 0);
    166     }
    167     UNREACHABLE();
    168     return Operand(no_reg, 0);
    169   }
    170 
    171   Operand MemoryOperand(size_t first_input = 0) {
    172     return MemoryOperand(&first_input);
    173   }
    174 };
    175 
    176 
    177 namespace {
    178 
    179 bool HasImmediateInput(Instruction* instr, size_t index) {
    180   return instr->InputAt(index)->IsImmediate();
    181 }
    182 
    183 
    184 class OutOfLineLoadInteger final : public OutOfLineCode {
    185  public:
    186   OutOfLineLoadInteger(CodeGenerator* gen, Register result)
    187       : OutOfLineCode(gen), result_(result) {}
    188 
    189   void Generate() final { __ xor_(result_, result_); }
    190 
    191  private:
    192   Register const result_;
    193 };
    194 
    195 
    196 class OutOfLineLoadFloat final : public OutOfLineCode {
    197  public:
    198   OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result)
    199       : OutOfLineCode(gen), result_(result) {}
    200 
    201   void Generate() final { __ pcmpeqd(result_, result_); }
    202 
    203  private:
    204   XMMRegister const result_;
    205 };
    206 
    207 
    208 class OutOfLineTruncateDoubleToI final : public OutOfLineCode {
    209  public:
    210   OutOfLineTruncateDoubleToI(CodeGenerator* gen, Register result,
    211                              XMMRegister input)
    212       : OutOfLineCode(gen), result_(result), input_(input) {}
    213 
    214   void Generate() final {
    215     __ sub(esp, Immediate(kDoubleSize));
    216     __ movsd(MemOperand(esp, 0), input_);
    217     __ SlowTruncateToI(result_, esp, 0);
    218     __ add(esp, Immediate(kDoubleSize));
    219   }
    220 
    221  private:
    222   Register const result_;
    223   XMMRegister const input_;
    224 };
    225 
    226 
    227 class OutOfLineRecordWrite final : public OutOfLineCode {
    228  public:
    229   OutOfLineRecordWrite(CodeGenerator* gen, Register object, Operand operand,
    230                        Register value, Register scratch0, Register scratch1,
    231                        RecordWriteMode mode)
    232       : OutOfLineCode(gen),
    233         object_(object),
    234         operand_(operand),
    235         value_(value),
    236         scratch0_(scratch0),
    237         scratch1_(scratch1),
    238         mode_(mode) {}
    239 
    240   void Generate() final {
    241     if (mode_ > RecordWriteMode::kValueIsPointer) {
    242       __ JumpIfSmi(value_, exit());
    243     }
    244     if (mode_ > RecordWriteMode::kValueIsMap) {
    245       __ CheckPageFlag(value_, scratch0_,
    246                        MemoryChunk::kPointersToHereAreInterestingMask, zero,
    247                        exit());
    248     }
    249     SaveFPRegsMode const save_fp_mode =
    250         frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
    251     RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
    252                          EMIT_REMEMBERED_SET, save_fp_mode);
    253     __ lea(scratch1_, operand_);
    254     __ CallStub(&stub);
    255   }
    256 
    257  private:
    258   Register const object_;
    259   Operand const operand_;
    260   Register const value_;
    261   Register const scratch0_;
    262   Register const scratch1_;
    263   RecordWriteMode const mode_;
    264 };
    265 
    266 }  // namespace
    267 
    268 
    269 #define ASSEMBLE_CHECKED_LOAD_FLOAT(asm_instr)                          \
    270   do {                                                                  \
    271     auto result = i.OutputDoubleRegister();                             \
    272     auto offset = i.InputRegister(0);                                   \
    273     if (instr->InputAt(1)->IsRegister()) {                              \
    274       __ cmp(offset, i.InputRegister(1));                               \
    275     } else {                                                            \
    276       __ cmp(offset, i.InputImmediate(1));                              \
    277     }                                                                   \
    278     OutOfLineCode* ool = new (zone()) OutOfLineLoadFloat(this, result); \
    279     __ j(above_equal, ool->entry());                                    \
    280     __ asm_instr(result, i.MemoryOperand(2));                           \
    281     __ bind(ool->exit());                                               \
    282   } while (false)
    283 
    284 
    285 #define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr)                          \
    286   do {                                                                    \
    287     auto result = i.OutputRegister();                                     \
    288     auto offset = i.InputRegister(0);                                     \
    289     if (instr->InputAt(1)->IsRegister()) {                                \
    290       __ cmp(offset, i.InputRegister(1));                                 \
    291     } else {                                                              \
    292       __ cmp(offset, i.InputImmediate(1));                                \
    293     }                                                                     \
    294     OutOfLineCode* ool = new (zone()) OutOfLineLoadInteger(this, result); \
    295     __ j(above_equal, ool->entry());                                      \
    296     __ asm_instr(result, i.MemoryOperand(2));                             \
    297     __ bind(ool->exit());                                                 \
    298   } while (false)
    299 
    300 
    301 #define ASSEMBLE_CHECKED_STORE_FLOAT(asm_instr)                 \
    302   do {                                                          \
    303     auto offset = i.InputRegister(0);                           \
    304     if (instr->InputAt(1)->IsRegister()) {                      \
    305       __ cmp(offset, i.InputRegister(1));                       \
    306     } else {                                                    \
    307       __ cmp(offset, i.InputImmediate(1));                      \
    308     }                                                           \
    309     Label done;                                                 \
    310     __ j(above_equal, &done, Label::kNear);                     \
    311     __ asm_instr(i.MemoryOperand(3), i.InputDoubleRegister(2)); \
    312     __ bind(&done);                                             \
    313   } while (false)
    314 
    315 
    316 #define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr)            \
    317   do {                                                       \
    318     auto offset = i.InputRegister(0);                        \
    319     if (instr->InputAt(1)->IsRegister()) {                   \
    320       __ cmp(offset, i.InputRegister(1));                    \
    321     } else {                                                 \
    322       __ cmp(offset, i.InputImmediate(1));                   \
    323     }                                                        \
    324     Label done;                                              \
    325     __ j(above_equal, &done, Label::kNear);                  \
    326     if (instr->InputAt(2)->IsRegister()) {                   \
    327       __ asm_instr(i.MemoryOperand(3), i.InputRegister(2));  \
    328     } else {                                                 \
    329       __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \
    330     }                                                        \
    331     __ bind(&done);                                          \
    332   } while (false)
    333 
    334 
    335 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
    336   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
    337   if (sp_slot_delta > 0) {
    338     __ add(esp, Immediate(sp_slot_delta * kPointerSize));
    339   }
    340   frame_access_state()->SetFrameAccessToDefault();
    341 }
    342 
    343 
    344 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
    345   int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
    346   if (sp_slot_delta < 0) {
    347     __ sub(esp, Immediate(-sp_slot_delta * kPointerSize));
    348     frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
    349   }
    350   if (frame()->needs_frame()) {
    351     __ mov(ebp, MemOperand(ebp, 0));
    352   }
    353   frame_access_state()->SetFrameAccessToSP();
    354 }
    355 
    356 
    357 // Assembles an instruction after register allocation, producing machine code.
    358 void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
    359   IA32OperandConverter i(this, instr);
    360 
    361   switch (ArchOpcodeField::decode(instr->opcode())) {
    362     case kArchCallCodeObject: {
    363       EnsureSpaceForLazyDeopt();
    364       if (HasImmediateInput(instr, 0)) {
    365         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
    366         __ call(code, RelocInfo::CODE_TARGET);
    367       } else {
    368         Register reg = i.InputRegister(0);
    369         __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
    370         __ call(reg);
    371       }
    372       RecordCallPosition(instr);
    373       frame_access_state()->ClearSPDelta();
    374       break;
    375     }
    376     case kArchTailCallCodeObject: {
    377       int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
    378       AssembleDeconstructActivationRecord(stack_param_delta);
    379       if (HasImmediateInput(instr, 0)) {
    380         Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
    381         __ jmp(code, RelocInfo::CODE_TARGET);
    382       } else {
    383         Register reg = i.InputRegister(0);
    384         __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
    385         __ jmp(reg);
    386       }
    387       frame_access_state()->ClearSPDelta();
    388       break;
    389     }
    390     case kArchCallJSFunction: {
    391       EnsureSpaceForLazyDeopt();
    392       Register func = i.InputRegister(0);
    393       if (FLAG_debug_code) {
    394         // Check the function's context matches the context argument.
    395         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
    396         __ Assert(equal, kWrongFunctionContext);
    397       }
    398       __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
    399       RecordCallPosition(instr);
    400       frame_access_state()->ClearSPDelta();
    401       break;
    402     }
    403     case kArchTailCallJSFunction: {
    404       Register func = i.InputRegister(0);
    405       if (FLAG_debug_code) {
    406         // Check the function's context matches the context argument.
    407         __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
    408         __ Assert(equal, kWrongFunctionContext);
    409       }
    410       int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
    411       AssembleDeconstructActivationRecord(stack_param_delta);
    412       __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
    413       frame_access_state()->ClearSPDelta();
    414       break;
    415     }
    416     case kArchLazyBailout: {
    417       EnsureSpaceForLazyDeopt();
    418       RecordCallPosition(instr);
    419       break;
    420     }
    421     case kArchPrepareCallCFunction: {
    422       // Frame alignment requires using FP-relative frame addressing.
    423       frame_access_state()->SetFrameAccessToFP();
    424       int const num_parameters = MiscField::decode(instr->opcode());
    425       __ PrepareCallCFunction(num_parameters, i.TempRegister(0));
    426       break;
    427     }
    428     case kArchPrepareTailCall:
    429       AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1));
    430       break;
    431     case kArchCallCFunction: {
    432       int const num_parameters = MiscField::decode(instr->opcode());
    433       if (HasImmediateInput(instr, 0)) {
    434         ExternalReference ref = i.InputExternalReference(0);
    435         __ CallCFunction(ref, num_parameters);
    436       } else {
    437         Register func = i.InputRegister(0);
    438         __ CallCFunction(func, num_parameters);
    439       }
    440       frame_access_state()->SetFrameAccessToDefault();
    441       frame_access_state()->ClearSPDelta();
    442       break;
    443     }
    444     case kArchJmp:
    445       AssembleArchJump(i.InputRpo(0));
    446       break;
    447     case kArchLookupSwitch:
    448       AssembleArchLookupSwitch(instr);
    449       break;
    450     case kArchTableSwitch:
    451       AssembleArchTableSwitch(instr);
    452       break;
    453     case kArchNop:
    454     case kArchThrowTerminator:
    455       // don't emit code for nops.
    456       break;
    457     case kArchDeoptimize: {
    458       int deopt_state_id =
    459           BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
    460       Deoptimizer::BailoutType bailout_type =
    461           Deoptimizer::BailoutType(MiscField::decode(instr->opcode()));
    462       AssembleDeoptimizerCall(deopt_state_id, bailout_type);
    463       break;
    464     }
    465     case kArchRet:
    466       AssembleReturn();
    467       break;
    468     case kArchStackPointer:
    469       __ mov(i.OutputRegister(), esp);
    470       break;
    471     case kArchFramePointer:
    472       __ mov(i.OutputRegister(), ebp);
    473       break;
    474     case kArchTruncateDoubleToI: {
    475       auto result = i.OutputRegister();
    476       auto input = i.InputDoubleRegister(0);
    477       auto ool = new (zone()) OutOfLineTruncateDoubleToI(this, result, input);
    478       __ cvttsd2si(result, Operand(input));
    479       __ cmp(result, 1);
    480       __ j(overflow, ool->entry());
    481       __ bind(ool->exit());
    482       break;
    483     }
    484     case kArchStoreWithWriteBarrier: {
    485       RecordWriteMode mode =
    486           static_cast<RecordWriteMode>(MiscField::decode(instr->opcode()));
    487       Register object = i.InputRegister(0);
    488       size_t index = 0;
    489       Operand operand = i.MemoryOperand(&index);
    490       Register value = i.InputRegister(index);
    491       Register scratch0 = i.TempRegister(0);
    492       Register scratch1 = i.TempRegister(1);
    493       auto ool = new (zone()) OutOfLineRecordWrite(this, object, operand, value,
    494                                                    scratch0, scratch1, mode);
    495       __ mov(operand, value);
    496       __ CheckPageFlag(object, scratch0,
    497                        MemoryChunk::kPointersFromHereAreInterestingMask,
    498                        not_zero, ool->entry());
    499       __ bind(ool->exit());
    500       break;
    501     }
    502     case kIA32Add:
    503       if (HasImmediateInput(instr, 1)) {
    504         __ add(i.InputOperand(0), i.InputImmediate(1));
    505       } else {
    506         __ add(i.InputRegister(0), i.InputOperand(1));
    507       }
    508       break;
    509     case kIA32And:
    510       if (HasImmediateInput(instr, 1)) {
    511         __ and_(i.InputOperand(0), i.InputImmediate(1));
    512       } else {
    513         __ and_(i.InputRegister(0), i.InputOperand(1));
    514       }
    515       break;
    516     case kIA32Cmp:
    517       if (HasImmediateInput(instr, 1)) {
    518         __ cmp(i.InputOperand(0), i.InputImmediate(1));
    519       } else {
    520         __ cmp(i.InputRegister(0), i.InputOperand(1));
    521       }
    522       break;
    523     case kIA32Test:
    524       if (HasImmediateInput(instr, 1)) {
    525         __ test(i.InputOperand(0), i.InputImmediate(1));
    526       } else {
    527         __ test(i.InputRegister(0), i.InputOperand(1));
    528       }
    529       break;
    530     case kIA32Imul:
    531       if (HasImmediateInput(instr, 1)) {
    532         __ imul(i.OutputRegister(), i.InputOperand(0), i.InputInt32(1));
    533       } else {
    534         __ imul(i.OutputRegister(), i.InputOperand(1));
    535       }
    536       break;
    537     case kIA32ImulHigh:
    538       __ imul(i.InputRegister(1));
    539       break;
    540     case kIA32UmulHigh:
    541       __ mul(i.InputRegister(1));
    542       break;
    543     case kIA32Idiv:
    544       __ cdq();
    545       __ idiv(i.InputOperand(1));
    546       break;
    547     case kIA32Udiv:
    548       __ Move(edx, Immediate(0));
    549       __ div(i.InputOperand(1));
    550       break;
    551     case kIA32Not:
    552       __ not_(i.OutputOperand());
    553       break;
    554     case kIA32Neg:
    555       __ neg(i.OutputOperand());
    556       break;
    557     case kIA32Or:
    558       if (HasImmediateInput(instr, 1)) {
    559         __ or_(i.InputOperand(0), i.InputImmediate(1));
    560       } else {
    561         __ or_(i.InputRegister(0), i.InputOperand(1));
    562       }
    563       break;
    564     case kIA32Xor:
    565       if (HasImmediateInput(instr, 1)) {
    566         __ xor_(i.InputOperand(0), i.InputImmediate(1));
    567       } else {
    568         __ xor_(i.InputRegister(0), i.InputOperand(1));
    569       }
    570       break;
    571     case kIA32Sub:
    572       if (HasImmediateInput(instr, 1)) {
    573         __ sub(i.InputOperand(0), i.InputImmediate(1));
    574       } else {
    575         __ sub(i.InputRegister(0), i.InputOperand(1));
    576       }
    577       break;
    578     case kIA32Shl:
    579       if (HasImmediateInput(instr, 1)) {
    580         __ shl(i.OutputOperand(), i.InputInt5(1));
    581       } else {
    582         __ shl_cl(i.OutputOperand());
    583       }
    584       break;
    585     case kIA32Shr:
    586       if (HasImmediateInput(instr, 1)) {
    587         __ shr(i.OutputOperand(), i.InputInt5(1));
    588       } else {
    589         __ shr_cl(i.OutputOperand());
    590       }
    591       break;
    592     case kIA32Sar:
    593       if (HasImmediateInput(instr, 1)) {
    594         __ sar(i.OutputOperand(), i.InputInt5(1));
    595       } else {
    596         __ sar_cl(i.OutputOperand());
    597       }
    598       break;
    599     case kIA32Ror:
    600       if (HasImmediateInput(instr, 1)) {
    601         __ ror(i.OutputOperand(), i.InputInt5(1));
    602       } else {
    603         __ ror_cl(i.OutputOperand());
    604       }
    605       break;
    606     case kIA32Lzcnt:
    607       __ Lzcnt(i.OutputRegister(), i.InputOperand(0));
    608       break;
    609     case kIA32Tzcnt:
    610       __ Tzcnt(i.OutputRegister(), i.InputOperand(0));
    611       break;
    612     case kIA32Popcnt:
    613       __ Popcnt(i.OutputRegister(), i.InputOperand(0));
    614       break;
    615     case kSSEFloat32Cmp:
    616       __ ucomiss(i.InputDoubleRegister(0), i.InputOperand(1));
    617       break;
    618     case kSSEFloat32Add:
    619       __ addss(i.InputDoubleRegister(0), i.InputOperand(1));
    620       break;
    621     case kSSEFloat32Sub:
    622       __ subss(i.InputDoubleRegister(0), i.InputOperand(1));
    623       break;
    624     case kSSEFloat32Mul:
    625       __ mulss(i.InputDoubleRegister(0), i.InputOperand(1));
    626       break;
    627     case kSSEFloat32Div:
    628       __ divss(i.InputDoubleRegister(0), i.InputOperand(1));
    629       // Don't delete this mov. It may improve performance on some CPUs,
    630       // when there is a (v)mulss depending on the result.
    631       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
    632       break;
    633     case kSSEFloat32Max:
    634       __ maxss(i.InputDoubleRegister(0), i.InputOperand(1));
    635       break;
    636     case kSSEFloat32Min:
    637       __ minss(i.InputDoubleRegister(0), i.InputOperand(1));
    638       break;
    639     case kSSEFloat32Sqrt:
    640       __ sqrtss(i.OutputDoubleRegister(), i.InputOperand(0));
    641       break;
    642     case kSSEFloat32Abs: {
    643       // TODO(bmeurer): Use 128-bit constants.
    644       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    645       __ psrlq(kScratchDoubleReg, 33);
    646       __ andps(i.OutputDoubleRegister(), kScratchDoubleReg);
    647       break;
    648     }
    649     case kSSEFloat32Neg: {
    650       // TODO(bmeurer): Use 128-bit constants.
    651       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    652       __ psllq(kScratchDoubleReg, 31);
    653       __ xorps(i.OutputDoubleRegister(), kScratchDoubleReg);
    654       break;
    655     }
    656     case kSSEFloat32Round: {
    657       CpuFeatureScope sse_scope(masm(), SSE4_1);
    658       RoundingMode const mode =
    659           static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
    660       __ roundss(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
    661       break;
    662     }
    663     case kSSEFloat64Cmp:
    664       __ ucomisd(i.InputDoubleRegister(0), i.InputOperand(1));
    665       break;
    666     case kSSEFloat64Add:
    667       __ addsd(i.InputDoubleRegister(0), i.InputOperand(1));
    668       break;
    669     case kSSEFloat64Sub:
    670       __ subsd(i.InputDoubleRegister(0), i.InputOperand(1));
    671       break;
    672     case kSSEFloat64Mul:
    673       __ mulsd(i.InputDoubleRegister(0), i.InputOperand(1));
    674       break;
    675     case kSSEFloat64Div:
    676       __ divsd(i.InputDoubleRegister(0), i.InputOperand(1));
    677       // Don't delete this mov. It may improve performance on some CPUs,
    678       // when there is a (v)mulsd depending on the result.
    679       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
    680       break;
    681     case kSSEFloat64Max:
    682       __ maxsd(i.InputDoubleRegister(0), i.InputOperand(1));
    683       break;
    684     case kSSEFloat64Min:
    685       __ minsd(i.InputDoubleRegister(0), i.InputOperand(1));
    686       break;
    687     case kSSEFloat64Mod: {
    688       // TODO(dcarney): alignment is wrong.
    689       __ sub(esp, Immediate(kDoubleSize));
    690       // Move values to st(0) and st(1).
    691       __ movsd(Operand(esp, 0), i.InputDoubleRegister(1));
    692       __ fld_d(Operand(esp, 0));
    693       __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
    694       __ fld_d(Operand(esp, 0));
    695       // Loop while fprem isn't done.
    696       Label mod_loop;
    697       __ bind(&mod_loop);
    698       // This instructions traps on all kinds inputs, but we are assuming the
    699       // floating point control word is set to ignore them all.
    700       __ fprem();
    701       // The following 2 instruction implicitly use eax.
    702       __ fnstsw_ax();
    703       __ sahf();
    704       __ j(parity_even, &mod_loop);
    705       // Move output to stack and clean up.
    706       __ fstp(1);
    707       __ fstp_d(Operand(esp, 0));
    708       __ movsd(i.OutputDoubleRegister(), Operand(esp, 0));
    709       __ add(esp, Immediate(kDoubleSize));
    710       break;
    711     }
    712     case kSSEFloat64Abs: {
    713       // TODO(bmeurer): Use 128-bit constants.
    714       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    715       __ psrlq(kScratchDoubleReg, 1);
    716       __ andpd(i.OutputDoubleRegister(), kScratchDoubleReg);
    717       break;
    718     }
    719     case kSSEFloat64Neg: {
    720       // TODO(bmeurer): Use 128-bit constants.
    721       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    722       __ psllq(kScratchDoubleReg, 63);
    723       __ xorpd(i.OutputDoubleRegister(), kScratchDoubleReg);
    724       break;
    725     }
    726     case kSSEFloat64Sqrt:
    727       __ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0));
    728       break;
    729     case kSSEFloat64Round: {
    730       CpuFeatureScope sse_scope(masm(), SSE4_1);
    731       RoundingMode const mode =
    732           static_cast<RoundingMode>(MiscField::decode(instr->opcode()));
    733       __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode);
    734       break;
    735     }
    736     case kSSEFloat32ToFloat64:
    737       __ cvtss2sd(i.OutputDoubleRegister(), i.InputOperand(0));
    738       break;
    739     case kSSEFloat64ToFloat32:
    740       __ cvtsd2ss(i.OutputDoubleRegister(), i.InputOperand(0));
    741       break;
    742     case kSSEFloat64ToInt32:
    743       __ cvttsd2si(i.OutputRegister(), i.InputOperand(0));
    744       break;
    745     case kSSEFloat64ToUint32: {
    746       __ Move(kScratchDoubleReg, -2147483648.0);
    747       __ addsd(kScratchDoubleReg, i.InputOperand(0));
    748       __ cvttsd2si(i.OutputRegister(), kScratchDoubleReg);
    749       __ add(i.OutputRegister(), Immediate(0x80000000));
    750       break;
    751     }
    752     case kSSEInt32ToFloat64:
    753       __ cvtsi2sd(i.OutputDoubleRegister(), i.InputOperand(0));
    754       break;
    755     case kSSEUint32ToFloat64:
    756       __ LoadUint32(i.OutputDoubleRegister(), i.InputOperand(0));
    757       break;
    758     case kSSEFloat64ExtractLowWord32:
    759       if (instr->InputAt(0)->IsDoubleStackSlot()) {
    760         __ mov(i.OutputRegister(), i.InputOperand(0));
    761       } else {
    762         __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
    763       }
    764       break;
    765     case kSSEFloat64ExtractHighWord32:
    766       if (instr->InputAt(0)->IsDoubleStackSlot()) {
    767         __ mov(i.OutputRegister(), i.InputOperand(0, kDoubleSize / 2));
    768       } else {
    769         __ Pextrd(i.OutputRegister(), i.InputDoubleRegister(0), 1);
    770       }
    771       break;
    772     case kSSEFloat64InsertLowWord32:
    773       __ Pinsrd(i.OutputDoubleRegister(), i.InputOperand(1), 0);
    774       break;
    775     case kSSEFloat64InsertHighWord32:
    776       __ Pinsrd(i.OutputDoubleRegister(), i.InputOperand(1), 1);
    777       break;
    778     case kSSEFloat64LoadLowWord32:
    779       __ movd(i.OutputDoubleRegister(), i.InputOperand(0));
    780       break;
    781     case kAVXFloat32Add: {
    782       CpuFeatureScope avx_scope(masm(), AVX);
    783       __ vaddss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    784                 i.InputOperand(1));
    785       break;
    786     }
    787     case kAVXFloat32Sub: {
    788       CpuFeatureScope avx_scope(masm(), AVX);
    789       __ vsubss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    790                 i.InputOperand(1));
    791       break;
    792     }
    793     case kAVXFloat32Mul: {
    794       CpuFeatureScope avx_scope(masm(), AVX);
    795       __ vmulss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    796                 i.InputOperand(1));
    797       break;
    798     }
    799     case kAVXFloat32Div: {
    800       CpuFeatureScope avx_scope(masm(), AVX);
    801       __ vdivss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    802                 i.InputOperand(1));
    803       // Don't delete this mov. It may improve performance on some CPUs,
    804       // when there is a (v)mulss depending on the result.
    805       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
    806       break;
    807     }
    808     case kAVXFloat32Max: {
    809       CpuFeatureScope avx_scope(masm(), AVX);
    810       __ vmaxss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    811                 i.InputOperand(1));
    812       break;
    813     }
    814     case kAVXFloat32Min: {
    815       CpuFeatureScope avx_scope(masm(), AVX);
    816       __ vminss(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    817                 i.InputOperand(1));
    818       break;
    819     }
    820     case kAVXFloat64Add: {
    821       CpuFeatureScope avx_scope(masm(), AVX);
    822       __ vaddsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    823                 i.InputOperand(1));
    824       break;
    825     }
    826     case kAVXFloat64Sub: {
    827       CpuFeatureScope avx_scope(masm(), AVX);
    828       __ vsubsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    829                 i.InputOperand(1));
    830       break;
    831     }
    832     case kAVXFloat64Mul: {
    833       CpuFeatureScope avx_scope(masm(), AVX);
    834       __ vmulsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    835                 i.InputOperand(1));
    836       break;
    837     }
    838     case kAVXFloat64Div: {
    839       CpuFeatureScope avx_scope(masm(), AVX);
    840       __ vdivsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    841                 i.InputOperand(1));
    842       // Don't delete this mov. It may improve performance on some CPUs,
    843       // when there is a (v)mulsd depending on the result.
    844       __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister());
    845       break;
    846     }
    847     case kAVXFloat64Max: {
    848       CpuFeatureScope avx_scope(masm(), AVX);
    849       __ vmaxsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    850                 i.InputOperand(1));
    851       break;
    852     }
    853     case kAVXFloat64Min: {
    854       CpuFeatureScope avx_scope(masm(), AVX);
    855       __ vminsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0),
    856                 i.InputOperand(1));
    857       break;
    858     }
    859     case kAVXFloat32Abs: {
    860       // TODO(bmeurer): Use RIP relative 128-bit constants.
    861       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    862       __ psrlq(kScratchDoubleReg, 33);
    863       CpuFeatureScope avx_scope(masm(), AVX);
    864       __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
    865       break;
    866     }
    867     case kAVXFloat32Neg: {
    868       // TODO(bmeurer): Use RIP relative 128-bit constants.
    869       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    870       __ psllq(kScratchDoubleReg, 31);
    871       CpuFeatureScope avx_scope(masm(), AVX);
    872       __ vxorps(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
    873       break;
    874     }
    875     case kAVXFloat64Abs: {
    876       // TODO(bmeurer): Use RIP relative 128-bit constants.
    877       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    878       __ psrlq(kScratchDoubleReg, 1);
    879       CpuFeatureScope avx_scope(masm(), AVX);
    880       __ vandpd(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
    881       break;
    882     }
    883     case kAVXFloat64Neg: {
    884       // TODO(bmeurer): Use RIP relative 128-bit constants.
    885       __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg);
    886       __ psllq(kScratchDoubleReg, 63);
    887       CpuFeatureScope avx_scope(masm(), AVX);
    888       __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg, i.InputOperand(0));
    889       break;
    890     }
    891     case kIA32Movsxbl:
    892       __ movsx_b(i.OutputRegister(), i.MemoryOperand());
    893       break;
    894     case kIA32Movzxbl:
    895       __ movzx_b(i.OutputRegister(), i.MemoryOperand());
    896       break;
    897     case kIA32Movb: {
    898       size_t index = 0;
    899       Operand operand = i.MemoryOperand(&index);
    900       if (HasImmediateInput(instr, index)) {
    901         __ mov_b(operand, i.InputInt8(index));
    902       } else {
    903         __ mov_b(operand, i.InputRegister(index));
    904       }
    905       break;
    906     }
    907     case kIA32Movsxwl:
    908       __ movsx_w(i.OutputRegister(), i.MemoryOperand());
    909       break;
    910     case kIA32Movzxwl:
    911       __ movzx_w(i.OutputRegister(), i.MemoryOperand());
    912       break;
    913     case kIA32Movw: {
    914       size_t index = 0;
    915       Operand operand = i.MemoryOperand(&index);
    916       if (HasImmediateInput(instr, index)) {
    917         __ mov_w(operand, i.InputInt16(index));
    918       } else {
    919         __ mov_w(operand, i.InputRegister(index));
    920       }
    921       break;
    922     }
    923     case kIA32Movl:
    924       if (instr->HasOutput()) {
    925         __ mov(i.OutputRegister(), i.MemoryOperand());
    926       } else {
    927         size_t index = 0;
    928         Operand operand = i.MemoryOperand(&index);
    929         if (HasImmediateInput(instr, index)) {
    930           __ mov(operand, i.InputImmediate(index));
    931         } else {
    932           __ mov(operand, i.InputRegister(index));
    933         }
    934       }
    935       break;
    936     case kIA32Movsd:
    937       if (instr->HasOutput()) {
    938         __ movsd(i.OutputDoubleRegister(), i.MemoryOperand());
    939       } else {
    940         size_t index = 0;
    941         Operand operand = i.MemoryOperand(&index);
    942         __ movsd(operand, i.InputDoubleRegister(index));
    943       }
    944       break;
    945     case kIA32Movss:
    946       if (instr->HasOutput()) {
    947         __ movss(i.OutputDoubleRegister(), i.MemoryOperand());
    948       } else {
    949         size_t index = 0;
    950         Operand operand = i.MemoryOperand(&index);
    951         __ movss(operand, i.InputDoubleRegister(index));
    952       }
    953       break;
    954     case kIA32BitcastFI:
    955       if (instr->InputAt(0)->IsDoubleStackSlot()) {
    956         __ mov(i.OutputRegister(), i.InputOperand(0));
    957       } else {
    958         __ movd(i.OutputRegister(), i.InputDoubleRegister(0));
    959       }
    960       break;
    961     case kIA32BitcastIF:
    962       if (instr->InputAt(0)->IsRegister()) {
    963         __ movd(i.OutputDoubleRegister(), i.InputRegister(0));
    964       } else {
    965         __ movss(i.OutputDoubleRegister(), i.InputOperand(0));
    966       }
    967       break;
    968     case kIA32Lea: {
    969       AddressingMode mode = AddressingModeField::decode(instr->opcode());
    970       // Shorten "leal" to "addl", "subl" or "shll" if the register allocation
    971       // and addressing mode just happens to work out. The "addl"/"subl" forms
    972       // in these cases are faster based on measurements.
    973       if (mode == kMode_MI) {
    974         __ Move(i.OutputRegister(), Immediate(i.InputInt32(0)));
    975       } else if (i.InputRegister(0).is(i.OutputRegister())) {
    976         if (mode == kMode_MRI) {
    977           int32_t constant_summand = i.InputInt32(1);
    978           if (constant_summand > 0) {
    979             __ add(i.OutputRegister(), Immediate(constant_summand));
    980           } else if (constant_summand < 0) {
    981             __ sub(i.OutputRegister(), Immediate(-constant_summand));
    982           }
    983         } else if (mode == kMode_MR1) {
    984           if (i.InputRegister(1).is(i.OutputRegister())) {
    985             __ shl(i.OutputRegister(), 1);
    986           } else {
    987             __ lea(i.OutputRegister(), i.MemoryOperand());
    988           }
    989         } else if (mode == kMode_M2) {
    990           __ shl(i.OutputRegister(), 1);
    991         } else if (mode == kMode_M4) {
    992           __ shl(i.OutputRegister(), 2);
    993         } else if (mode == kMode_M8) {
    994           __ shl(i.OutputRegister(), 3);
    995         } else {
    996           __ lea(i.OutputRegister(), i.MemoryOperand());
    997         }
    998       } else {
    999         __ lea(i.OutputRegister(), i.MemoryOperand());
   1000       }
   1001       break;
   1002     }
   1003     case kIA32PushFloat32:
   1004       if (instr->InputAt(0)->IsDoubleRegister()) {
   1005         __ sub(esp, Immediate(kDoubleSize));
   1006         __ movss(Operand(esp, 0), i.InputDoubleRegister(0));
   1007         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1008       } else if (HasImmediateInput(instr, 0)) {
   1009         __ Move(kScratchDoubleReg, i.InputDouble(0));
   1010         __ sub(esp, Immediate(kDoubleSize));
   1011         __ movss(Operand(esp, 0), kScratchDoubleReg);
   1012         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1013       } else {
   1014         __ movsd(kScratchDoubleReg, i.InputOperand(0));
   1015         __ sub(esp, Immediate(kDoubleSize));
   1016         __ movss(Operand(esp, 0), kScratchDoubleReg);
   1017         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1018       }
   1019       break;
   1020     case kIA32PushFloat64:
   1021       if (instr->InputAt(0)->IsDoubleRegister()) {
   1022         __ sub(esp, Immediate(kDoubleSize));
   1023         __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
   1024         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1025       } else if (HasImmediateInput(instr, 0)) {
   1026         __ Move(kScratchDoubleReg, i.InputDouble(0));
   1027         __ sub(esp, Immediate(kDoubleSize));
   1028         __ movsd(Operand(esp, 0), kScratchDoubleReg);
   1029         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1030       } else {
   1031         __ movsd(kScratchDoubleReg, i.InputOperand(0));
   1032         __ sub(esp, Immediate(kDoubleSize));
   1033         __ movsd(Operand(esp, 0), kScratchDoubleReg);
   1034         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1035       }
   1036       break;
   1037     case kIA32Push:
   1038       if (instr->InputAt(0)->IsDoubleRegister()) {
   1039         __ sub(esp, Immediate(kDoubleSize));
   1040         __ movsd(Operand(esp, 0), i.InputDoubleRegister(0));
   1041         frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
   1042       } else if (HasImmediateInput(instr, 0)) {
   1043         __ push(i.InputImmediate(0));
   1044         frame_access_state()->IncreaseSPDelta(1);
   1045       } else {
   1046         __ push(i.InputOperand(0));
   1047         frame_access_state()->IncreaseSPDelta(1);
   1048       }
   1049       break;
   1050     case kIA32Poke: {
   1051       int const slot = MiscField::decode(instr->opcode());
   1052       if (HasImmediateInput(instr, 0)) {
   1053         __ mov(Operand(esp, slot * kPointerSize), i.InputImmediate(0));
   1054       } else {
   1055         __ mov(Operand(esp, slot * kPointerSize), i.InputRegister(0));
   1056       }
   1057       break;
   1058     }
   1059     case kCheckedLoadInt8:
   1060       ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_b);
   1061       break;
   1062     case kCheckedLoadUint8:
   1063       ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_b);
   1064       break;
   1065     case kCheckedLoadInt16:
   1066       ASSEMBLE_CHECKED_LOAD_INTEGER(movsx_w);
   1067       break;
   1068     case kCheckedLoadUint16:
   1069       ASSEMBLE_CHECKED_LOAD_INTEGER(movzx_w);
   1070       break;
   1071     case kCheckedLoadWord32:
   1072       ASSEMBLE_CHECKED_LOAD_INTEGER(mov);
   1073       break;
   1074     case kCheckedLoadFloat32:
   1075       ASSEMBLE_CHECKED_LOAD_FLOAT(movss);
   1076       break;
   1077     case kCheckedLoadFloat64:
   1078       ASSEMBLE_CHECKED_LOAD_FLOAT(movsd);
   1079       break;
   1080     case kCheckedStoreWord8:
   1081       ASSEMBLE_CHECKED_STORE_INTEGER(mov_b);
   1082       break;
   1083     case kCheckedStoreWord16:
   1084       ASSEMBLE_CHECKED_STORE_INTEGER(mov_w);
   1085       break;
   1086     case kCheckedStoreWord32:
   1087       ASSEMBLE_CHECKED_STORE_INTEGER(mov);
   1088       break;
   1089     case kCheckedStoreFloat32:
   1090       ASSEMBLE_CHECKED_STORE_FLOAT(movss);
   1091       break;
   1092     case kCheckedStoreFloat64:
   1093       ASSEMBLE_CHECKED_STORE_FLOAT(movsd);
   1094       break;
   1095     case kIA32StackCheck: {
   1096       ExternalReference const stack_limit =
   1097           ExternalReference::address_of_stack_limit(isolate());
   1098       __ cmp(esp, Operand::StaticVariable(stack_limit));
   1099       break;
   1100     }
   1101     case kCheckedLoadWord64:
   1102     case kCheckedStoreWord64:
   1103       UNREACHABLE();  // currently unsupported checked int64 load/store.
   1104       break;
   1105   }
   1106 }  // NOLINT(readability/fn_size)
   1107 
   1108 
   1109 // Assembles a branch after an instruction.
   1110 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
   1111   IA32OperandConverter i(this, instr);
   1112   Label::Distance flabel_distance =
   1113       branch->fallthru ? Label::kNear : Label::kFar;
   1114   Label* tlabel = branch->true_label;
   1115   Label* flabel = branch->false_label;
   1116   switch (branch->condition) {
   1117     case kUnorderedEqual:
   1118       __ j(parity_even, flabel, flabel_distance);
   1119     // Fall through.
   1120     case kEqual:
   1121       __ j(equal, tlabel);
   1122       break;
   1123     case kUnorderedNotEqual:
   1124       __ j(parity_even, tlabel);
   1125     // Fall through.
   1126     case kNotEqual:
   1127       __ j(not_equal, tlabel);
   1128       break;
   1129     case kSignedLessThan:
   1130       __ j(less, tlabel);
   1131       break;
   1132     case kSignedGreaterThanOrEqual:
   1133       __ j(greater_equal, tlabel);
   1134       break;
   1135     case kSignedLessThanOrEqual:
   1136       __ j(less_equal, tlabel);
   1137       break;
   1138     case kSignedGreaterThan:
   1139       __ j(greater, tlabel);
   1140       break;
   1141     case kUnsignedLessThan:
   1142       __ j(below, tlabel);
   1143       break;
   1144     case kUnsignedGreaterThanOrEqual:
   1145       __ j(above_equal, tlabel);
   1146       break;
   1147     case kUnsignedLessThanOrEqual:
   1148       __ j(below_equal, tlabel);
   1149       break;
   1150     case kUnsignedGreaterThan:
   1151       __ j(above, tlabel);
   1152       break;
   1153     case kOverflow:
   1154       __ j(overflow, tlabel);
   1155       break;
   1156     case kNotOverflow:
   1157       __ j(no_overflow, tlabel);
   1158       break;
   1159     default:
   1160       UNREACHABLE();
   1161       break;
   1162   }
   1163   // Add a jump if not falling through to the next block.
   1164   if (!branch->fallthru) __ jmp(flabel);
   1165 }
   1166 
   1167 
   1168 void CodeGenerator::AssembleArchJump(RpoNumber target) {
   1169   if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target));
   1170 }
   1171 
   1172 
   1173 // Assembles boolean materializations after an instruction.
   1174 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
   1175                                         FlagsCondition condition) {
   1176   IA32OperandConverter i(this, instr);
   1177   Label done;
   1178 
   1179   // Materialize a full 32-bit 1 or 0 value. The result register is always the
   1180   // last output of the instruction.
   1181   Label check;
   1182   DCHECK_NE(0u, instr->OutputCount());
   1183   Register reg = i.OutputRegister(instr->OutputCount() - 1);
   1184   Condition cc = no_condition;
   1185   switch (condition) {
   1186     case kUnorderedEqual:
   1187       __ j(parity_odd, &check, Label::kNear);
   1188       __ Move(reg, Immediate(0));
   1189       __ jmp(&done, Label::kNear);
   1190     // Fall through.
   1191     case kEqual:
   1192       cc = equal;
   1193       break;
   1194     case kUnorderedNotEqual:
   1195       __ j(parity_odd, &check, Label::kNear);
   1196       __ mov(reg, Immediate(1));
   1197       __ jmp(&done, Label::kNear);
   1198     // Fall through.
   1199     case kNotEqual:
   1200       cc = not_equal;
   1201       break;
   1202     case kSignedLessThan:
   1203       cc = less;
   1204       break;
   1205     case kSignedGreaterThanOrEqual:
   1206       cc = greater_equal;
   1207       break;
   1208     case kSignedLessThanOrEqual:
   1209       cc = less_equal;
   1210       break;
   1211     case kSignedGreaterThan:
   1212       cc = greater;
   1213       break;
   1214     case kUnsignedLessThan:
   1215       cc = below;
   1216       break;
   1217     case kUnsignedGreaterThanOrEqual:
   1218       cc = above_equal;
   1219       break;
   1220     case kUnsignedLessThanOrEqual:
   1221       cc = below_equal;
   1222       break;
   1223     case kUnsignedGreaterThan:
   1224       cc = above;
   1225       break;
   1226     case kOverflow:
   1227       cc = overflow;
   1228       break;
   1229     case kNotOverflow:
   1230       cc = no_overflow;
   1231       break;
   1232     default:
   1233       UNREACHABLE();
   1234       break;
   1235   }
   1236   __ bind(&check);
   1237   if (reg.is_byte_register()) {
   1238     // setcc for byte registers (al, bl, cl, dl).
   1239     __ setcc(cc, reg);
   1240     __ movzx_b(reg, reg);
   1241   } else {
   1242     // Emit a branch to set a register to either 1 or 0.
   1243     Label set;
   1244     __ j(cc, &set, Label::kNear);
   1245     __ Move(reg, Immediate(0));
   1246     __ jmp(&done, Label::kNear);
   1247     __ bind(&set);
   1248     __ mov(reg, Immediate(1));
   1249   }
   1250   __ bind(&done);
   1251 }
   1252 
   1253 
   1254 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
   1255   IA32OperandConverter i(this, instr);
   1256   Register input = i.InputRegister(0);
   1257   for (size_t index = 2; index < instr->InputCount(); index += 2) {
   1258     __ cmp(input, Immediate(i.InputInt32(index + 0)));
   1259     __ j(equal, GetLabel(i.InputRpo(index + 1)));
   1260   }
   1261   AssembleArchJump(i.InputRpo(1));
   1262 }
   1263 
   1264 
   1265 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
   1266   IA32OperandConverter i(this, instr);
   1267   Register input = i.InputRegister(0);
   1268   size_t const case_count = instr->InputCount() - 2;
   1269   Label** cases = zone()->NewArray<Label*>(case_count);
   1270   for (size_t index = 0; index < case_count; ++index) {
   1271     cases[index] = GetLabel(i.InputRpo(index + 2));
   1272   }
   1273   Label* const table = AddJumpTable(cases, case_count);
   1274   __ cmp(input, Immediate(case_count));
   1275   __ j(above_equal, GetLabel(i.InputRpo(1)));
   1276   __ jmp(Operand::JumpTable(input, times_4, table));
   1277 }
   1278 
   1279 
   1280 void CodeGenerator::AssembleDeoptimizerCall(
   1281     int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
   1282   Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
   1283       isolate(), deoptimization_id, bailout_type);
   1284   __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
   1285 }
   1286 
   1287 
   1288 // The calling convention for JSFunctions on IA32 passes arguments on the
   1289 // stack and the JSFunction and context in EDI and ESI, respectively, thus
   1290 // the steps of the call look as follows:
   1291 
   1292 // --{ before the call instruction }--------------------------------------------
   1293 //                                                         |  caller frame |
   1294 //                                                         ^ esp           ^ ebp
   1295 
   1296 // --{ push arguments and setup ESI, EDI }--------------------------------------
   1297 //                                       | args + receiver |  caller frame |
   1298 //                                       ^ esp                             ^ ebp
   1299 //                 [edi = JSFunction, esi = context]
   1300 
   1301 // --{ call [edi + kCodeEntryOffset] }------------------------------------------
   1302 //                                 | RET | args + receiver |  caller frame |
   1303 //                                 ^ esp                                   ^ ebp
   1304 
   1305 // =={ prologue of called function }============================================
   1306 // --{ push ebp }---------------------------------------------------------------
   1307 //                            | FP | RET | args + receiver |  caller frame |
   1308 //                            ^ esp                                        ^ ebp
   1309 
   1310 // --{ mov ebp, esp }-----------------------------------------------------------
   1311 //                            | FP | RET | args + receiver |  caller frame |
   1312 //                            ^ ebp,esp
   1313 
   1314 // --{ push esi }---------------------------------------------------------------
   1315 //                      | CTX | FP | RET | args + receiver |  caller frame |
   1316 //                      ^esp  ^ ebp
   1317 
   1318 // --{ push edi }---------------------------------------------------------------
   1319 //                | FNC | CTX | FP | RET | args + receiver |  caller frame |
   1320 //                ^esp        ^ ebp
   1321 
   1322 // --{ subi esp, #N }-----------------------------------------------------------
   1323 // | callee frame | FNC | CTX | FP | RET | args + receiver |  caller frame |
   1324 // ^esp                       ^ ebp
   1325 
   1326 // =={ body of called function }================================================
   1327 
   1328 // =={ epilogue of called function }============================================
   1329 // --{ mov esp, ebp }-----------------------------------------------------------
   1330 //                            | FP | RET | args + receiver |  caller frame |
   1331 //                            ^ esp,ebp
   1332 
   1333 // --{ pop ebp }-----------------------------------------------------------
   1334 // |                               | RET | args + receiver |  caller frame |
   1335 //                                 ^ esp                                   ^ ebp
   1336 
   1337 // --{ ret #A+1 }-----------------------------------------------------------
   1338 // |                                                       |  caller frame |
   1339 //                                                         ^ esp           ^ ebp
   1340 
   1341 
   1342 // Runtime function calls are accomplished by doing a stub call to the
   1343 // CEntryStub (a real code object). On IA32 passes arguments on the
   1344 // stack, the number of arguments in EAX, the address of the runtime function
   1345 // in EBX, and the context in ESI.
   1346 
   1347 // --{ before the call instruction }--------------------------------------------
   1348 //                                                         |  caller frame |
   1349 //                                                         ^ esp           ^ ebp
   1350 
   1351 // --{ push arguments and setup EAX, EBX, and ESI }-----------------------------
   1352 //                                       | args + receiver |  caller frame |
   1353 //                                       ^ esp                             ^ ebp
   1354 //              [eax = #args, ebx = runtime function, esi = context]
   1355 
   1356 // --{ call #CEntryStub }-------------------------------------------------------
   1357 //                                 | RET | args + receiver |  caller frame |
   1358 //                                 ^ esp                                   ^ ebp
   1359 
   1360 // =={ body of runtime function }===============================================
   1361 
   1362 // --{ runtime returns }--------------------------------------------------------
   1363 //                                                         |  caller frame |
   1364 //                                                         ^ esp           ^ ebp
   1365 
   1366 // Other custom linkages (e.g. for calling directly into and out of C++) may
   1367 // need to save callee-saved registers on the stack, which is done in the
   1368 // function prologue of generated code.
   1369 
   1370 // --{ before the call instruction }--------------------------------------------
   1371 //                                                         |  caller frame |
   1372 //                                                         ^ esp           ^ ebp
   1373 
   1374 // --{ set up arguments in registers on stack }---------------------------------
   1375 //                                                  | args |  caller frame |
   1376 //                                                  ^ esp                  ^ ebp
   1377 //                  [r0 = arg0, r1 = arg1, ...]
   1378 
   1379 // --{ call code }--------------------------------------------------------------
   1380 //                                            | RET | args |  caller frame |
   1381 //                                            ^ esp                        ^ ebp
   1382 
   1383 // =={ prologue of called function }============================================
   1384 // --{ push ebp }---------------------------------------------------------------
   1385 //                                       | FP | RET | args |  caller frame |
   1386 //                                       ^ esp                             ^ ebp
   1387 
   1388 // --{ mov ebp, esp }-----------------------------------------------------------
   1389 //                                       | FP | RET | args |  caller frame |
   1390 //                                       ^ ebp,esp
   1391 
   1392 // --{ save registers }---------------------------------------------------------
   1393 //                                | regs | FP | RET | args |  caller frame |
   1394 //                                ^ esp  ^ ebp
   1395 
   1396 // --{ subi esp, #N }-----------------------------------------------------------
   1397 //                 | callee frame | regs | FP | RET | args |  caller frame |
   1398 //                 ^esp                  ^ ebp
   1399 
   1400 // =={ body of called function }================================================
   1401 
   1402 // =={ epilogue of called function }============================================
   1403 // --{ restore registers }------------------------------------------------------
   1404 //                                | regs | FP | RET | args |  caller frame |
   1405 //                                ^ esp  ^ ebp
   1406 
   1407 // --{ mov esp, ebp }-----------------------------------------------------------
   1408 //                                       | FP | RET | args |  caller frame |
   1409 //                                       ^ esp,ebp
   1410 
   1411 // --{ pop ebp }----------------------------------------------------------------
   1412 //                                            | RET | args |  caller frame |
   1413 //                                            ^ esp                        ^ ebp
   1414 
   1415 
   1416 void CodeGenerator::AssemblePrologue() {
   1417   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   1418   if (descriptor->IsCFunctionCall()) {
   1419     // Assemble a prologue similar the to cdecl calling convention.
   1420     __ push(ebp);
   1421     __ mov(ebp, esp);
   1422   } else if (descriptor->IsJSFunctionCall()) {
   1423     // TODO(turbofan): this prologue is redundant with OSR, but still needed for
   1424     // code aging.
   1425     __ Prologue(this->info()->GeneratePreagedPrologue());
   1426   } else if (frame()->needs_frame()) {
   1427     __ StubPrologue();
   1428   } else {
   1429     frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize);
   1430   }
   1431   frame_access_state()->SetFrameAccessToDefault();
   1432 
   1433   int stack_shrink_slots = frame()->GetSpillSlotCount();
   1434   if (info()->is_osr()) {
   1435     // TurboFan OSR-compiled functions cannot be entered directly.
   1436     __ Abort(kShouldNotDirectlyEnterOsrFunction);
   1437 
   1438     // Unoptimized code jumps directly to this entrypoint while the unoptimized
   1439     // frame is still on the stack. Optimized code uses OSR values directly from
   1440     // the unoptimized frame. Thus, all that needs to be done is to allocate the
   1441     // remaining stack slots.
   1442     if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
   1443     osr_pc_offset_ = __ pc_offset();
   1444     // TODO(titzer): cannot address target function == local #-1
   1445     __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
   1446     stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
   1447   }
   1448 
   1449   const RegList saves = descriptor->CalleeSavedRegisters();
   1450   if (stack_shrink_slots > 0) {
   1451     __ sub(esp, Immediate(stack_shrink_slots * kPointerSize));
   1452   }
   1453 
   1454   if (saves != 0) {  // Save callee-saved registers.
   1455     DCHECK(!info()->is_osr());
   1456     int pushed = 0;
   1457     for (int i = Register::kNumRegisters - 1; i >= 0; i--) {
   1458       if (!((1 << i) & saves)) continue;
   1459       __ push(Register::from_code(i));
   1460       ++pushed;
   1461     }
   1462     frame()->AllocateSavedCalleeRegisterSlots(pushed);
   1463   }
   1464 }
   1465 
   1466 
   1467 void CodeGenerator::AssembleReturn() {
   1468   CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
   1469 
   1470   const RegList saves = descriptor->CalleeSavedRegisters();
   1471   // Restore registers.
   1472   if (saves != 0) {
   1473     for (int i = 0; i < Register::kNumRegisters; i++) {
   1474       if (!((1 << i) & saves)) continue;
   1475       __ pop(Register::from_code(i));
   1476     }
   1477   }
   1478 
   1479   if (descriptor->IsCFunctionCall()) {
   1480     __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
   1481     __ pop(ebp);       // Pop caller's frame pointer.
   1482   } else if (frame()->needs_frame()) {
   1483     // Canonicalize JSFunction return sites for now.
   1484     if (return_label_.is_bound()) {
   1485       __ jmp(&return_label_);
   1486       return;
   1487     } else {
   1488       __ bind(&return_label_);
   1489       __ mov(esp, ebp);  // Move stack pointer back to frame pointer.
   1490       __ pop(ebp);       // Pop caller's frame pointer.
   1491     }
   1492   }
   1493   size_t pop_size = descriptor->StackParameterCount() * kPointerSize;
   1494   // Might need ecx for scratch if pop_size is too big.
   1495   DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & ecx.bit());
   1496   __ Ret(static_cast<int>(pop_size), ecx);
   1497 }
   1498 
   1499 
   1500 void CodeGenerator::AssembleMove(InstructionOperand* source,
   1501                                  InstructionOperand* destination) {
   1502   IA32OperandConverter g(this, nullptr);
   1503   // Dispatch on the source and destination operand kinds.  Not all
   1504   // combinations are possible.
   1505   if (source->IsRegister()) {
   1506     DCHECK(destination->IsRegister() || destination->IsStackSlot());
   1507     Register src = g.ToRegister(source);
   1508     Operand dst = g.ToOperand(destination);
   1509     __ mov(dst, src);
   1510   } else if (source->IsStackSlot()) {
   1511     DCHECK(destination->IsRegister() || destination->IsStackSlot());
   1512     Operand src = g.ToOperand(source);
   1513     if (destination->IsRegister()) {
   1514       Register dst = g.ToRegister(destination);
   1515       __ mov(dst, src);
   1516     } else {
   1517       Operand dst = g.ToOperand(destination);
   1518       __ push(src);
   1519       __ pop(dst);
   1520     }
   1521   } else if (source->IsConstant()) {
   1522     Constant src_constant = g.ToConstant(source);
   1523     if (src_constant.type() == Constant::kHeapObject) {
   1524       Handle<HeapObject> src = src_constant.ToHeapObject();
   1525       int offset;
   1526       if (IsMaterializableFromFrame(src, &offset)) {
   1527         if (destination->IsRegister()) {
   1528           Register dst = g.ToRegister(destination);
   1529           __ mov(dst, g.ToMaterializableOperand(offset));
   1530         } else {
   1531           DCHECK(destination->IsStackSlot());
   1532           Operand dst = g.ToOperand(destination);
   1533           __ push(g.ToMaterializableOperand(offset));
   1534           __ pop(dst);
   1535         }
   1536       } else if (destination->IsRegister()) {
   1537         Register dst = g.ToRegister(destination);
   1538         __ LoadHeapObject(dst, src);
   1539       } else {
   1540         DCHECK(destination->IsStackSlot());
   1541         Operand dst = g.ToOperand(destination);
   1542         AllowDeferredHandleDereference embedding_raw_address;
   1543         if (isolate()->heap()->InNewSpace(*src)) {
   1544           __ PushHeapObject(src);
   1545           __ pop(dst);
   1546         } else {
   1547           __ mov(dst, src);
   1548         }
   1549       }
   1550     } else if (destination->IsRegister()) {
   1551       Register dst = g.ToRegister(destination);
   1552       __ Move(dst, g.ToImmediate(source));
   1553     } else if (destination->IsStackSlot()) {
   1554       Operand dst = g.ToOperand(destination);
   1555       __ Move(dst, g.ToImmediate(source));
   1556     } else if (src_constant.type() == Constant::kFloat32) {
   1557       // TODO(turbofan): Can we do better here?
   1558       uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32());
   1559       if (destination->IsDoubleRegister()) {
   1560         XMMRegister dst = g.ToDoubleRegister(destination);
   1561         __ Move(dst, src);
   1562       } else {
   1563         DCHECK(destination->IsDoubleStackSlot());
   1564         Operand dst = g.ToOperand(destination);
   1565         __ Move(dst, Immediate(src));
   1566       }
   1567     } else {
   1568       DCHECK_EQ(Constant::kFloat64, src_constant.type());
   1569       uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
   1570       uint32_t lower = static_cast<uint32_t>(src);
   1571       uint32_t upper = static_cast<uint32_t>(src >> 32);
   1572       if (destination->IsDoubleRegister()) {
   1573         XMMRegister dst = g.ToDoubleRegister(destination);
   1574         __ Move(dst, src);
   1575       } else {
   1576         DCHECK(destination->IsDoubleStackSlot());
   1577         Operand dst0 = g.ToOperand(destination);
   1578         Operand dst1 = g.HighOperand(destination);
   1579         __ Move(dst0, Immediate(lower));
   1580         __ Move(dst1, Immediate(upper));
   1581       }
   1582     }
   1583   } else if (source->IsDoubleRegister()) {
   1584     XMMRegister src = g.ToDoubleRegister(source);
   1585     if (destination->IsDoubleRegister()) {
   1586       XMMRegister dst = g.ToDoubleRegister(destination);
   1587       __ movaps(dst, src);
   1588     } else {
   1589       DCHECK(destination->IsDoubleStackSlot());
   1590       Operand dst = g.ToOperand(destination);
   1591       __ movsd(dst, src);
   1592     }
   1593   } else if (source->IsDoubleStackSlot()) {
   1594     DCHECK(destination->IsDoubleRegister() || destination->IsDoubleStackSlot());
   1595     Operand src = g.ToOperand(source);
   1596     if (destination->IsDoubleRegister()) {
   1597       XMMRegister dst = g.ToDoubleRegister(destination);
   1598       __ movsd(dst, src);
   1599     } else {
   1600       Operand dst = g.ToOperand(destination);
   1601       __ movsd(kScratchDoubleReg, src);
   1602       __ movsd(dst, kScratchDoubleReg);
   1603     }
   1604   } else {
   1605     UNREACHABLE();
   1606   }
   1607 }
   1608 
   1609 
   1610 void CodeGenerator::AssembleSwap(InstructionOperand* source,
   1611                                  InstructionOperand* destination) {
   1612   IA32OperandConverter g(this, nullptr);
   1613   // Dispatch on the source and destination operand kinds.  Not all
   1614   // combinations are possible.
   1615   if (source->IsRegister() && destination->IsRegister()) {
   1616     // Register-register.
   1617     Register src = g.ToRegister(source);
   1618     Register dst = g.ToRegister(destination);
   1619     __ push(src);
   1620     __ mov(src, dst);
   1621     __ pop(dst);
   1622   } else if (source->IsRegister() && destination->IsStackSlot()) {
   1623     // Register-memory.
   1624     Register src = g.ToRegister(source);
   1625     __ push(src);
   1626     frame_access_state()->IncreaseSPDelta(1);
   1627     Operand dst = g.ToOperand(destination);
   1628     __ mov(src, dst);
   1629     frame_access_state()->IncreaseSPDelta(-1);
   1630     dst = g.ToOperand(destination);
   1631     __ pop(dst);
   1632   } else if (source->IsStackSlot() && destination->IsStackSlot()) {
   1633     // Memory-memory.
   1634     Operand dst1 = g.ToOperand(destination);
   1635     __ push(dst1);
   1636     frame_access_state()->IncreaseSPDelta(1);
   1637     Operand src1 = g.ToOperand(source);
   1638     __ push(src1);
   1639     Operand dst2 = g.ToOperand(destination);
   1640     __ pop(dst2);
   1641     frame_access_state()->IncreaseSPDelta(-1);
   1642     Operand src2 = g.ToOperand(source);
   1643     __ pop(src2);
   1644   } else if (source->IsDoubleRegister() && destination->IsDoubleRegister()) {
   1645     // XMM register-register swap.
   1646     XMMRegister src = g.ToDoubleRegister(source);
   1647     XMMRegister dst = g.ToDoubleRegister(destination);
   1648     __ movaps(kScratchDoubleReg, src);
   1649     __ movaps(src, dst);
   1650     __ movaps(dst, kScratchDoubleReg);
   1651   } else if (source->IsDoubleRegister() && destination->IsDoubleStackSlot()) {
   1652     // XMM register-memory swap.
   1653     XMMRegister reg = g.ToDoubleRegister(source);
   1654     Operand other = g.ToOperand(destination);
   1655     __ movsd(kScratchDoubleReg, other);
   1656     __ movsd(other, reg);
   1657     __ movaps(reg, kScratchDoubleReg);
   1658   } else if (source->IsDoubleStackSlot() && destination->IsDoubleStackSlot()) {
   1659     // Double-width memory-to-memory.
   1660     Operand src0 = g.ToOperand(source);
   1661     Operand src1 = g.HighOperand(source);
   1662     Operand dst0 = g.ToOperand(destination);
   1663     Operand dst1 = g.HighOperand(destination);
   1664     __ movsd(kScratchDoubleReg, dst0);  // Save destination in scratch register.
   1665     __ push(src0);  // Then use stack to copy source to destination.
   1666     __ pop(dst0);
   1667     __ push(src1);
   1668     __ pop(dst1);
   1669     __ movsd(src0, kScratchDoubleReg);
   1670   } else {
   1671     // No other combinations are possible.
   1672     UNREACHABLE();
   1673   }
   1674 }
   1675 
   1676 
   1677 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) {
   1678   for (size_t index = 0; index < target_count; ++index) {
   1679     __ dd(targets[index]);
   1680   }
   1681 }
   1682 
   1683 
   1684 void CodeGenerator::AddNopForSmiCodeInlining() { __ nop(); }
   1685 
   1686 
   1687 void CodeGenerator::EnsureSpaceForLazyDeopt() {
   1688   if (!info()->ShouldEnsureSpaceForLazyDeopt()) {
   1689     return;
   1690   }
   1691 
   1692   int space_needed = Deoptimizer::patch_size();
   1693   // Ensure that we have enough space after the previous lazy-bailout
   1694   // instruction for patching the code here.
   1695   int current_pc = masm()->pc_offset();
   1696   if (current_pc < last_lazy_deopt_pc_ + space_needed) {
   1697     int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
   1698     __ Nop(padding_size);
   1699   }
   1700 }
   1701 
   1702 #undef __
   1703 
   1704 }  // namespace compiler
   1705 }  // namespace internal
   1706 }  // namespace v8
   1707