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