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