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