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