Home | History | Annotate | Download | only in arm64
      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/crankshaft/arm64/lithium-arm64.h"
      6 
      7 #include <sstream>
      8 
      9 #include "src/crankshaft/arm64/lithium-codegen-arm64.h"
     10 #include "src/crankshaft/hydrogen-osr.h"
     11 #include "src/crankshaft/lithium-inl.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 #define DEFINE_COMPILE(type)                            \
     17   void L##type::CompileToNative(LCodeGen* generator) {  \
     18     generator->Do##type(this);                          \
     19   }
     20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
     21 #undef DEFINE_COMPILE
     22 
     23 #ifdef DEBUG
     24 void LInstruction::VerifyCall() {
     25   // Call instructions can use only fixed registers as temporaries and
     26   // outputs because all registers are blocked by the calling convention.
     27   // Inputs operands must use a fixed register or use-at-start policy or
     28   // a non-register policy.
     29   DCHECK(Output() == NULL ||
     30          LUnallocated::cast(Output())->HasFixedPolicy() ||
     31          !LUnallocated::cast(Output())->HasRegisterPolicy());
     32   for (UseIterator it(this); !it.Done(); it.Advance()) {
     33     LUnallocated* operand = LUnallocated::cast(it.Current());
     34     DCHECK(operand->HasFixedPolicy() ||
     35            operand->IsUsedAtStart());
     36   }
     37   for (TempIterator it(this); !it.Done(); it.Advance()) {
     38     LUnallocated* operand = LUnallocated::cast(it.Current());
     39     DCHECK(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
     40   }
     41 }
     42 #endif
     43 
     44 
     45 void LLabel::PrintDataTo(StringStream* stream) {
     46   LGap::PrintDataTo(stream);
     47   LLabel* rep = replacement();
     48   if (rep != NULL) {
     49     stream->Add(" Dead block replaced with B%d", rep->block_id());
     50   }
     51 }
     52 
     53 
     54 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
     55   arguments()->PrintTo(stream);
     56   stream->Add(" length ");
     57   length()->PrintTo(stream);
     58   stream->Add(" index ");
     59   index()->PrintTo(stream);
     60 }
     61 
     62 
     63 void LBranch::PrintDataTo(StringStream* stream) {
     64   stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
     65   value()->PrintTo(stream);
     66 }
     67 
     68 
     69 void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
     70   for (int i = 0; i < InputCount(); i++) {
     71     InputAt(i)->PrintTo(stream);
     72     stream->Add(" ");
     73   }
     74   stream->Add("#%d / ", arity());
     75 }
     76 
     77 
     78 void LCallNewArray::PrintDataTo(StringStream* stream) {
     79   stream->Add("= ");
     80   constructor()->PrintTo(stream);
     81   stream->Add(" #%d / ", arity());
     82   ElementsKind kind = hydrogen()->elements_kind();
     83   stream->Add(" (%s) ", ElementsKindToString(kind));
     84 }
     85 
     86 
     87 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
     88   stream->Add("if class_of_test(");
     89   value()->PrintTo(stream);
     90   stream->Add(", \"%o\") then B%d else B%d",
     91               *hydrogen()->class_name(),
     92               true_block_id(),
     93               false_block_id());
     94 }
     95 
     96 
     97 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
     98   stream->Add("if ");
     99   left()->PrintTo(stream);
    100   stream->Add(" %s ", Token::String(op()));
    101   right()->PrintTo(stream);
    102   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
    103 }
    104 
    105 bool LGoto::HasInterestingComment(LCodeGen* gen) const {
    106   return !gen->IsNextEmittedBlock(block_id());
    107 }
    108 
    109 
    110 void LGoto::PrintDataTo(StringStream* stream) {
    111   stream->Add("B%d", block_id());
    112 }
    113 
    114 
    115 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
    116   stream->Add(" = ");
    117   base_object()->PrintTo(stream);
    118   stream->Add(" + ");
    119   offset()->PrintTo(stream);
    120 }
    121 
    122 
    123 void LInvokeFunction::PrintDataTo(StringStream* stream) {
    124   stream->Add("= ");
    125   function()->PrintTo(stream);
    126   stream->Add(" #%d / ", arity());
    127 }
    128 
    129 
    130 void LInstruction::PrintTo(StringStream* stream) {
    131   stream->Add("%s ", this->Mnemonic());
    132 
    133   PrintOutputOperandTo(stream);
    134 
    135   PrintDataTo(stream);
    136 
    137   if (HasEnvironment()) {
    138     stream->Add(" ");
    139     environment()->PrintTo(stream);
    140   }
    141 
    142   if (HasPointerMap()) {
    143     stream->Add(" ");
    144     pointer_map()->PrintTo(stream);
    145   }
    146 }
    147 
    148 
    149 void LInstruction::PrintDataTo(StringStream* stream) {
    150   stream->Add("= ");
    151   for (int i = 0; i < InputCount(); i++) {
    152     if (i > 0) stream->Add(" ");
    153     if (InputAt(i) == NULL) {
    154       stream->Add("NULL");
    155     } else {
    156       InputAt(i)->PrintTo(stream);
    157     }
    158   }
    159 }
    160 
    161 
    162 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
    163   if (HasResult()) result()->PrintTo(stream);
    164 }
    165 
    166 
    167 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
    168   stream->Add("if has_instance_type(");
    169   value()->PrintTo(stream);
    170   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    171 }
    172 
    173 
    174 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
    175   stream->Add("if is_string(");
    176   value()->PrintTo(stream);
    177   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    178 }
    179 
    180 
    181 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
    182   stream->Add("if is_smi(");
    183   value()->PrintTo(stream);
    184   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    185 }
    186 
    187 
    188 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
    189   stream->Add("if typeof ");
    190   value()->PrintTo(stream);
    191   stream->Add(" == \"%s\" then B%d else B%d",
    192               hydrogen()->type_literal()->ToCString().get(),
    193               true_block_id(), false_block_id());
    194 }
    195 
    196 
    197 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
    198   stream->Add("if is_undetectable(");
    199   value()->PrintTo(stream);
    200   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    201 }
    202 
    203 
    204 bool LGap::IsRedundant() const {
    205   for (int i = 0; i < 4; i++) {
    206     if ((parallel_moves_[i] != NULL) && !parallel_moves_[i]->IsRedundant()) {
    207       return false;
    208     }
    209   }
    210 
    211   return true;
    212 }
    213 
    214 
    215 void LGap::PrintDataTo(StringStream* stream) {
    216   for (int i = 0; i < 4; i++) {
    217     stream->Add("(");
    218     if (parallel_moves_[i] != NULL) {
    219       parallel_moves_[i]->PrintDataTo(stream);
    220     }
    221     stream->Add(") ");
    222   }
    223 }
    224 
    225 
    226 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
    227   context()->PrintTo(stream);
    228   stream->Add("[%d]", slot_index());
    229 }
    230 
    231 
    232 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
    233   stream->Add(" = ");
    234   function()->PrintTo(stream);
    235   stream->Add(".code_entry = ");
    236   code_object()->PrintTo(stream);
    237 }
    238 
    239 
    240 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
    241   context()->PrintTo(stream);
    242   stream->Add("[%d] <- ", slot_index());
    243   value()->PrintTo(stream);
    244 }
    245 
    246 
    247 void LStoreNamedField::PrintDataTo(StringStream* stream) {
    248   object()->PrintTo(stream);
    249   std::ostringstream os;
    250   os << hydrogen()->access();
    251   stream->Add(os.str().c_str());
    252   stream->Add(" <- ");
    253   value()->PrintTo(stream);
    254 }
    255 
    256 
    257 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
    258   stream->Add("if string_compare(");
    259   left()->PrintTo(stream);
    260   right()->PrintTo(stream);
    261   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    262 }
    263 
    264 
    265 void LTransitionElementsKind::PrintDataTo(StringStream* stream) {
    266   object()->PrintTo(stream);
    267   stream->Add("%p -> %p", *original_map(), *transitioned_map());
    268 }
    269 
    270 
    271 template<int T>
    272 void LUnaryMathOperation<T>::PrintDataTo(StringStream* stream) {
    273   value()->PrintTo(stream);
    274 }
    275 
    276 
    277 const char* LArithmeticD::Mnemonic() const {
    278   switch (op()) {
    279     case Token::ADD: return "add-d";
    280     case Token::SUB: return "sub-d";
    281     case Token::MUL: return "mul-d";
    282     case Token::DIV: return "div-d";
    283     case Token::MOD: return "mod-d";
    284     default:
    285       UNREACHABLE();
    286       return NULL;
    287   }
    288 }
    289 
    290 
    291 const char* LArithmeticT::Mnemonic() const {
    292   switch (op()) {
    293     case Token::ADD: return "add-t";
    294     case Token::SUB: return "sub-t";
    295     case Token::MUL: return "mul-t";
    296     case Token::MOD: return "mod-t";
    297     case Token::DIV: return "div-t";
    298     case Token::BIT_AND: return "bit-and-t";
    299     case Token::BIT_OR: return "bit-or-t";
    300     case Token::BIT_XOR: return "bit-xor-t";
    301     case Token::ROR: return "ror-t";
    302     case Token::SHL: return "shl-t";
    303     case Token::SAR: return "sar-t";
    304     case Token::SHR: return "shr-t";
    305     default:
    306       UNREACHABLE();
    307       return NULL;
    308   }
    309 }
    310 
    311 
    312 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
    313   return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
    314 }
    315 
    316 
    317 LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
    318   return new (zone())
    319       LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
    320 }
    321 
    322 
    323 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
    324   if (value->EmitAtUses()) {
    325     HInstruction* instr = HInstruction::cast(value);
    326     VisitInstruction(instr);
    327   }
    328   operand->set_virtual_register(value->id());
    329   return operand;
    330 }
    331 
    332 
    333 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
    334   return Use(value, ToUnallocated(fixed_register));
    335 }
    336 
    337 
    338 LOperand* LChunkBuilder::UseFixedDouble(HValue* value,
    339                                         DoubleRegister fixed_register) {
    340   return Use(value, ToUnallocated(fixed_register));
    341 }
    342 
    343 
    344 LOperand* LChunkBuilder::UseRegister(HValue* value) {
    345   return Use(value, new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
    346 }
    347 
    348 
    349 LOperand* LChunkBuilder::UseRegisterAndClobber(HValue* value) {
    350   return Use(value, new(zone()) LUnallocated(LUnallocated::WRITABLE_REGISTER));
    351 }
    352 
    353 
    354 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
    355   return Use(value,
    356              new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
    357                                       LUnallocated::USED_AT_START));
    358 }
    359 
    360 
    361 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
    362   return value->IsConstant() ? UseConstant(value) : UseRegister(value);
    363 }
    364 
    365 
    366 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
    367   return value->IsConstant() ? UseConstant(value) : UseRegisterAtStart(value);
    368 }
    369 
    370 
    371 LConstantOperand* LChunkBuilder::UseConstant(HValue* value) {
    372   return chunk_->DefineConstantOperand(HConstant::cast(value));
    373 }
    374 
    375 
    376 LOperand* LChunkBuilder::UseAny(HValue* value) {
    377   return value->IsConstant()
    378       ? UseConstant(value)
    379       : Use(value, new(zone()) LUnallocated(LUnallocated::ANY));
    380 }
    381 
    382 
    383 LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
    384                                     LUnallocated* result) {
    385   result->set_virtual_register(current_instruction_->id());
    386   instr->set_result(result);
    387   return instr;
    388 }
    389 
    390 
    391 LInstruction* LChunkBuilder::DefineAsRegister(
    392     LTemplateResultInstruction<1>* instr) {
    393   return Define(instr,
    394                 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
    395 }
    396 
    397 
    398 LInstruction* LChunkBuilder::DefineAsSpilled(
    399     LTemplateResultInstruction<1>* instr, int index) {
    400   return Define(instr,
    401                 new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
    402 }
    403 
    404 
    405 LInstruction* LChunkBuilder::DefineSameAsFirst(
    406     LTemplateResultInstruction<1>* instr) {
    407   return Define(instr,
    408                 new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
    409 }
    410 
    411 
    412 LInstruction* LChunkBuilder::DefineFixed(
    413     LTemplateResultInstruction<1>* instr, Register reg) {
    414   return Define(instr, ToUnallocated(reg));
    415 }
    416 
    417 
    418 LInstruction* LChunkBuilder::DefineFixedDouble(
    419     LTemplateResultInstruction<1>* instr, DoubleRegister reg) {
    420   return Define(instr, ToUnallocated(reg));
    421 }
    422 
    423 
    424 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
    425                                         HInstruction* hinstr,
    426                                         CanDeoptimize can_deoptimize) {
    427   info()->MarkAsNonDeferredCalling();
    428 #ifdef DEBUG
    429   instr->VerifyCall();
    430 #endif
    431   instr->MarkAsCall();
    432   instr = AssignPointerMap(instr);
    433 
    434   // If instruction does not have side-effects lazy deoptimization
    435   // after the call will try to deoptimize to the point before the call.
    436   // Thus we still need to attach environment to this call even if
    437   // call sequence can not deoptimize eagerly.
    438   bool needs_environment =
    439       (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) ||
    440       !hinstr->HasObservableSideEffects();
    441   if (needs_environment && !instr->HasEnvironment()) {
    442     instr = AssignEnvironment(instr);
    443     // We can't really figure out if the environment is needed or not.
    444     instr->environment()->set_has_been_used();
    445   }
    446 
    447   return instr;
    448 }
    449 
    450 
    451 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
    452   DCHECK(!instr->HasPointerMap());
    453   instr->set_pointer_map(new(zone()) LPointerMap(zone()));
    454   return instr;
    455 }
    456 
    457 
    458 LUnallocated* LChunkBuilder::TempRegister() {
    459   LUnallocated* operand =
    460       new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
    461   int vreg = allocator_->GetVirtualRegister();
    462   if (!allocator_->AllocationOk()) {
    463     Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
    464     vreg = 0;
    465   }
    466   operand->set_virtual_register(vreg);
    467   return operand;
    468 }
    469 
    470 
    471 LUnallocated* LChunkBuilder::TempDoubleRegister() {
    472   LUnallocated* operand =
    473       new(zone()) LUnallocated(LUnallocated::MUST_HAVE_DOUBLE_REGISTER);
    474   int vreg = allocator_->GetVirtualRegister();
    475   if (!allocator_->AllocationOk()) {
    476     Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister);
    477     vreg = 0;
    478   }
    479   operand->set_virtual_register(vreg);
    480   return operand;
    481 }
    482 
    483 int LPlatformChunk::GetNextSpillIndex() { return current_frame_slots_++; }
    484 
    485 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) {
    486   int index = GetNextSpillIndex();
    487   if (kind == DOUBLE_REGISTERS) {
    488     return LDoubleStackSlot::Create(index, zone());
    489   } else {
    490     DCHECK(kind == GENERAL_REGISTERS);
    491     return LStackSlot::Create(index, zone());
    492   }
    493 }
    494 
    495 
    496 LOperand* LChunkBuilder::FixedTemp(Register reg) {
    497   LUnallocated* operand = ToUnallocated(reg);
    498   DCHECK(operand->HasFixedPolicy());
    499   return operand;
    500 }
    501 
    502 
    503 LOperand* LChunkBuilder::FixedTemp(DoubleRegister reg) {
    504   LUnallocated* operand = ToUnallocated(reg);
    505   DCHECK(operand->HasFixedPolicy());
    506   return operand;
    507 }
    508 
    509 
    510 LPlatformChunk* LChunkBuilder::Build() {
    511   DCHECK(is_unused());
    512   chunk_ = new(zone()) LPlatformChunk(info_, graph_);
    513   LPhase phase("L_Building chunk", chunk_);
    514   status_ = BUILDING;
    515 
    516   // If compiling for OSR, reserve space for the unoptimized frame,
    517   // which will be subsumed into this frame.
    518   if (graph()->has_osr()) {
    519     // TODO(all): GetNextSpillIndex just increments a field. It has no other
    520     // side effects, so we should get rid of this loop.
    521     for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) {
    522       chunk_->GetNextSpillIndex();
    523     }
    524   }
    525 
    526   const ZoneList<HBasicBlock*>* blocks = graph_->blocks();
    527   for (int i = 0; i < blocks->length(); i++) {
    528     DoBasicBlock(blocks->at(i));
    529     if (is_aborted()) return NULL;
    530   }
    531   status_ = DONE;
    532   return chunk_;
    533 }
    534 
    535 
    536 void LChunkBuilder::DoBasicBlock(HBasicBlock* block) {
    537   DCHECK(is_building());
    538   current_block_ = block;
    539 
    540   if (block->IsStartBlock()) {
    541     block->UpdateEnvironment(graph_->start_environment());
    542     argument_count_ = 0;
    543   } else if (block->predecessors()->length() == 1) {
    544     // We have a single predecessor => copy environment and outgoing
    545     // argument count from the predecessor.
    546     DCHECK(block->phis()->length() == 0);
    547     HBasicBlock* pred = block->predecessors()->at(0);
    548     HEnvironment* last_environment = pred->last_environment();
    549     DCHECK(last_environment != NULL);
    550 
    551     // Only copy the environment, if it is later used again.
    552     if (pred->end()->SecondSuccessor() == NULL) {
    553       DCHECK(pred->end()->FirstSuccessor() == block);
    554     } else {
    555       if ((pred->end()->FirstSuccessor()->block_id() > block->block_id()) ||
    556           (pred->end()->SecondSuccessor()->block_id() > block->block_id())) {
    557         last_environment = last_environment->Copy();
    558       }
    559     }
    560     block->UpdateEnvironment(last_environment);
    561     DCHECK(pred->argument_count() >= 0);
    562     argument_count_ = pred->argument_count();
    563   } else {
    564     // We are at a state join => process phis.
    565     HBasicBlock* pred = block->predecessors()->at(0);
    566     // No need to copy the environment, it cannot be used later.
    567     HEnvironment* last_environment = pred->last_environment();
    568     for (int i = 0; i < block->phis()->length(); ++i) {
    569       HPhi* phi = block->phis()->at(i);
    570       if (phi->HasMergedIndex()) {
    571         last_environment->SetValueAt(phi->merged_index(), phi);
    572       }
    573     }
    574     for (int i = 0; i < block->deleted_phis()->length(); ++i) {
    575       if (block->deleted_phis()->at(i) < last_environment->length()) {
    576         last_environment->SetValueAt(block->deleted_phis()->at(i),
    577                                      graph_->GetConstantUndefined());
    578       }
    579     }
    580     block->UpdateEnvironment(last_environment);
    581     // Pick up the outgoing argument count of one of the predecessors.
    582     argument_count_ = pred->argument_count();
    583   }
    584 
    585   // Translate hydrogen instructions to lithium ones for the current block.
    586   HInstruction* current = block->first();
    587   int start = chunk_->instructions()->length();
    588   while ((current != NULL) && !is_aborted()) {
    589     // Code for constants in registers is generated lazily.
    590     if (!current->EmitAtUses()) {
    591       VisitInstruction(current);
    592     }
    593     current = current->next();
    594   }
    595   int end = chunk_->instructions()->length() - 1;
    596   if (end >= start) {
    597     block->set_first_instruction_index(start);
    598     block->set_last_instruction_index(end);
    599   }
    600   block->set_argument_count(argument_count_);
    601   current_block_ = NULL;
    602 }
    603 
    604 
    605 void LChunkBuilder::VisitInstruction(HInstruction* current) {
    606   HInstruction* old_current = current_instruction_;
    607   current_instruction_ = current;
    608 
    609   LInstruction* instr = NULL;
    610   if (current->CanReplaceWithDummyUses()) {
    611     if (current->OperandCount() == 0) {
    612       instr = DefineAsRegister(new(zone()) LDummy());
    613     } else {
    614       DCHECK(!current->OperandAt(0)->IsControlInstruction());
    615       instr = DefineAsRegister(new(zone())
    616           LDummyUse(UseAny(current->OperandAt(0))));
    617     }
    618     for (int i = 1; i < current->OperandCount(); ++i) {
    619       if (current->OperandAt(i)->IsControlInstruction()) continue;
    620       LInstruction* dummy =
    621           new(zone()) LDummyUse(UseAny(current->OperandAt(i)));
    622       dummy->set_hydrogen_value(current);
    623       chunk_->AddInstruction(dummy, current_block_);
    624     }
    625   } else {
    626     HBasicBlock* successor;
    627     if (current->IsControlInstruction() &&
    628         HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) &&
    629         successor != NULL) {
    630       instr = new(zone()) LGoto(successor);
    631     } else {
    632       instr = current->CompileToLithium(this);
    633     }
    634   }
    635 
    636   argument_count_ += current->argument_delta();
    637   DCHECK(argument_count_ >= 0);
    638 
    639   if (instr != NULL) {
    640     AddInstruction(instr, current);
    641   }
    642 
    643   current_instruction_ = old_current;
    644 }
    645 
    646 
    647 void LChunkBuilder::AddInstruction(LInstruction* instr,
    648                                    HInstruction* hydrogen_val) {
    649   // Associate the hydrogen instruction first, since we may need it for
    650   // the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
    651   instr->set_hydrogen_value(hydrogen_val);
    652 
    653 #if DEBUG
    654   // Make sure that the lithium instruction has either no fixed register
    655   // constraints in temps or the result OR no uses that are only used at
    656   // start. If this invariant doesn't hold, the register allocator can decide
    657   // to insert a split of a range immediately before the instruction due to an
    658   // already allocated register needing to be used for the instruction's fixed
    659   // register constraint. In this case, the register allocator won't see an
    660   // interference between the split child and the use-at-start (it would if
    661   // the it was just a plain use), so it is free to move the split child into
    662   // the same register that is used for the use-at-start.
    663   // See https://code.google.com/p/chromium/issues/detail?id=201590
    664   if (!(instr->ClobbersRegisters() &&
    665         instr->ClobbersDoubleRegisters(isolate()))) {
    666     int fixed = 0;
    667     int used_at_start = 0;
    668     for (UseIterator it(instr); !it.Done(); it.Advance()) {
    669       LUnallocated* operand = LUnallocated::cast(it.Current());
    670       if (operand->IsUsedAtStart()) ++used_at_start;
    671     }
    672     if (instr->Output() != NULL) {
    673       if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed;
    674     }
    675     for (TempIterator it(instr); !it.Done(); it.Advance()) {
    676       LUnallocated* operand = LUnallocated::cast(it.Current());
    677       if (operand->HasFixedPolicy()) ++fixed;
    678     }
    679     DCHECK(fixed == 0 || used_at_start == 0);
    680   }
    681 #endif
    682 
    683   if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
    684     instr = AssignPointerMap(instr);
    685   }
    686   if (FLAG_stress_environments && !instr->HasEnvironment()) {
    687     instr = AssignEnvironment(instr);
    688   }
    689   chunk_->AddInstruction(instr, current_block_);
    690 
    691   CreateLazyBailoutForCall(current_block_, instr, hydrogen_val);
    692 }
    693 
    694 
    695 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
    696   HEnvironment* hydrogen_env = current_block_->last_environment();
    697   return LChunkBuilderBase::AssignEnvironment(instr, hydrogen_env);
    698 }
    699 
    700 
    701 LInstruction* LChunkBuilder::DoPrologue(HPrologue* instr) {
    702   LInstruction* result = new (zone()) LPrologue();
    703   if (info_->scope()->NeedsContext()) {
    704     result = MarkAsCall(result, instr);
    705   }
    706   return result;
    707 }
    708 
    709 
    710 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
    711   // The control instruction marking the end of a block that completed
    712   // abruptly (e.g., threw an exception). There is nothing specific to do.
    713   return NULL;
    714 }
    715 
    716 
    717 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
    718                                            HArithmeticBinaryOperation* instr) {
    719   DCHECK(instr->representation().IsDouble());
    720   DCHECK(instr->left()->representation().IsDouble());
    721   DCHECK(instr->right()->representation().IsDouble());
    722 
    723   if (op == Token::MOD) {
    724     LOperand* left = UseFixedDouble(instr->left(), d0);
    725     LOperand* right = UseFixedDouble(instr->right(), d1);
    726     LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right);
    727     return MarkAsCall(DefineFixedDouble(result, d0), instr);
    728   } else {
    729     LOperand* left = UseRegisterAtStart(instr->left());
    730     LOperand* right = UseRegisterAtStart(instr->right());
    731     LArithmeticD* result = new(zone()) LArithmeticD(op, left, right);
    732     return DefineAsRegister(result);
    733   }
    734 }
    735 
    736 
    737 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
    738                                            HBinaryOperation* instr) {
    739   DCHECK((op == Token::ADD) || (op == Token::SUB) || (op == Token::MUL) ||
    740          (op == Token::DIV) || (op == Token::MOD) || (op == Token::SHR) ||
    741          (op == Token::SHL) || (op == Token::SAR) || (op == Token::ROR) ||
    742          (op == Token::BIT_OR) || (op == Token::BIT_AND) ||
    743          (op == Token::BIT_XOR));
    744   HValue* left = instr->left();
    745   HValue* right = instr->right();
    746 
    747   // TODO(jbramley): Once we've implemented smi support for all arithmetic
    748   // operations, these assertions should check IsTagged().
    749   DCHECK(instr->representation().IsSmiOrTagged());
    750   DCHECK(left->representation().IsSmiOrTagged());
    751   DCHECK(right->representation().IsSmiOrTagged());
    752 
    753   LOperand* context = UseFixed(instr->context(), cp);
    754   LOperand* left_operand = UseFixed(left, x1);
    755   LOperand* right_operand = UseFixed(right, x0);
    756   LArithmeticT* result =
    757       new(zone()) LArithmeticT(op, context, left_operand, right_operand);
    758   return MarkAsCall(DefineFixed(result, x0), instr);
    759 }
    760 
    761 
    762 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
    763   info()->MarkAsRequiresFrame();
    764   LOperand* args = NULL;
    765   LOperand* length = NULL;
    766   LOperand* index = NULL;
    767 
    768   if (instr->length()->IsConstant() && instr->index()->IsConstant()) {
    769     args = UseRegisterAtStart(instr->arguments());
    770     length = UseConstant(instr->length());
    771     index = UseConstant(instr->index());
    772   } else {
    773     args = UseRegister(instr->arguments());
    774     length = UseRegisterAtStart(instr->length());
    775     index = UseRegisterOrConstantAtStart(instr->index());
    776   }
    777 
    778   return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
    779 }
    780 
    781 
    782 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
    783   if (instr->representation().IsSmiOrInteger32()) {
    784     DCHECK(instr->left()->representation().Equals(instr->representation()));
    785     DCHECK(instr->right()->representation().Equals(instr->representation()));
    786 
    787     LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
    788     if (shifted_operation != NULL) {
    789       return shifted_operation;
    790     }
    791 
    792     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
    793     LOperand* right =
    794         UseRegisterOrConstantAtStart(instr->BetterRightOperand());
    795     LInstruction* result = instr->representation().IsSmi() ?
    796         DefineAsRegister(new(zone()) LAddS(left, right)) :
    797         DefineAsRegister(new(zone()) LAddI(left, right));
    798     if (instr->CheckFlag(HValue::kCanOverflow)) {
    799       result = AssignEnvironment(result);
    800     }
    801     return result;
    802   } else if (instr->representation().IsExternal()) {
    803     DCHECK(instr->IsConsistentExternalRepresentation());
    804     DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
    805     LOperand* left = UseRegisterAtStart(instr->left());
    806     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
    807     return DefineAsRegister(new(zone()) LAddE(left, right));
    808   } else if (instr->representation().IsDouble()) {
    809     return DoArithmeticD(Token::ADD, instr);
    810   } else {
    811     DCHECK(instr->representation().IsTagged());
    812     return DoArithmeticT(Token::ADD, instr);
    813   }
    814 }
    815 
    816 
    817 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
    818   LOperand* size = UseRegisterOrConstant(instr->size());
    819   LOperand* temp1 = TempRegister();
    820   LOperand* temp2 = TempRegister();
    821   if (instr->IsAllocationFolded()) {
    822     LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
    823     return DefineAsRegister(result);
    824   } else {
    825     info()->MarkAsDeferredCalling();
    826     LOperand* context = UseAny(instr->context());
    827     LOperand* temp3 = instr->MustPrefillWithFiller() ? TempRegister() : NULL;
    828     LAllocate* result =
    829         new (zone()) LAllocate(context, size, temp1, temp2, temp3);
    830     return AssignPointerMap(DefineAsRegister(result));
    831   }
    832 }
    833 
    834 
    835 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
    836   LOperand* function = UseFixed(instr->function(), x1);
    837   LOperand* receiver = UseFixed(instr->receiver(), x0);
    838   LOperand* length = UseFixed(instr->length(), x2);
    839   LOperand* elements = UseFixed(instr->elements(), x3);
    840   LApplyArguments* result = new(zone()) LApplyArguments(function,
    841                                                         receiver,
    842                                                         length,
    843                                                         elements);
    844   return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
    845 }
    846 
    847 
    848 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* instr) {
    849   info()->MarkAsRequiresFrame();
    850   LOperand* temp = instr->from_inlined() ? NULL : TempRegister();
    851   return DefineAsRegister(new(zone()) LArgumentsElements(temp));
    852 }
    853 
    854 
    855 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* instr) {
    856   info()->MarkAsRequiresFrame();
    857   LOperand* value = UseRegisterAtStart(instr->value());
    858   return DefineAsRegister(new(zone()) LArgumentsLength(value));
    859 }
    860 
    861 
    862 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
    863   // There are no real uses of the arguments object.
    864   // arguments.length and element access are supported directly on
    865   // stack arguments, and any real arguments object use causes a bailout.
    866   // So this value is never used.
    867   return NULL;
    868 }
    869 
    870 
    871 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) {
    872   if (instr->representation().IsSmiOrInteger32()) {
    873     DCHECK(instr->left()->representation().Equals(instr->representation()));
    874     DCHECK(instr->right()->representation().Equals(instr->representation()));
    875     DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32));
    876 
    877     LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
    878     if (shifted_operation != NULL) {
    879       return shifted_operation;
    880     }
    881 
    882     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
    883     LOperand* right =
    884         UseRegisterOrConstantAtStart(instr->BetterRightOperand());
    885     return instr->representation().IsSmi() ?
    886         DefineAsRegister(new(zone()) LBitS(left, right)) :
    887         DefineAsRegister(new(zone()) LBitI(left, right));
    888   } else {
    889     return DoArithmeticT(instr->op(), instr);
    890   }
    891 }
    892 
    893 
    894 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
    895   // V8 expects a label to be generated for each basic block.
    896   // This is used in some places like LAllocator::IsBlockBoundary
    897   // in lithium-allocator.cc
    898   return new(zone()) LLabel(instr->block());
    899 }
    900 
    901 
    902 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
    903   if (!FLAG_debug_code && instr->skip_check()) return NULL;
    904   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
    905   LOperand* length = !index->IsConstantOperand()
    906       ? UseRegisterOrConstantAtStart(instr->length())
    907       : UseRegisterAtStart(instr->length());
    908   LInstruction* result = new(zone()) LBoundsCheck(index, length);
    909   if (!FLAG_debug_code || !instr->skip_check()) {
    910     result = AssignEnvironment(result);
    911   }
    912   return result;
    913 }
    914 
    915 
    916 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) {
    917   HValue* value = instr->value();
    918   Representation r = value->representation();
    919   HType type = value->type();
    920 
    921   if (r.IsInteger32() || r.IsSmi() || r.IsDouble()) {
    922     // These representations have simple checks that cannot deoptimize.
    923     return new(zone()) LBranch(UseRegister(value), NULL, NULL);
    924   } else {
    925     DCHECK(r.IsTagged());
    926     if (type.IsBoolean() || type.IsSmi() || type.IsJSArray() ||
    927         type.IsHeapNumber()) {
    928       // These types have simple checks that cannot deoptimize.
    929       return new(zone()) LBranch(UseRegister(value), NULL, NULL);
    930     }
    931 
    932     if (type.IsString()) {
    933       // This type cannot deoptimize, but needs a scratch register.
    934       return new(zone()) LBranch(UseRegister(value), TempRegister(), NULL);
    935     }
    936 
    937     ToBooleanHints expected = instr->expected_input_types();
    938     bool needs_temps = (expected & ToBooleanHint::kNeedsMap) ||
    939                        expected == ToBooleanHint::kNone;
    940     LOperand* temp1 = needs_temps ? TempRegister() : NULL;
    941     LOperand* temp2 = needs_temps ? TempRegister() : NULL;
    942 
    943     if (expected == ToBooleanHint::kAny || expected == ToBooleanHint::kNone) {
    944       // The generic case cannot deoptimize because it already supports every
    945       // possible input type.
    946       DCHECK(needs_temps);
    947       return new(zone()) LBranch(UseRegister(value), temp1, temp2);
    948     } else {
    949       return AssignEnvironment(
    950           new(zone()) LBranch(UseRegister(value), temp1, temp2));
    951     }
    952   }
    953 }
    954 
    955 
    956 LInstruction* LChunkBuilder::DoCallWithDescriptor(
    957     HCallWithDescriptor* instr) {
    958   CallInterfaceDescriptor descriptor = instr->descriptor();
    959   DCHECK_EQ(descriptor.GetParameterCount() +
    960                 LCallWithDescriptor::kImplicitRegisterParameterCount,
    961             instr->OperandCount());
    962 
    963   LOperand* target = UseRegisterOrConstantAtStart(instr->target());
    964   ZoneList<LOperand*> ops(instr->OperandCount(), zone());
    965   // Target
    966   ops.Add(target, zone());
    967   // Context
    968   LOperand* op = UseFixed(instr->OperandAt(1), cp);
    969   ops.Add(op, zone());
    970   // Load register parameters.
    971   int i = 0;
    972   for (; i < descriptor.GetRegisterParameterCount(); i++) {
    973     op = UseFixed(instr->OperandAt(
    974                       i + LCallWithDescriptor::kImplicitRegisterParameterCount),
    975                   descriptor.GetRegisterParameter(i));
    976     ops.Add(op, zone());
    977   }
    978   // Push stack parameters.
    979   if (i < descriptor.GetParameterCount()) {
    980     int argc = descriptor.GetParameterCount() - i;
    981     AddInstruction(new (zone()) LPreparePushArguments(argc), instr);
    982     LPushArguments* push_args = new (zone()) LPushArguments(zone());
    983     for (; i < descriptor.GetParameterCount(); i++) {
    984       if (push_args->ShouldSplitPush()) {
    985         AddInstruction(push_args, instr);
    986         push_args = new (zone()) LPushArguments(zone());
    987       }
    988       op = UseRegisterAtStart(instr->OperandAt(
    989           i + LCallWithDescriptor::kImplicitRegisterParameterCount));
    990       push_args->AddArgument(op);
    991     }
    992     AddInstruction(push_args, instr);
    993   }
    994 
    995   LCallWithDescriptor* result = new(zone()) LCallWithDescriptor(descriptor,
    996                                                                 ops,
    997                                                                 zone());
    998   if (instr->syntactic_tail_call_mode() == TailCallMode::kAllow) {
    999     result->MarkAsSyntacticTailCall();
   1000   }
   1001   return MarkAsCall(DefineFixed(result, x0), instr);
   1002 }
   1003 
   1004 
   1005 LInstruction* LChunkBuilder::DoCallNewArray(HCallNewArray* instr) {
   1006   LOperand* context = UseFixed(instr->context(), cp);
   1007   // The call to ArrayConstructCode will expect the constructor to be in x1.
   1008   LOperand* constructor = UseFixed(instr->constructor(), x1);
   1009   LCallNewArray* result = new(zone()) LCallNewArray(context, constructor);
   1010   return MarkAsCall(DefineFixed(result, x0), instr);
   1011 }
   1012 
   1013 
   1014 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
   1015   LOperand* context = UseFixed(instr->context(), cp);
   1016   return MarkAsCall(DefineFixed(new(zone()) LCallRuntime(context), x0), instr);
   1017 }
   1018 
   1019 
   1020 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
   1021   instr->ReplayEnvironment(current_block_->last_environment());
   1022 
   1023   // There are no real uses of a captured object.
   1024   return NULL;
   1025 }
   1026 
   1027 
   1028 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
   1029   Representation from = instr->from();
   1030   Representation to = instr->to();
   1031   HValue* val = instr->value();
   1032   if (from.IsSmi()) {
   1033     if (to.IsTagged()) {
   1034       LOperand* value = UseRegister(val);
   1035       return DefineSameAsFirst(new(zone()) LDummyUse(value));
   1036     }
   1037     from = Representation::Tagged();
   1038   }
   1039   if (from.IsTagged()) {
   1040     if (to.IsDouble()) {
   1041       LOperand* value = UseRegister(val);
   1042       LOperand* temp = TempRegister();
   1043       LInstruction* result =
   1044           DefineAsRegister(new(zone()) LNumberUntagD(value, temp));
   1045       if (!val->representation().IsSmi()) result = AssignEnvironment(result);
   1046       return result;
   1047     } else if (to.IsSmi()) {
   1048       LOperand* value = UseRegister(val);
   1049       if (val->type().IsSmi()) {
   1050         return DefineSameAsFirst(new(zone()) LDummyUse(value));
   1051       }
   1052       return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
   1053     } else {
   1054       DCHECK(to.IsInteger32());
   1055       if (val->type().IsSmi() || val->representation().IsSmi()) {
   1056         LOperand* value = UseRegisterAtStart(val);
   1057         return DefineAsRegister(new(zone()) LSmiUntag(value, false));
   1058       } else {
   1059         LOperand* value = UseRegister(val);
   1060         LOperand* temp1 = TempRegister();
   1061         LOperand* temp2 = instr->CanTruncateToInt32()
   1062             ? NULL : TempDoubleRegister();
   1063         LInstruction* result =
   1064             DefineAsRegister(new(zone()) LTaggedToI(value, temp1, temp2));
   1065         if (!val->representation().IsSmi()) result = AssignEnvironment(result);
   1066         return result;
   1067       }
   1068     }
   1069   } else if (from.IsDouble()) {
   1070     if (to.IsTagged()) {
   1071       info()->MarkAsDeferredCalling();
   1072       LOperand* value = UseRegister(val);
   1073       LOperand* temp1 = TempRegister();
   1074       LOperand* temp2 = TempRegister();
   1075       LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
   1076       return AssignPointerMap(DefineAsRegister(result));
   1077     } else {
   1078       DCHECK(to.IsSmi() || to.IsInteger32());
   1079       if (instr->CanTruncateToInt32()) {
   1080         LOperand* value = UseRegister(val);
   1081         return DefineAsRegister(new(zone()) LTruncateDoubleToIntOrSmi(value));
   1082       } else {
   1083         LOperand* value = UseRegister(val);
   1084         LDoubleToIntOrSmi* result = new(zone()) LDoubleToIntOrSmi(value);
   1085         return AssignEnvironment(DefineAsRegister(result));
   1086       }
   1087     }
   1088   } else if (from.IsInteger32()) {
   1089     info()->MarkAsDeferredCalling();
   1090     if (to.IsTagged()) {
   1091       if (val->CheckFlag(HInstruction::kUint32)) {
   1092         LOperand* value = UseRegister(val);
   1093         LNumberTagU* result =
   1094             new(zone()) LNumberTagU(value, TempRegister(), TempRegister());
   1095         return AssignPointerMap(DefineAsRegister(result));
   1096       } else {
   1097         STATIC_ASSERT((kMinInt == Smi::kMinValue) &&
   1098                       (kMaxInt == Smi::kMaxValue));
   1099         LOperand* value = UseRegisterAtStart(val);
   1100         return DefineAsRegister(new(zone()) LSmiTag(value));
   1101       }
   1102     } else if (to.IsSmi()) {
   1103       LOperand* value = UseRegisterAtStart(val);
   1104       LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value));
   1105       if (instr->CheckFlag(HValue::kCanOverflow)) {
   1106         result = AssignEnvironment(result);
   1107       }
   1108       return result;
   1109     } else {
   1110       DCHECK(to.IsDouble());
   1111       if (val->CheckFlag(HInstruction::kUint32)) {
   1112         return DefineAsRegister(
   1113             new(zone()) LUint32ToDouble(UseRegisterAtStart(val)));
   1114       } else {
   1115         return DefineAsRegister(
   1116             new(zone()) LInteger32ToDouble(UseRegisterAtStart(val)));
   1117       }
   1118     }
   1119   }
   1120   UNREACHABLE();
   1121   return NULL;
   1122 }
   1123 
   1124 
   1125 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
   1126   LOperand* value = UseRegisterAtStart(instr->value());
   1127   return AssignEnvironment(new(zone()) LCheckValue(value));
   1128 }
   1129 
   1130 
   1131 LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
   1132     HCheckArrayBufferNotNeutered* instr) {
   1133   LOperand* view = UseRegisterAtStart(instr->value());
   1134   LCheckArrayBufferNotNeutered* result =
   1135       new (zone()) LCheckArrayBufferNotNeutered(view);
   1136   return AssignEnvironment(result);
   1137 }
   1138 
   1139 
   1140 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   1141   LOperand* value = UseRegisterAtStart(instr->value());
   1142   LOperand* temp = TempRegister();
   1143   LInstruction* result = new(zone()) LCheckInstanceType(value, temp);
   1144   return AssignEnvironment(result);
   1145 }
   1146 
   1147 
   1148 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
   1149   if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
   1150   LOperand* value = UseRegisterAtStart(instr->value());
   1151   LOperand* temp = TempRegister();
   1152   LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value, temp));
   1153   if (instr->HasMigrationTarget()) {
   1154     info()->MarkAsDeferredCalling();
   1155     result = AssignPointerMap(result);
   1156   }
   1157   return result;
   1158 }
   1159 
   1160 
   1161 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
   1162   LOperand* value = UseRegisterAtStart(instr->value());
   1163   LInstruction* result = new(zone()) LCheckNonSmi(value);
   1164   if (!instr->value()->type().IsHeapObject()) {
   1165     result = AssignEnvironment(result);
   1166   }
   1167   return result;
   1168 }
   1169 
   1170 
   1171 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
   1172   LOperand* value = UseRegisterAtStart(instr->value());
   1173   return AssignEnvironment(new(zone()) LCheckSmi(value));
   1174 }
   1175 
   1176 
   1177 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
   1178   HValue* value = instr->value();
   1179   Representation input_rep = value->representation();
   1180   LOperand* reg = UseRegister(value);
   1181   if (input_rep.IsDouble()) {
   1182     return DefineAsRegister(new(zone()) LClampDToUint8(reg));
   1183   } else if (input_rep.IsInteger32()) {
   1184     return DefineAsRegister(new(zone()) LClampIToUint8(reg));
   1185   } else {
   1186     DCHECK(input_rep.IsSmiOrTagged());
   1187     return AssignEnvironment(
   1188         DefineAsRegister(new(zone()) LClampTToUint8(reg,
   1189                                                     TempDoubleRegister())));
   1190   }
   1191 }
   1192 
   1193 
   1194 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
   1195     HClassOfTestAndBranch* instr) {
   1196   DCHECK(instr->value()->representation().IsTagged());
   1197   LOperand* value = UseRegisterAtStart(instr->value());
   1198   return new(zone()) LClassOfTestAndBranch(value,
   1199                                            TempRegister(),
   1200                                            TempRegister());
   1201 }
   1202 
   1203 
   1204 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
   1205     HCompareNumericAndBranch* instr) {
   1206   Representation r = instr->representation();
   1207   if (r.IsSmiOrInteger32()) {
   1208     DCHECK(instr->left()->representation().Equals(r));
   1209     DCHECK(instr->right()->representation().Equals(r));
   1210     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
   1211     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
   1212     return new(zone()) LCompareNumericAndBranch(left, right);
   1213   } else {
   1214     DCHECK(r.IsDouble());
   1215     DCHECK(instr->left()->representation().IsDouble());
   1216     DCHECK(instr->right()->representation().IsDouble());
   1217     if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
   1218       LOperand* left = UseConstant(instr->left());
   1219       LOperand* right = UseConstant(instr->right());
   1220       return new(zone()) LCompareNumericAndBranch(left, right);
   1221     }
   1222     LOperand* left = UseRegisterAtStart(instr->left());
   1223     LOperand* right = UseRegisterAtStart(instr->right());
   1224     return new(zone()) LCompareNumericAndBranch(left, right);
   1225   }
   1226 }
   1227 
   1228 
   1229 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
   1230   DCHECK(instr->left()->representation().IsTagged());
   1231   DCHECK(instr->right()->representation().IsTagged());
   1232   LOperand* context = UseFixed(instr->context(), cp);
   1233   LOperand* left = UseFixed(instr->left(), x1);
   1234   LOperand* right = UseFixed(instr->right(), x0);
   1235   LCmpT* result = new(zone()) LCmpT(context, left, right);
   1236   return MarkAsCall(DefineFixed(result, x0), instr);
   1237 }
   1238 
   1239 
   1240 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
   1241     HCompareHoleAndBranch* instr) {
   1242   LOperand* value = UseRegister(instr->value());
   1243   if (instr->representation().IsTagged()) {
   1244     return new(zone()) LCmpHoleAndBranchT(value);
   1245   } else {
   1246     LOperand* temp = TempRegister();
   1247     return new(zone()) LCmpHoleAndBranchD(value, temp);
   1248   }
   1249 }
   1250 
   1251 
   1252 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
   1253     HCompareObjectEqAndBranch* instr) {
   1254   LOperand* left = UseRegisterAtStart(instr->left());
   1255   LOperand* right = UseRegisterAtStart(instr->right());
   1256   return new(zone()) LCmpObjectEqAndBranch(left, right);
   1257 }
   1258 
   1259 
   1260 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
   1261   DCHECK(instr->value()->representation().IsTagged());
   1262   LOperand* value = UseRegisterAtStart(instr->value());
   1263   LOperand* temp = TempRegister();
   1264   return new(zone()) LCmpMapAndBranch(value, temp);
   1265 }
   1266 
   1267 
   1268 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   1269   Representation r = instr->representation();
   1270   if (r.IsSmi()) {
   1271     return DefineAsRegister(new(zone()) LConstantS);
   1272   } else if (r.IsInteger32()) {
   1273     return DefineAsRegister(new(zone()) LConstantI);
   1274   } else if (r.IsDouble()) {
   1275     return DefineAsRegister(new(zone()) LConstantD);
   1276   } else if (r.IsExternal()) {
   1277     return DefineAsRegister(new(zone()) LConstantE);
   1278   } else if (r.IsTagged()) {
   1279     return DefineAsRegister(new(zone()) LConstantT);
   1280   } else {
   1281     UNREACHABLE();
   1282     return NULL;
   1283   }
   1284 }
   1285 
   1286 
   1287 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
   1288   if (instr->HasNoUses()) return NULL;
   1289 
   1290   if (info()->IsStub()) {
   1291     return DefineFixed(new(zone()) LContext, cp);
   1292   }
   1293 
   1294   return DefineAsRegister(new(zone()) LContext);
   1295 }
   1296 
   1297 
   1298 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
   1299   return new(zone()) LDebugBreak();
   1300 }
   1301 
   1302 
   1303 LInstruction* LChunkBuilder::DoDeclareGlobals(HDeclareGlobals* instr) {
   1304   LOperand* context = UseFixed(instr->context(), cp);
   1305   return MarkAsCall(new(zone()) LDeclareGlobals(context), instr);
   1306 }
   1307 
   1308 
   1309 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
   1310   return AssignEnvironment(new(zone()) LDeoptimize);
   1311 }
   1312 
   1313 
   1314 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) {
   1315   DCHECK(instr->representation().IsInteger32());
   1316   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1317   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1318   LOperand* dividend = UseRegister(instr->left());
   1319   int32_t divisor = instr->right()->GetInteger32Constant();
   1320   LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
   1321           dividend, divisor));
   1322   if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
   1323       (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
   1324       (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
   1325        divisor != 1 && divisor != -1)) {
   1326     result = AssignEnvironment(result);
   1327   }
   1328   return result;
   1329 }
   1330 
   1331 
   1332 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
   1333   DCHECK(instr->representation().IsInteger32());
   1334   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1335   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1336   LOperand* dividend = UseRegister(instr->left());
   1337   int32_t divisor = instr->right()->GetInteger32Constant();
   1338   LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)
   1339       ? NULL : TempRegister();
   1340   LInstruction* result = DefineAsRegister(new(zone()) LDivByConstI(
   1341           dividend, divisor, temp));
   1342   if (divisor == 0 ||
   1343       (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
   1344       !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
   1345     result = AssignEnvironment(result);
   1346   }
   1347   return result;
   1348 }
   1349 
   1350 
   1351 LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) {
   1352   DCHECK(instr->representation().IsSmiOrInteger32());
   1353   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1354   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1355   LOperand* dividend = UseRegister(instr->left());
   1356   LOperand* divisor = UseRegister(instr->right());
   1357   LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)
   1358       ? NULL : TempRegister();
   1359   LInstruction* result =
   1360       DefineAsRegister(new(zone()) LDivI(dividend, divisor, temp));
   1361   if (!instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
   1362     result = AssignEnvironment(result);
   1363   }
   1364   return result;
   1365 }
   1366 
   1367 
   1368 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   1369   if (instr->representation().IsSmiOrInteger32()) {
   1370     if (instr->RightIsPowerOf2()) {
   1371       return DoDivByPowerOf2I(instr);
   1372     } else if (instr->right()->IsConstant()) {
   1373       return DoDivByConstI(instr);
   1374     } else {
   1375       return DoDivI(instr);
   1376     }
   1377   } else if (instr->representation().IsDouble()) {
   1378     return DoArithmeticD(Token::DIV, instr);
   1379   } else {
   1380     return DoArithmeticT(Token::DIV, instr);
   1381   }
   1382 }
   1383 
   1384 
   1385 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) {
   1386   return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value())));
   1387 }
   1388 
   1389 
   1390 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
   1391   HEnvironment* outer = current_block_->last_environment();
   1392   outer->set_ast_id(instr->ReturnId());
   1393   HConstant* undefined = graph()->GetConstantUndefined();
   1394   HEnvironment* inner = outer->CopyForInlining(
   1395       instr->closure(), instr->arguments_count(), instr->function(), undefined,
   1396       instr->inlining_kind(), instr->syntactic_tail_call_mode());
   1397   // Only replay binding of arguments object if it wasn't removed from graph.
   1398   if ((instr->arguments_var() != NULL) &&
   1399       instr->arguments_object()->IsLinked()) {
   1400     inner->Bind(instr->arguments_var(), instr->arguments_object());
   1401   }
   1402   inner->BindContext(instr->closure_context());
   1403   inner->set_entry(instr);
   1404   current_block_->UpdateEnvironment(inner);
   1405   return NULL;
   1406 }
   1407 
   1408 
   1409 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) {
   1410   UNREACHABLE();
   1411   return NULL;
   1412 }
   1413 
   1414 
   1415 LInstruction* LChunkBuilder::DoForceRepresentation(
   1416     HForceRepresentation* instr) {
   1417   // All HForceRepresentation instructions should be eliminated in the
   1418   // representation change phase of Hydrogen.
   1419   UNREACHABLE();
   1420   return NULL;
   1421 }
   1422 
   1423 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
   1424   return new(zone()) LGoto(instr->FirstSuccessor());
   1425 }
   1426 
   1427 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
   1428     HHasInstanceTypeAndBranch* instr) {
   1429   DCHECK(instr->value()->representation().IsTagged());
   1430   LOperand* value = UseRegisterAtStart(instr->value());
   1431   return new(zone()) LHasInstanceTypeAndBranch(value, TempRegister());
   1432 }
   1433 
   1434 
   1435 LInstruction* LChunkBuilder::DoInnerAllocatedObject(
   1436     HInnerAllocatedObject* instr) {
   1437   LOperand* base_object = UseRegisterAtStart(instr->base_object());
   1438   LOperand* offset = UseRegisterOrConstantAtStart(instr->offset());
   1439   return DefineAsRegister(
   1440       new(zone()) LInnerAllocatedObject(base_object, offset));
   1441 }
   1442 
   1443 
   1444 LInstruction* LChunkBuilder::DoHasInPrototypeChainAndBranch(
   1445     HHasInPrototypeChainAndBranch* instr) {
   1446   LOperand* object = UseRegister(instr->object());
   1447   LOperand* prototype = UseRegister(instr->prototype());
   1448   LOperand* scratch1 = TempRegister();
   1449   LOperand* scratch2 = TempRegister();
   1450   LHasInPrototypeChainAndBranch* result = new (zone())
   1451       LHasInPrototypeChainAndBranch(object, prototype, scratch1, scratch2);
   1452   return AssignEnvironment(result);
   1453 }
   1454 
   1455 
   1456 LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
   1457   LOperand* context = UseFixed(instr->context(), cp);
   1458   // The function is required (by MacroAssembler::InvokeFunction) to be in x1.
   1459   LOperand* function = UseFixed(instr->function(), x1);
   1460   LInvokeFunction* result = new(zone()) LInvokeFunction(context, function);
   1461   if (instr->syntactic_tail_call_mode() == TailCallMode::kAllow) {
   1462     result->MarkAsSyntacticTailCall();
   1463   }
   1464   return MarkAsCall(DefineFixed(result, x0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
   1465 }
   1466 
   1467 
   1468 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
   1469   DCHECK(instr->value()->representation().IsTagged());
   1470   LOperand* value = UseRegisterAtStart(instr->value());
   1471   LOperand* temp = TempRegister();
   1472   return new(zone()) LIsStringAndBranch(value, temp);
   1473 }
   1474 
   1475 
   1476 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
   1477   DCHECK(instr->value()->representation().IsTagged());
   1478   return new(zone()) LIsSmiAndBranch(UseRegisterAtStart(instr->value()));
   1479 }
   1480 
   1481 
   1482 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
   1483     HIsUndetectableAndBranch* instr) {
   1484   DCHECK(instr->value()->representation().IsTagged());
   1485   LOperand* value = UseRegisterAtStart(instr->value());
   1486   return new(zone()) LIsUndetectableAndBranch(value, TempRegister());
   1487 }
   1488 
   1489 
   1490 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
   1491   LInstruction* pop = NULL;
   1492   HEnvironment* env = current_block_->last_environment();
   1493 
   1494   if (env->entry()->arguments_pushed()) {
   1495     int argument_count = env->arguments_environment()->parameter_count();
   1496     pop = new(zone()) LDrop(argument_count);
   1497     DCHECK(instr->argument_delta() == -argument_count);
   1498   }
   1499 
   1500   HEnvironment* outer =
   1501       current_block_->last_environment()->DiscardInlined(false);
   1502   current_block_->UpdateEnvironment(outer);
   1503 
   1504   return pop;
   1505 }
   1506 
   1507 
   1508 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   1509   LOperand* context = UseRegisterAtStart(instr->value());
   1510   LInstruction* result =
   1511       DefineAsRegister(new(zone()) LLoadContextSlot(context));
   1512   if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
   1513     result = AssignEnvironment(result);
   1514   }
   1515   return result;
   1516 }
   1517 
   1518 
   1519 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
   1520     HLoadFunctionPrototype* instr) {
   1521   LOperand* function = UseRegister(instr->function());
   1522   LOperand* temp = TempRegister();
   1523   return AssignEnvironment(DefineAsRegister(
   1524       new(zone()) LLoadFunctionPrototype(function, temp)));
   1525 }
   1526 
   1527 
   1528 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   1529   DCHECK(instr->key()->representation().IsSmiOrInteger32());
   1530   ElementsKind elements_kind = instr->elements_kind();
   1531   LOperand* elements = UseRegister(instr->elements());
   1532   LOperand* key = UseRegisterOrConstant(instr->key());
   1533 
   1534   if (!instr->is_fixed_typed_array()) {
   1535     if (instr->representation().IsDouble()) {
   1536       LOperand* temp = (!instr->key()->IsConstant() ||
   1537                         instr->RequiresHoleCheck())
   1538              ? TempRegister()
   1539              : NULL;
   1540       LInstruction* result = DefineAsRegister(
   1541           new (zone()) LLoadKeyedFixedDouble(elements, key, temp));
   1542       if (instr->RequiresHoleCheck()) {
   1543         result = AssignEnvironment(result);
   1544       }
   1545       return result;
   1546     } else {
   1547       DCHECK(instr->representation().IsSmiOrTagged() ||
   1548              instr->representation().IsInteger32());
   1549       LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister();
   1550       LInstruction* result =
   1551           DefineAsRegister(new (zone()) LLoadKeyedFixed(elements, key, temp));
   1552       if (instr->RequiresHoleCheck() ||
   1553           (instr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED &&
   1554            info()->IsStub())) {
   1555         result = AssignEnvironment(result);
   1556       }
   1557       return result;
   1558     }
   1559   } else {
   1560     DCHECK((instr->representation().IsInteger32() &&
   1561             !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
   1562            (instr->representation().IsDouble() &&
   1563             IsDoubleOrFloatElementsKind(instr->elements_kind())));
   1564 
   1565     LOperand* temp = instr->key()->IsConstant() ? NULL : TempRegister();
   1566     LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
   1567     LInstruction* result = DefineAsRegister(new (zone()) LLoadKeyedExternal(
   1568         elements, key, backing_store_owner, temp));
   1569     if (elements_kind == UINT32_ELEMENTS &&
   1570         !instr->CheckFlag(HInstruction::kUint32)) {
   1571       result = AssignEnvironment(result);
   1572     }
   1573     return result;
   1574   }
   1575 }
   1576 
   1577 
   1578 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
   1579   LOperand* object = UseRegisterAtStart(instr->object());
   1580   return DefineAsRegister(new(zone()) LLoadNamedField(object));
   1581 }
   1582 
   1583 
   1584 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
   1585   return DefineAsRegister(new(zone()) LLoadRoot);
   1586 }
   1587 
   1588 
   1589 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
   1590   DCHECK(instr->representation().IsInteger32());
   1591   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1592   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1593   LOperand* dividend = UseRegisterAtStart(instr->left());
   1594   int32_t divisor = instr->right()->GetInteger32Constant();
   1595   LInstruction* result = DefineAsRegister(new(zone()) LFlooringDivByPowerOf2I(
   1596           dividend, divisor));
   1597   if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
   1598       (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
   1599     result = AssignEnvironment(result);
   1600   }
   1601   return result;
   1602 }
   1603 
   1604 
   1605 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
   1606   DCHECK(instr->representation().IsInteger32());
   1607   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1608   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1609   LOperand* dividend = UseRegister(instr->left());
   1610   int32_t divisor = instr->right()->GetInteger32Constant();
   1611   LOperand* temp =
   1612       ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
   1613        (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
   1614       NULL : TempRegister();
   1615   LInstruction* result = DefineAsRegister(
   1616       new(zone()) LFlooringDivByConstI(dividend, divisor, temp));
   1617   if (divisor == 0 ||
   1618       (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
   1619     result = AssignEnvironment(result);
   1620   }
   1621   return result;
   1622 }
   1623 
   1624 
   1625 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
   1626   LOperand* dividend = UseRegister(instr->left());
   1627   LOperand* divisor = UseRegister(instr->right());
   1628   LOperand* remainder = TempRegister();
   1629   LInstruction* result =
   1630       DefineAsRegister(new(zone()) LFlooringDivI(dividend, divisor, remainder));
   1631   return AssignEnvironment(result);
   1632 }
   1633 
   1634 
   1635 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
   1636   if (instr->RightIsPowerOf2()) {
   1637     return DoFlooringDivByPowerOf2I(instr);
   1638   } else if (instr->right()->IsConstant()) {
   1639     return DoFlooringDivByConstI(instr);
   1640   } else {
   1641     return DoFlooringDivI(instr);
   1642   }
   1643 }
   1644 
   1645 
   1646 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
   1647   LOperand* left = NULL;
   1648   LOperand* right = NULL;
   1649   if (instr->representation().IsSmiOrInteger32()) {
   1650     DCHECK(instr->left()->representation().Equals(instr->representation()));
   1651     DCHECK(instr->right()->representation().Equals(instr->representation()));
   1652     left = UseRegisterAtStart(instr->BetterLeftOperand());
   1653     right = UseRegisterOrConstantAtStart(instr->BetterRightOperand());
   1654   } else {
   1655     DCHECK(instr->representation().IsDouble());
   1656     DCHECK(instr->left()->representation().IsDouble());
   1657     DCHECK(instr->right()->representation().IsDouble());
   1658     left = UseRegisterAtStart(instr->left());
   1659     right = UseRegisterAtStart(instr->right());
   1660   }
   1661   return DefineAsRegister(new(zone()) LMathMinMax(left, right));
   1662 }
   1663 
   1664 
   1665 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
   1666   DCHECK(instr->representation().IsInteger32());
   1667   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1668   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1669   LOperand* dividend = UseRegisterAtStart(instr->left());
   1670   int32_t divisor = instr->right()->GetInteger32Constant();
   1671   LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
   1672           dividend, divisor));
   1673   if (instr->CheckFlag(HValue::kLeftCanBeNegative) &&
   1674       instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1675     result = AssignEnvironment(result);
   1676   }
   1677   return result;
   1678 }
   1679 
   1680 
   1681 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
   1682   DCHECK(instr->representation().IsInteger32());
   1683   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1684   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1685   LOperand* dividend = UseRegister(instr->left());
   1686   int32_t divisor = instr->right()->GetInteger32Constant();
   1687   LOperand* temp = TempRegister();
   1688   LInstruction* result = DefineAsRegister(new(zone()) LModByConstI(
   1689           dividend, divisor, temp));
   1690   if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1691     result = AssignEnvironment(result);
   1692   }
   1693   return result;
   1694 }
   1695 
   1696 
   1697 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
   1698   DCHECK(instr->representation().IsSmiOrInteger32());
   1699   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1700   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1701   LOperand* dividend = UseRegister(instr->left());
   1702   LOperand* divisor = UseRegister(instr->right());
   1703   LInstruction* result = DefineAsRegister(new(zone()) LModI(dividend, divisor));
   1704   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
   1705       instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1706     result = AssignEnvironment(result);
   1707   }
   1708   return result;
   1709 }
   1710 
   1711 
   1712 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
   1713   if (instr->representation().IsSmiOrInteger32()) {
   1714     if (instr->RightIsPowerOf2()) {
   1715       return DoModByPowerOf2I(instr);
   1716     } else if (instr->right()->IsConstant()) {
   1717       return DoModByConstI(instr);
   1718     } else {
   1719       return DoModI(instr);
   1720     }
   1721   } else if (instr->representation().IsDouble()) {
   1722     return DoArithmeticD(Token::MOD, instr);
   1723   } else {
   1724     return DoArithmeticT(Token::MOD, instr);
   1725   }
   1726 }
   1727 
   1728 
   1729 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
   1730   if (instr->representation().IsSmiOrInteger32()) {
   1731     DCHECK(instr->left()->representation().Equals(instr->representation()));
   1732     DCHECK(instr->right()->representation().Equals(instr->representation()));
   1733 
   1734     bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
   1735     bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
   1736 
   1737     HValue* least_const = instr->BetterLeftOperand();
   1738     HValue* most_const = instr->BetterRightOperand();
   1739 
   1740     // LMulConstI can handle a subset of constants:
   1741     //  With support for overflow detection:
   1742     //    -1, 0, 1, 2
   1743     //    2^n, -(2^n)
   1744     //  Without support for overflow detection:
   1745     //    2^n + 1, -(2^n - 1)
   1746     if (most_const->IsConstant()) {
   1747       int32_t constant = HConstant::cast(most_const)->Integer32Value();
   1748       bool small_constant = (constant >= -1) && (constant <= 2);
   1749       bool end_range_constant = (constant <= -kMaxInt) || (constant == kMaxInt);
   1750       int32_t constant_abs = Abs(constant);
   1751 
   1752       if (!end_range_constant &&
   1753           (small_constant || (base::bits::IsPowerOfTwo32(constant_abs)) ||
   1754            (!can_overflow && (base::bits::IsPowerOfTwo32(constant_abs + 1) ||
   1755                               base::bits::IsPowerOfTwo32(constant_abs - 1))))) {
   1756         LConstantOperand* right = UseConstant(most_const);
   1757         bool need_register =
   1758             base::bits::IsPowerOfTwo32(constant_abs) && !small_constant;
   1759         LOperand* left = need_register ? UseRegister(least_const)
   1760                                        : UseRegisterAtStart(least_const);
   1761         LInstruction* result =
   1762             DefineAsRegister(new(zone()) LMulConstIS(left, right));
   1763         if ((bailout_on_minus_zero && constant <= 0) ||
   1764             (can_overflow && constant != 1 &&
   1765              base::bits::IsPowerOfTwo32(constant_abs))) {
   1766           result = AssignEnvironment(result);
   1767         }
   1768         return result;
   1769       }
   1770     }
   1771 
   1772     // LMulI/S can handle all cases, but it requires that a register is
   1773     // allocated for the second operand.
   1774     LOperand* left = UseRegisterAtStart(least_const);
   1775     LOperand* right = UseRegisterAtStart(most_const);
   1776     LInstruction* result = instr->representation().IsSmi()
   1777         ? DefineAsRegister(new(zone()) LMulS(left, right))
   1778         : DefineAsRegister(new(zone()) LMulI(left, right));
   1779     if ((bailout_on_minus_zero && least_const != most_const) || can_overflow) {
   1780       result = AssignEnvironment(result);
   1781     }
   1782     return result;
   1783   } else if (instr->representation().IsDouble()) {
   1784     return DoArithmeticD(Token::MUL, instr);
   1785   } else {
   1786     return DoArithmeticT(Token::MUL, instr);
   1787   }
   1788 }
   1789 
   1790 
   1791 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
   1792   DCHECK(argument_count_ == 0);
   1793   allocator_->MarkAsOsrEntry();
   1794   current_block_->last_environment()->set_ast_id(instr->ast_id());
   1795   return AssignEnvironment(new(zone()) LOsrEntry);
   1796 }
   1797 
   1798 
   1799 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
   1800   LParameter* result = new(zone()) LParameter;
   1801   if (instr->kind() == HParameter::STACK_PARAMETER) {
   1802     int spill_index = chunk_->GetParameterStackSlot(instr->index());
   1803     return DefineAsSpilled(result, spill_index);
   1804   } else {
   1805     DCHECK(info()->IsStub());
   1806     CallInterfaceDescriptor descriptor = graph()->descriptor();
   1807     int index = static_cast<int>(instr->index());
   1808     Register reg = descriptor.GetRegisterParameter(index);
   1809     return DefineFixed(result, reg);
   1810   }
   1811 }
   1812 
   1813 
   1814 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
   1815   DCHECK(instr->representation().IsDouble());
   1816   // We call a C function for double power. It can't trigger a GC.
   1817   // We need to use fixed result register for the call.
   1818   Representation exponent_type = instr->right()->representation();
   1819   DCHECK(instr->left()->representation().IsDouble());
   1820   LOperand* left = UseFixedDouble(instr->left(), d0);
   1821   LOperand* right;
   1822   if (exponent_type.IsInteger32()) {
   1823     right = UseFixed(instr->right(), MathPowIntegerDescriptor::exponent());
   1824   } else if (exponent_type.IsDouble()) {
   1825     right = UseFixedDouble(instr->right(), d1);
   1826   } else {
   1827     right = UseFixed(instr->right(), MathPowTaggedDescriptor::exponent());
   1828   }
   1829   LPower* result = new(zone()) LPower(left, right);
   1830   return MarkAsCall(DefineFixedDouble(result, d0),
   1831                     instr,
   1832                     CAN_DEOPTIMIZE_EAGERLY);
   1833 }
   1834 
   1835 
   1836 LInstruction* LChunkBuilder::DoPushArguments(HPushArguments* instr) {
   1837   int argc = instr->OperandCount();
   1838   AddInstruction(new(zone()) LPreparePushArguments(argc), instr);
   1839 
   1840   LPushArguments* push_args = new(zone()) LPushArguments(zone());
   1841 
   1842   for (int i = 0; i < argc; ++i) {
   1843     if (push_args->ShouldSplitPush()) {
   1844       AddInstruction(push_args, instr);
   1845       push_args = new(zone()) LPushArguments(zone());
   1846     }
   1847     push_args->AddArgument(UseRegister(instr->argument(i)));
   1848   }
   1849 
   1850   return push_args;
   1851 }
   1852 
   1853 
   1854 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   1855   LOperand* context = info()->IsStub()
   1856       ? UseFixed(instr->context(), cp)
   1857       : NULL;
   1858   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
   1859   return new(zone()) LReturn(UseFixed(instr->value(), x0), context,
   1860                              parameter_count);
   1861 }
   1862 
   1863 
   1864 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
   1865   LOperand* string = UseRegisterAtStart(instr->string());
   1866   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
   1867   LOperand* temp = TempRegister();
   1868   LSeqStringGetChar* result =
   1869       new(zone()) LSeqStringGetChar(string, index, temp);
   1870   return DefineAsRegister(result);
   1871 }
   1872 
   1873 
   1874 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
   1875   LOperand* string = UseRegister(instr->string());
   1876   LOperand* index = FLAG_debug_code
   1877       ? UseRegister(instr->index())
   1878       : UseRegisterOrConstant(instr->index());
   1879   LOperand* value = UseRegister(instr->value());
   1880   LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL;
   1881   LOperand* temp = TempRegister();
   1882   LSeqStringSetChar* result =
   1883       new(zone()) LSeqStringSetChar(context, string, index, value, temp);
   1884   return DefineAsRegister(result);
   1885 }
   1886 
   1887 
   1888 HBitwiseBinaryOperation* LChunkBuilder::CanTransformToShiftedOp(HValue* val,
   1889                                                                 HValue** left) {
   1890   if (!val->representation().IsInteger32()) return NULL;
   1891   if (!(val->IsBitwise() || val->IsAdd() || val->IsSub())) return NULL;
   1892 
   1893   HBinaryOperation* hinstr = HBinaryOperation::cast(val);
   1894   HValue* hleft = hinstr->left();
   1895   HValue* hright = hinstr->right();
   1896   DCHECK(hleft->representation().Equals(hinstr->representation()));
   1897   DCHECK(hright->representation().Equals(hinstr->representation()));
   1898 
   1899   if (hleft == hright) return NULL;
   1900 
   1901   if ((hright->IsConstant() &&
   1902        LikelyFitsImmField(hinstr, HConstant::cast(hright)->Integer32Value())) ||
   1903       (hinstr->IsCommutative() && hleft->IsConstant() &&
   1904        LikelyFitsImmField(hinstr, HConstant::cast(hleft)->Integer32Value()))) {
   1905     // The constant operand will likely fit in the immediate field. We are
   1906     // better off with
   1907     //     lsl x8, x9, #imm
   1908     //     add x0, x8, #imm2
   1909     // than with
   1910     //     mov x16, #imm2
   1911     //     add x0, x16, x9 LSL #imm
   1912     return NULL;
   1913   }
   1914 
   1915   HBitwiseBinaryOperation* shift = NULL;
   1916   // TODO(aleram): We will miss situations where a shift operation is used by
   1917   // different instructions both as a left and right operands.
   1918   if (hright->IsBitwiseBinaryShift() &&
   1919       HBitwiseBinaryOperation::cast(hright)->right()->IsConstant()) {
   1920     shift = HBitwiseBinaryOperation::cast(hright);
   1921     if (left != NULL) {
   1922       *left = hleft;
   1923     }
   1924   } else if (hinstr->IsCommutative() &&
   1925              hleft->IsBitwiseBinaryShift() &&
   1926              HBitwiseBinaryOperation::cast(hleft)->right()->IsConstant()) {
   1927     shift = HBitwiseBinaryOperation::cast(hleft);
   1928     if (left != NULL) {
   1929       *left = hright;
   1930     }
   1931   } else {
   1932     return NULL;
   1933   }
   1934 
   1935   if ((JSShiftAmountFromHConstant(shift->right()) == 0) && shift->IsShr()) {
   1936     // Shifts right by zero can deoptimize.
   1937     return NULL;
   1938   }
   1939 
   1940   return shift;
   1941 }
   1942 
   1943 
   1944 bool LChunkBuilder::ShiftCanBeOptimizedAway(HBitwiseBinaryOperation* shift) {
   1945   if (!shift->representation().IsInteger32()) {
   1946     return false;
   1947   }
   1948   for (HUseIterator it(shift->uses()); !it.Done(); it.Advance()) {
   1949     if (shift != CanTransformToShiftedOp(it.value())) {
   1950       return false;
   1951     }
   1952   }
   1953   return true;
   1954 }
   1955 
   1956 
   1957 LInstruction* LChunkBuilder::TryDoOpWithShiftedRightOperand(
   1958     HBinaryOperation* instr) {
   1959   HValue* left;
   1960   HBitwiseBinaryOperation* shift = CanTransformToShiftedOp(instr, &left);
   1961 
   1962   if ((shift != NULL) && ShiftCanBeOptimizedAway(shift)) {
   1963     return DoShiftedBinaryOp(instr, left, shift);
   1964   }
   1965   return NULL;
   1966 }
   1967 
   1968 
   1969 LInstruction* LChunkBuilder::DoShiftedBinaryOp(
   1970     HBinaryOperation* hinstr, HValue* hleft, HBitwiseBinaryOperation* hshift) {
   1971   DCHECK(hshift->IsBitwiseBinaryShift());
   1972   DCHECK(!hshift->IsShr() || (JSShiftAmountFromHConstant(hshift->right()) > 0));
   1973 
   1974   LTemplateResultInstruction<1>* res;
   1975   LOperand* left = UseRegisterAtStart(hleft);
   1976   LOperand* right = UseRegisterAtStart(hshift->left());
   1977   LOperand* shift_amount = UseConstant(hshift->right());
   1978   Shift shift_op;
   1979   switch (hshift->opcode()) {
   1980     case HValue::kShl: shift_op = LSL; break;
   1981     case HValue::kShr: shift_op = LSR; break;
   1982     case HValue::kSar: shift_op = ASR; break;
   1983     default: UNREACHABLE(); shift_op = NO_SHIFT;
   1984   }
   1985 
   1986   if (hinstr->IsBitwise()) {
   1987     res = new(zone()) LBitI(left, right, shift_op, shift_amount);
   1988   } else if (hinstr->IsAdd()) {
   1989     res = new(zone()) LAddI(left, right, shift_op, shift_amount);
   1990   } else {
   1991     DCHECK(hinstr->IsSub());
   1992     res = new(zone()) LSubI(left, right, shift_op, shift_amount);
   1993   }
   1994   if (hinstr->CheckFlag(HValue::kCanOverflow)) {
   1995     AssignEnvironment(res);
   1996   }
   1997   return DefineAsRegister(res);
   1998 }
   1999 
   2000 
   2001 LInstruction* LChunkBuilder::DoShift(Token::Value op,
   2002                                      HBitwiseBinaryOperation* instr) {
   2003   if (instr->representation().IsTagged()) {
   2004     return DoArithmeticT(op, instr);
   2005   }
   2006 
   2007   DCHECK(instr->representation().IsSmiOrInteger32());
   2008   DCHECK(instr->left()->representation().Equals(instr->representation()));
   2009   DCHECK(instr->right()->representation().Equals(instr->representation()));
   2010 
   2011   if (ShiftCanBeOptimizedAway(instr)) {
   2012     return NULL;
   2013   }
   2014 
   2015   LOperand* left = instr->representation().IsSmi()
   2016       ? UseRegister(instr->left())
   2017       : UseRegisterAtStart(instr->left());
   2018   LOperand* right = UseRegisterOrConstantAtStart(instr->right());
   2019 
   2020   // The only shift that can deoptimize is `left >>> 0`, where left is negative.
   2021   // In these cases, the result is a uint32 that is too large for an int32.
   2022   bool right_can_be_zero = !instr->right()->IsConstant() ||
   2023                            (JSShiftAmountFromHConstant(instr->right()) == 0);
   2024   bool can_deopt = false;
   2025   if ((op == Token::SHR) && right_can_be_zero) {
   2026     can_deopt = !instr->CheckFlag(HInstruction::kUint32);
   2027   }
   2028 
   2029   LInstruction* result;
   2030   if (instr->representation().IsInteger32()) {
   2031     result = DefineAsRegister(new (zone()) LShiftI(op, left, right, can_deopt));
   2032   } else {
   2033     DCHECK(instr->representation().IsSmi());
   2034     result = DefineAsRegister(new (zone()) LShiftS(op, left, right, can_deopt));
   2035   }
   2036 
   2037   return can_deopt ? AssignEnvironment(result) : result;
   2038 }
   2039 
   2040 
   2041 LInstruction* LChunkBuilder::DoRor(HRor* instr) {
   2042   return DoShift(Token::ROR, instr);
   2043 }
   2044 
   2045 
   2046 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
   2047   return DoShift(Token::SAR, instr);
   2048 }
   2049 
   2050 
   2051 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
   2052   return DoShift(Token::SHL, instr);
   2053 }
   2054 
   2055 
   2056 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
   2057   return DoShift(Token::SHR, instr);
   2058 }
   2059 
   2060 
   2061 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
   2062   instr->ReplayEnvironment(current_block_->last_environment());
   2063   return NULL;
   2064 }
   2065 
   2066 
   2067 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
   2068   if (instr->is_function_entry()) {
   2069     LOperand* context = UseFixed(instr->context(), cp);
   2070     return MarkAsCall(new(zone()) LStackCheck(context), instr);
   2071   } else {
   2072     DCHECK(instr->is_backwards_branch());
   2073     LOperand* context = UseAny(instr->context());
   2074     return AssignEnvironment(
   2075         AssignPointerMap(new(zone()) LStackCheck(context)));
   2076   }
   2077 }
   2078 
   2079 
   2080 LInstruction* LChunkBuilder::DoStoreCodeEntry(HStoreCodeEntry* instr) {
   2081   LOperand* function = UseRegister(instr->function());
   2082   LOperand* code_object = UseRegisterAtStart(instr->code_object());
   2083   LOperand* temp = TempRegister();
   2084   return new(zone()) LStoreCodeEntry(function, code_object, temp);
   2085 }
   2086 
   2087 
   2088 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
   2089   LOperand* temp = TempRegister();
   2090   LOperand* context;
   2091   LOperand* value;
   2092   if (instr->NeedsWriteBarrier()) {
   2093     // TODO(all): Replace these constraints when RecordWriteStub has been
   2094     // rewritten.
   2095     context = UseRegisterAndClobber(instr->context());
   2096     value = UseRegisterAndClobber(instr->value());
   2097   } else {
   2098     context = UseRegister(instr->context());
   2099     value = UseRegister(instr->value());
   2100   }
   2101   LInstruction* result = new(zone()) LStoreContextSlot(context, value, temp);
   2102   if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
   2103     result = AssignEnvironment(result);
   2104   }
   2105   return result;
   2106 }
   2107 
   2108 
   2109 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
   2110   LOperand* key = UseRegisterOrConstant(instr->key());
   2111   LOperand* temp = NULL;
   2112   LOperand* elements = NULL;
   2113   LOperand* val = NULL;
   2114 
   2115   if (!instr->is_fixed_typed_array() &&
   2116       instr->value()->representation().IsTagged() &&
   2117       instr->NeedsWriteBarrier()) {
   2118     // RecordWrite() will clobber all registers.
   2119     elements = UseRegisterAndClobber(instr->elements());
   2120     val = UseRegisterAndClobber(instr->value());
   2121     temp = TempRegister();
   2122   } else {
   2123     elements = UseRegister(instr->elements());
   2124     val = UseRegister(instr->value());
   2125     temp = instr->key()->IsConstant() ? NULL : TempRegister();
   2126   }
   2127 
   2128   if (instr->is_fixed_typed_array()) {
   2129     DCHECK((instr->value()->representation().IsInteger32() &&
   2130             !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
   2131            (instr->value()->representation().IsDouble() &&
   2132             IsDoubleOrFloatElementsKind(instr->elements_kind())));
   2133     DCHECK(instr->elements()->representation().IsExternal());
   2134     LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
   2135     return new (zone())
   2136         LStoreKeyedExternal(elements, key, val, backing_store_owner, temp);
   2137 
   2138   } else if (instr->value()->representation().IsDouble()) {
   2139     DCHECK(instr->elements()->representation().IsTagged());
   2140     return new(zone()) LStoreKeyedFixedDouble(elements, key, val, temp);
   2141 
   2142   } else {
   2143     DCHECK(instr->elements()->representation().IsTagged());
   2144     DCHECK(instr->value()->representation().IsSmiOrTagged() ||
   2145            instr->value()->representation().IsInteger32());
   2146     return new(zone()) LStoreKeyedFixed(elements, key, val, temp);
   2147   }
   2148 }
   2149 
   2150 
   2151 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   2152   // TODO(jbramley): It might be beneficial to allow value to be a constant in
   2153   // some cases. x64 makes use of this with FLAG_track_fields, for example.
   2154 
   2155   LOperand* object = UseRegister(instr->object());
   2156   LOperand* value;
   2157   LOperand* temp0 = NULL;
   2158   LOperand* temp1 = NULL;
   2159 
   2160   if (instr->access().IsExternalMemory() ||
   2161       (!FLAG_unbox_double_fields && instr->field_representation().IsDouble())) {
   2162     value = UseRegister(instr->value());
   2163   } else if (instr->NeedsWriteBarrier()) {
   2164     value = UseRegisterAndClobber(instr->value());
   2165     temp0 = TempRegister();
   2166     temp1 = TempRegister();
   2167   } else if (instr->NeedsWriteBarrierForMap()) {
   2168     value = UseRegister(instr->value());
   2169     temp0 = TempRegister();
   2170     temp1 = TempRegister();
   2171   } else {
   2172     value = UseRegister(instr->value());
   2173     temp0 = TempRegister();
   2174   }
   2175 
   2176   return new(zone()) LStoreNamedField(object, value, temp0, temp1);
   2177 }
   2178 
   2179 
   2180 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
   2181   LOperand* context = UseFixed(instr->context(), cp);
   2182   LOperand* left = UseFixed(instr->left(), x1);
   2183   LOperand* right = UseFixed(instr->right(), x0);
   2184 
   2185   LStringAdd* result = new(zone()) LStringAdd(context, left, right);
   2186   return MarkAsCall(DefineFixed(result, x0), instr);
   2187 }
   2188 
   2189 
   2190 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
   2191   LOperand* string = UseRegisterAndClobber(instr->string());
   2192   LOperand* index = UseRegisterAndClobber(instr->index());
   2193   LOperand* context = UseAny(instr->context());
   2194   LStringCharCodeAt* result =
   2195       new(zone()) LStringCharCodeAt(context, string, index);
   2196   return AssignPointerMap(DefineAsRegister(result));
   2197 }
   2198 
   2199 
   2200 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
   2201   LOperand* char_code = UseRegister(instr->value());
   2202   LOperand* context = UseAny(instr->context());
   2203   LStringCharFromCode* result =
   2204       new(zone()) LStringCharFromCode(context, char_code);
   2205   return AssignPointerMap(DefineAsRegister(result));
   2206 }
   2207 
   2208 
   2209 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
   2210     HStringCompareAndBranch* instr) {
   2211   DCHECK(instr->left()->representation().IsTagged());
   2212   DCHECK(instr->right()->representation().IsTagged());
   2213   LOperand* context = UseFixed(instr->context(), cp);
   2214   LOperand* left = UseFixed(instr->left(), x1);
   2215   LOperand* right = UseFixed(instr->right(), x0);
   2216   LStringCompareAndBranch* result =
   2217       new(zone()) LStringCompareAndBranch(context, left, right);
   2218   return MarkAsCall(result, instr);
   2219 }
   2220 
   2221 
   2222 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
   2223   if (instr->representation().IsSmiOrInteger32()) {
   2224     DCHECK(instr->left()->representation().Equals(instr->representation()));
   2225     DCHECK(instr->right()->representation().Equals(instr->representation()));
   2226 
   2227     LInstruction* shifted_operation = TryDoOpWithShiftedRightOperand(instr);
   2228     if (shifted_operation != NULL) {
   2229       return shifted_operation;
   2230     }
   2231 
   2232     LOperand *left;
   2233     if (instr->left()->IsConstant() &&
   2234         (HConstant::cast(instr->left())->Integer32Value() == 0)) {
   2235       left = UseConstant(instr->left());
   2236     } else {
   2237       left = UseRegisterAtStart(instr->left());
   2238     }
   2239     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
   2240     LInstruction* result = instr->representation().IsSmi() ?
   2241         DefineAsRegister(new(zone()) LSubS(left, right)) :
   2242         DefineAsRegister(new(zone()) LSubI(left, right));
   2243     if (instr->CheckFlag(HValue::kCanOverflow)) {
   2244       result = AssignEnvironment(result);
   2245     }
   2246     return result;
   2247   } else if (instr->representation().IsDouble()) {
   2248     return DoArithmeticD(Token::SUB, instr);
   2249   } else {
   2250     return DoArithmeticT(Token::SUB, instr);
   2251   }
   2252 }
   2253 
   2254 
   2255 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
   2256   if (instr->HasNoUses()) {
   2257     return NULL;
   2258   } else {
   2259     return DefineAsRegister(new(zone()) LThisFunction);
   2260   }
   2261 }
   2262 
   2263 
   2264 LInstruction* LChunkBuilder::DoTransitionElementsKind(
   2265     HTransitionElementsKind* instr) {
   2266   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
   2267     LOperand* object = UseRegister(instr->object());
   2268     LTransitionElementsKind* result =
   2269         new(zone()) LTransitionElementsKind(object, NULL,
   2270                                             TempRegister(), TempRegister());
   2271     return result;
   2272   } else {
   2273     LOperand* object = UseFixed(instr->object(), x0);
   2274     LOperand* context = UseFixed(instr->context(), cp);
   2275     LTransitionElementsKind* result =
   2276         new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
   2277     return MarkAsCall(result, instr);
   2278   }
   2279 }
   2280 
   2281 
   2282 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
   2283     HTrapAllocationMemento* instr) {
   2284   LOperand* object = UseRegister(instr->object());
   2285   LOperand* temp1 = TempRegister();
   2286   LOperand* temp2 = TempRegister();
   2287   LTrapAllocationMemento* result =
   2288       new(zone()) LTrapAllocationMemento(object, temp1, temp2);
   2289   return AssignEnvironment(result);
   2290 }
   2291 
   2292 
   2293 LInstruction* LChunkBuilder::DoMaybeGrowElements(HMaybeGrowElements* instr) {
   2294   info()->MarkAsDeferredCalling();
   2295   LOperand* context = UseFixed(instr->context(), cp);
   2296   LOperand* object = UseRegister(instr->object());
   2297   LOperand* elements = UseRegister(instr->elements());
   2298   LOperand* key = UseRegisterOrConstant(instr->key());
   2299   LOperand* current_capacity = UseRegisterOrConstant(instr->current_capacity());
   2300 
   2301   LMaybeGrowElements* result = new (zone())
   2302       LMaybeGrowElements(context, object, elements, key, current_capacity);
   2303   DefineFixed(result, x0);
   2304   return AssignPointerMap(AssignEnvironment(result));
   2305 }
   2306 
   2307 
   2308 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
   2309   LOperand* context = UseFixed(instr->context(), cp);
   2310   LOperand* value = UseFixed(instr->value(), x3);
   2311   LTypeof* result = new (zone()) LTypeof(context, value);
   2312   return MarkAsCall(DefineFixed(result, x0), instr);
   2313 }
   2314 
   2315 
   2316 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
   2317   // We only need temp registers in some cases, but we can't dereference the
   2318   // instr->type_literal() handle to test that here.
   2319   LOperand* temp1 = TempRegister();
   2320   LOperand* temp2 = TempRegister();
   2321 
   2322   return new(zone()) LTypeofIsAndBranch(
   2323       UseRegister(instr->value()), temp1, temp2);
   2324 }
   2325 
   2326 
   2327 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
   2328   switch (instr->op()) {
   2329     case kMathAbs: {
   2330       Representation r = instr->representation();
   2331       if (r.IsTagged()) {
   2332         // The tagged case might need to allocate a HeapNumber for the result,
   2333         // so it is handled by a separate LInstruction.
   2334         LOperand* context = UseFixed(instr->context(), cp);
   2335         LOperand* input = UseRegister(instr->value());
   2336         LOperand* temp1 = TempRegister();
   2337         LOperand* temp2 = TempRegister();
   2338         LOperand* temp3 = TempRegister();
   2339         LInstruction* result = DefineAsRegister(
   2340             new(zone()) LMathAbsTagged(context, input, temp1, temp2, temp3));
   2341         return AssignEnvironment(AssignPointerMap(result));
   2342       } else {
   2343         LOperand* input = UseRegisterAtStart(instr->value());
   2344         LInstruction* result = DefineAsRegister(new(zone()) LMathAbs(input));
   2345         if (!r.IsDouble()) result = AssignEnvironment(result);
   2346         return result;
   2347       }
   2348     }
   2349     case kMathCos: {
   2350       DCHECK(instr->representation().IsDouble());
   2351       DCHECK(instr->value()->representation().IsDouble());
   2352       LOperand* input = UseFixedDouble(instr->value(), d0);
   2353       LMathCos* result = new (zone()) LMathCos(input);
   2354       return MarkAsCall(DefineFixedDouble(result, d0), instr);
   2355     }
   2356     case kMathSin: {
   2357       DCHECK(instr->representation().IsDouble());
   2358       DCHECK(instr->value()->representation().IsDouble());
   2359       LOperand* input = UseFixedDouble(instr->value(), d0);
   2360       LMathSin* result = new (zone()) LMathSin(input);
   2361       return MarkAsCall(DefineFixedDouble(result, d0), instr);
   2362     }
   2363     case kMathExp: {
   2364       DCHECK(instr->representation().IsDouble());
   2365       DCHECK(instr->value()->representation().IsDouble());
   2366       LOperand* input = UseFixedDouble(instr->value(), d0);
   2367       LMathExp* result = new (zone()) LMathExp(input);
   2368       return MarkAsCall(DefineFixedDouble(result, d0), instr);
   2369     }
   2370     case kMathFloor: {
   2371       DCHECK(instr->value()->representation().IsDouble());
   2372       LOperand* input = UseRegisterAtStart(instr->value());
   2373       if (instr->representation().IsInteger32()) {
   2374         LMathFloorI* result = new(zone()) LMathFloorI(input);
   2375         return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
   2376       } else {
   2377         DCHECK(instr->representation().IsDouble());
   2378         LMathFloorD* result = new(zone()) LMathFloorD(input);
   2379         return DefineAsRegister(result);
   2380       }
   2381     }
   2382     case kMathLog: {
   2383       DCHECK(instr->representation().IsDouble());
   2384       DCHECK(instr->value()->representation().IsDouble());
   2385       LOperand* input = UseFixedDouble(instr->value(), d0);
   2386       LMathLog* result = new(zone()) LMathLog(input);
   2387       return MarkAsCall(DefineFixedDouble(result, d0), instr);
   2388     }
   2389     case kMathPowHalf: {
   2390       DCHECK(instr->representation().IsDouble());
   2391       DCHECK(instr->value()->representation().IsDouble());
   2392       LOperand* input = UseRegister(instr->value());
   2393       return DefineAsRegister(new(zone()) LMathPowHalf(input));
   2394     }
   2395     case kMathRound: {
   2396       DCHECK(instr->value()->representation().IsDouble());
   2397       LOperand* input = UseRegister(instr->value());
   2398       if (instr->representation().IsInteger32()) {
   2399         LOperand* temp = TempDoubleRegister();
   2400         LMathRoundI* result = new(zone()) LMathRoundI(input, temp);
   2401         return AssignEnvironment(DefineAsRegister(result));
   2402       } else {
   2403         DCHECK(instr->representation().IsDouble());
   2404         LMathRoundD* result = new(zone()) LMathRoundD(input);
   2405         return DefineAsRegister(result);
   2406       }
   2407     }
   2408     case kMathFround: {
   2409       DCHECK(instr->value()->representation().IsDouble());
   2410       LOperand* input = UseRegister(instr->value());
   2411       LMathFround* result = new (zone()) LMathFround(input);
   2412       return DefineAsRegister(result);
   2413     }
   2414     case kMathSqrt: {
   2415       DCHECK(instr->representation().IsDouble());
   2416       DCHECK(instr->value()->representation().IsDouble());
   2417       LOperand* input = UseRegisterAtStart(instr->value());
   2418       return DefineAsRegister(new(zone()) LMathSqrt(input));
   2419     }
   2420     case kMathClz32: {
   2421       DCHECK(instr->representation().IsInteger32());
   2422       DCHECK(instr->value()->representation().IsInteger32());
   2423       LOperand* input = UseRegisterAtStart(instr->value());
   2424       return DefineAsRegister(new(zone()) LMathClz32(input));
   2425     }
   2426     default:
   2427       UNREACHABLE();
   2428       return NULL;
   2429   }
   2430 }
   2431 
   2432 
   2433 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
   2434   // Use an index that corresponds to the location in the unoptimized frame,
   2435   // which the optimized frame will subsume.
   2436   int env_index = instr->index();
   2437   int spill_index = 0;
   2438   if (instr->environment()->is_parameter_index(env_index)) {
   2439     spill_index = chunk_->GetParameterStackSlot(env_index);
   2440   } else {
   2441     spill_index = env_index - instr->environment()->first_local_index();
   2442     if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
   2443       Retry(kTooManySpillSlotsNeededForOSR);
   2444       spill_index = 0;
   2445     }
   2446     spill_index += StandardFrameConstants::kFixedSlotCount;
   2447   }
   2448   return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
   2449 }
   2450 
   2451 
   2452 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
   2453   return NULL;
   2454 }
   2455 
   2456 
   2457 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
   2458   LOperand* context = UseFixed(instr->context(), cp);
   2459   // Assign object to a fixed register different from those already used in
   2460   // LForInPrepareMap.
   2461   LOperand* object = UseFixed(instr->enumerable(), x0);
   2462   LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
   2463   return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
   2464 }
   2465 
   2466 
   2467 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
   2468   LOperand* map = UseRegister(instr->map());
   2469   return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
   2470 }
   2471 
   2472 
   2473 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
   2474   LOperand* value = UseRegisterAtStart(instr->value());
   2475   LOperand* map = UseRegister(instr->map());
   2476   LOperand* temp = TempRegister();
   2477   return AssignEnvironment(new(zone()) LCheckMapValue(value, map, temp));
   2478 }
   2479 
   2480 
   2481 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
   2482   LOperand* object = UseRegisterAtStart(instr->object());
   2483   LOperand* index = UseRegisterAndClobber(instr->index());
   2484   LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index);
   2485   LInstruction* result = DefineSameAsFirst(load);
   2486   return AssignPointerMap(result);
   2487 }
   2488 
   2489 
   2490 LInstruction* LChunkBuilder::DoWrapReceiver(HWrapReceiver* instr) {
   2491   LOperand* receiver = UseRegister(instr->receiver());
   2492   LOperand* function = UseRegister(instr->function());
   2493   LWrapReceiver* result = new(zone()) LWrapReceiver(receiver, function);
   2494   return AssignEnvironment(DefineAsRegister(result));
   2495 }
   2496 
   2497 }  // namespace internal
   2498 }  // namespace v8
   2499