Home | History | Annotate | Download | only in mips64
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/crankshaft/mips64/lithium-mips64.h"
      6 
      7 #include <sstream>
      8 
      9 #if V8_TARGET_ARCH_MIPS64
     10 
     11 #include "src/crankshaft/hydrogen-osr.h"
     12 #include "src/crankshaft/lithium-inl.h"
     13 #include "src/crankshaft/mips64/lithium-codegen-mips64.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 
     18 #define DEFINE_COMPILE(type)                            \
     19   void L##type::CompileToNative(LCodeGen* generator) {  \
     20     generator->Do##type(this);                          \
     21   }
     22 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
     23 #undef DEFINE_COMPILE
     24 
     25 #ifdef DEBUG
     26 void LInstruction::VerifyCall() {
     27   // Call instructions can use only fixed registers as temporaries and
     28   // outputs because all registers are blocked by the calling convention.
     29   // Inputs operands must use a fixed register or use-at-start policy or
     30   // a non-register policy.
     31   DCHECK(Output() == NULL ||
     32          LUnallocated::cast(Output())->HasFixedPolicy() ||
     33          !LUnallocated::cast(Output())->HasRegisterPolicy());
     34   for (UseIterator it(this); !it.Done(); it.Advance()) {
     35     LUnallocated* operand = LUnallocated::cast(it.Current());
     36     DCHECK(operand->HasFixedPolicy() ||
     37            operand->IsUsedAtStart());
     38   }
     39   for (TempIterator it(this); !it.Done(); it.Advance()) {
     40     LUnallocated* operand = LUnallocated::cast(it.Current());
     41     DCHECK(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy());
     42   }
     43 }
     44 #endif
     45 
     46 
     47 void LInstruction::PrintTo(StringStream* stream) {
     48   stream->Add("%s ", this->Mnemonic());
     49 
     50   PrintOutputOperandTo(stream);
     51 
     52   PrintDataTo(stream);
     53 
     54   if (HasEnvironment()) {
     55     stream->Add(" ");
     56     environment()->PrintTo(stream);
     57   }
     58 
     59   if (HasPointerMap()) {
     60     stream->Add(" ");
     61     pointer_map()->PrintTo(stream);
     62   }
     63 }
     64 
     65 
     66 void LInstruction::PrintDataTo(StringStream* stream) {
     67   stream->Add("= ");
     68   for (int i = 0; i < InputCount(); i++) {
     69     if (i > 0) stream->Add(" ");
     70     if (InputAt(i) == NULL) {
     71       stream->Add("NULL");
     72     } else {
     73       InputAt(i)->PrintTo(stream);
     74     }
     75   }
     76 }
     77 
     78 
     79 void LInstruction::PrintOutputOperandTo(StringStream* stream) {
     80   if (HasResult()) result()->PrintTo(stream);
     81 }
     82 
     83 
     84 void LLabel::PrintDataTo(StringStream* stream) {
     85   LGap::PrintDataTo(stream);
     86   LLabel* rep = replacement();
     87   if (rep != NULL) {
     88     stream->Add(" Dead block replaced with B%d", rep->block_id());
     89   }
     90 }
     91 
     92 
     93 bool LGap::IsRedundant() const {
     94   for (int i = 0; i < 4; i++) {
     95     if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
     96       return false;
     97     }
     98   }
     99 
    100   return true;
    101 }
    102 
    103 
    104 void LGap::PrintDataTo(StringStream* stream) {
    105   for (int i = 0; i < 4; i++) {
    106     stream->Add("(");
    107     if (parallel_moves_[i] != NULL) {
    108       parallel_moves_[i]->PrintDataTo(stream);
    109     }
    110     stream->Add(") ");
    111   }
    112 }
    113 
    114 
    115 const char* LArithmeticD::Mnemonic() const {
    116   switch (op()) {
    117     case Token::ADD: return "add-d";
    118     case Token::SUB: return "sub-d";
    119     case Token::MUL: return "mul-d";
    120     case Token::DIV: return "div-d";
    121     case Token::MOD: return "mod-d";
    122     default:
    123       UNREACHABLE();
    124       return NULL;
    125   }
    126 }
    127 
    128 
    129 const char* LArithmeticT::Mnemonic() const {
    130   switch (op()) {
    131     case Token::ADD: return "add-t";
    132     case Token::SUB: return "sub-t";
    133     case Token::MUL: return "mul-t";
    134     case Token::MOD: return "mod-t";
    135     case Token::DIV: return "div-t";
    136     case Token::BIT_AND: return "bit-and-t";
    137     case Token::BIT_OR: return "bit-or-t";
    138     case Token::BIT_XOR: return "bit-xor-t";
    139     case Token::ROR: return "ror-t";
    140     case Token::SHL: return "sll-t";
    141     case Token::SAR: return "sra-t";
    142     case Token::SHR: return "srl-t";
    143     default:
    144       UNREACHABLE();
    145       return NULL;
    146   }
    147 }
    148 
    149 
    150 bool LGoto::HasInterestingComment(LCodeGen* gen) const {
    151   return !gen->IsNextEmittedBlock(block_id());
    152 }
    153 
    154 
    155 void LGoto::PrintDataTo(StringStream* stream) {
    156   stream->Add("B%d", block_id());
    157 }
    158 
    159 
    160 void LBranch::PrintDataTo(StringStream* stream) {
    161   stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
    162   value()->PrintTo(stream);
    163 }
    164 
    165 
    166 LInstruction* LChunkBuilder::DoDebugBreak(HDebugBreak* instr) {
    167   return new(zone()) LDebugBreak();
    168 }
    169 
    170 
    171 void LCompareNumericAndBranch::PrintDataTo(StringStream* stream) {
    172   stream->Add("if ");
    173   left()->PrintTo(stream);
    174   stream->Add(" %s ", Token::String(op()));
    175   right()->PrintTo(stream);
    176   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
    177 }
    178 
    179 
    180 void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
    181   stream->Add("if is_string(");
    182   value()->PrintTo(stream);
    183   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    184 }
    185 
    186 
    187 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
    188   stream->Add("if is_smi(");
    189   value()->PrintTo(stream);
    190   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    191 }
    192 
    193 
    194 void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
    195   stream->Add("if is_undetectable(");
    196   value()->PrintTo(stream);
    197   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    198 }
    199 
    200 
    201 void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
    202   stream->Add("if string_compare(");
    203   left()->PrintTo(stream);
    204   right()->PrintTo(stream);
    205   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    206 }
    207 
    208 
    209 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
    210   stream->Add("if has_instance_type(");
    211   value()->PrintTo(stream);
    212   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    213 }
    214 
    215 
    216 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
    217   stream->Add("if has_cached_array_index(");
    218   value()->PrintTo(stream);
    219   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    220 }
    221 
    222 
    223 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
    224   stream->Add("if class_of_test(");
    225   value()->PrintTo(stream);
    226   stream->Add(", \"%o\") then B%d else B%d",
    227               *hydrogen()->class_name(),
    228               true_block_id(),
    229               false_block_id());
    230 }
    231 
    232 
    233 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
    234   stream->Add("if typeof ");
    235   value()->PrintTo(stream);
    236   stream->Add(" == \"%s\" then B%d else B%d",
    237               hydrogen()->type_literal()->ToCString().get(),
    238               true_block_id(), false_block_id());
    239 }
    240 
    241 
    242 void LStoreCodeEntry::PrintDataTo(StringStream* stream) {
    243   stream->Add(" = ");
    244   function()->PrintTo(stream);
    245   stream->Add(".code_entry = ");
    246   code_object()->PrintTo(stream);
    247 }
    248 
    249 
    250 void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
    251   stream->Add(" = ");
    252   base_object()->PrintTo(stream);
    253   stream->Add(" + ");
    254   offset()->PrintTo(stream);
    255 }
    256 
    257 
    258 void 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 = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)
   1276     ? NULL : TempRegister();
   1277   LInstruction* result =
   1278       DefineAsRegister(new(zone()) LDivI(dividend, divisor, temp));
   1279   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
   1280       instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
   1281       (instr->CheckFlag(HValue::kCanOverflow) &&
   1282        !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) ||
   1283       (!instr->IsMathFloorOfDiv() &&
   1284        !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
   1285     result = AssignEnvironment(result);
   1286   }
   1287   return result;
   1288 }
   1289 
   1290 
   1291 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   1292   if (instr->representation().IsSmiOrInteger32()) {
   1293     if (instr->RightIsPowerOf2()) {
   1294       return DoDivByPowerOf2I(instr);
   1295     } else if (instr->right()->IsConstant()) {
   1296       return DoDivByConstI(instr);
   1297     } else {
   1298       return DoDivI(instr);
   1299     }
   1300   } else if (instr->representation().IsDouble()) {
   1301     return DoArithmeticD(Token::DIV, instr);
   1302   } else {
   1303     return DoArithmeticT(Token::DIV, instr);
   1304   }
   1305 }
   1306 
   1307 
   1308 LInstruction* LChunkBuilder::DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr) {
   1309   LOperand* dividend = UseRegisterAtStart(instr->left());
   1310   int32_t divisor = instr->right()->GetInteger32Constant();
   1311   LInstruction* result = DefineAsRegister(new(zone()) LFlooringDivByPowerOf2I(
   1312           dividend, divisor));
   1313   if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
   1314       (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) {
   1315     result = AssignEnvironment(result);
   1316   }
   1317   return result;
   1318 }
   1319 
   1320 
   1321 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
   1322   DCHECK(instr->representation().IsInteger32());
   1323   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1324   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1325   LOperand* dividend = UseRegister(instr->left());
   1326   int32_t divisor = instr->right()->GetInteger32Constant();
   1327   LOperand* temp =
   1328       ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
   1329        (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
   1330       NULL : TempRegister();
   1331   LInstruction* result = DefineAsRegister(
   1332       new(zone()) LFlooringDivByConstI(dividend, divisor, temp));
   1333   if (divisor == 0 ||
   1334       (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
   1335     result = AssignEnvironment(result);
   1336   }
   1337   return result;
   1338 }
   1339 
   1340 
   1341 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
   1342   DCHECK(instr->representation().IsSmiOrInteger32());
   1343   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1344   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1345   LOperand* dividend = UseRegister(instr->left());
   1346   LOperand* divisor = UseRegister(instr->right());
   1347   LInstruction* result =
   1348       DefineAsRegister(new (zone()) LFlooringDivI(dividend, divisor));
   1349   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
   1350       instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
   1351       (instr->CheckFlag(HValue::kCanOverflow))) {
   1352     result = AssignEnvironment(result);
   1353   }
   1354   return result;
   1355 }
   1356 
   1357 
   1358 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
   1359   if (instr->RightIsPowerOf2()) {
   1360     return DoFlooringDivByPowerOf2I(instr);
   1361   } else if (instr->right()->IsConstant()) {
   1362     return DoFlooringDivByConstI(instr);
   1363   } else {
   1364     return DoFlooringDivI(instr);
   1365   }
   1366 }
   1367 
   1368 
   1369 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) {
   1370   DCHECK(instr->representation().IsSmiOrInteger32());
   1371   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1372   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1373   LOperand* dividend = UseRegisterAtStart(instr->left());
   1374   int32_t divisor = instr->right()->GetInteger32Constant();
   1375   LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
   1376           dividend, divisor));
   1377   if (instr->CheckFlag(HValue::kLeftCanBeNegative) &&
   1378       instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1379     result = AssignEnvironment(result);
   1380   }
   1381   return result;
   1382 }
   1383 
   1384 
   1385 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) {
   1386   DCHECK(instr->representation().IsSmiOrInteger32());
   1387   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1388   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1389   LOperand* dividend = UseRegister(instr->left());
   1390   int32_t divisor = instr->right()->GetInteger32Constant();
   1391   LInstruction* result = DefineAsRegister(new(zone()) LModByConstI(
   1392           dividend, divisor));
   1393   if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1394     result = AssignEnvironment(result);
   1395   }
   1396   return result;
   1397 }
   1398 
   1399 
   1400 LInstruction* LChunkBuilder::DoModI(HMod* instr) {
   1401   DCHECK(instr->representation().IsSmiOrInteger32());
   1402   DCHECK(instr->left()->representation().Equals(instr->representation()));
   1403   DCHECK(instr->right()->representation().Equals(instr->representation()));
   1404   LOperand* dividend = UseRegister(instr->left());
   1405   LOperand* divisor = UseRegister(instr->right());
   1406   LInstruction* result = DefineAsRegister(new(zone()) LModI(
   1407       dividend, divisor));
   1408   if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
   1409       instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1410     result = AssignEnvironment(result);
   1411   }
   1412   return result;
   1413 }
   1414 
   1415 
   1416 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
   1417   if (instr->representation().IsSmiOrInteger32()) {
   1418     return instr->RightIsPowerOf2() ? DoModByPowerOf2I(instr) : DoModI(instr);
   1419   } else if (instr->representation().IsDouble()) {
   1420     return DoArithmeticD(Token::MOD, instr);
   1421   } else {
   1422     return DoArithmeticT(Token::MOD, instr);
   1423   }
   1424 }
   1425 
   1426 
   1427 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
   1428   if (instr->representation().IsSmiOrInteger32()) {
   1429     DCHECK(instr->left()->representation().Equals(instr->representation()));
   1430     DCHECK(instr->right()->representation().Equals(instr->representation()));
   1431     HValue* left = instr->BetterLeftOperand();
   1432     HValue* right = instr->BetterRightOperand();
   1433     LOperand* left_op;
   1434     LOperand* right_op;
   1435     bool can_overflow = instr->CheckFlag(HValue::kCanOverflow);
   1436     bool bailout_on_minus_zero = instr->CheckFlag(HValue::kBailoutOnMinusZero);
   1437 
   1438     int32_t constant_value = 0;
   1439     if (right->IsConstant()) {
   1440       HConstant* constant = HConstant::cast(right);
   1441       constant_value = constant->Integer32Value();
   1442       // Constants -1, 0 and 1 can be optimized if the result can overflow.
   1443       // For other constants, it can be optimized only without overflow.
   1444       if (!can_overflow || ((constant_value >= -1) && (constant_value <= 1))) {
   1445         left_op = UseRegisterAtStart(left);
   1446         right_op = UseConstant(right);
   1447       } else {
   1448         if (bailout_on_minus_zero) {
   1449           left_op = UseRegister(left);
   1450         } else {
   1451           left_op = UseRegisterAtStart(left);
   1452         }
   1453         right_op = UseRegister(right);
   1454       }
   1455     } else {
   1456       if (bailout_on_minus_zero) {
   1457         left_op = UseRegister(left);
   1458       } else {
   1459         left_op = UseRegisterAtStart(left);
   1460       }
   1461       right_op = UseRegister(right);
   1462     }
   1463     LInstruction* result =
   1464         instr->representation().IsSmi()
   1465             ? DefineAsRegister(new (zone()) LMulS(left_op, right_op))
   1466             : DefineAsRegister(new (zone()) LMulI(left_op, right_op));
   1467     if (right_op->IsConstantOperand()
   1468             ? ((can_overflow && constant_value == -1) ||
   1469                (bailout_on_minus_zero && constant_value <= 0))
   1470             : (can_overflow || bailout_on_minus_zero)) {
   1471       AssignEnvironment(result);
   1472     }
   1473     return result;
   1474 
   1475   } else if (instr->representation().IsDouble()) {
   1476     if (kArchVariant == kMips64r2) {
   1477       if (instr->HasOneUse() && instr->uses().value()->IsAdd()) {
   1478         HAdd* add = HAdd::cast(instr->uses().value());
   1479         if (instr == add->left()) {
   1480           // This mul is the lhs of an add. The add and mul will be folded
   1481           // into a multiply-add.
   1482           return NULL;
   1483         }
   1484         if (instr == add->right() && !add->left()->IsMul()) {
   1485           // This mul is the rhs of an add, where the lhs is not another mul.
   1486           // The add and mul will be folded into a multiply-add.
   1487           return NULL;
   1488         }
   1489       }
   1490     }
   1491     return DoArithmeticD(Token::MUL, instr);
   1492   } else {
   1493     return DoArithmeticT(Token::MUL, instr);
   1494   }
   1495 }
   1496 
   1497 
   1498 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
   1499   if (instr->representation().IsSmiOrInteger32()) {
   1500     DCHECK(instr->left()->representation().Equals(instr->representation()));
   1501     DCHECK(instr->right()->representation().Equals(instr->representation()));
   1502     LOperand* left = UseRegisterAtStart(instr->left());
   1503     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
   1504     LInstruction* result =
   1505         instr->representation().IsSmi()
   1506             ? DefineAsRegister(new (zone()) LSubS(left, right))
   1507             : DefineAsRegister(new (zone()) LSubI(left, right));
   1508     if (instr->CheckFlag(HValue::kCanOverflow)) {
   1509       result = AssignEnvironment(result);
   1510     }
   1511     return result;
   1512   } else if (instr->representation().IsDouble()) {
   1513     return DoArithmeticD(Token::SUB, instr);
   1514   } else {
   1515     return DoArithmeticT(Token::SUB, instr);
   1516   }
   1517 }
   1518 
   1519 
   1520 LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) {
   1521   LOperand* multiplier_op = UseRegisterAtStart(mul->left());
   1522   LOperand* multiplicand_op = UseRegisterAtStart(mul->right());
   1523   LOperand* addend_op = UseRegisterAtStart(addend);
   1524   return DefineSameAsFirst(new(zone()) LMultiplyAddD(addend_op, multiplier_op,
   1525                                                      multiplicand_op));
   1526 }
   1527 
   1528 
   1529 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
   1530   if (instr->representation().IsSmiOrInteger32()) {
   1531     DCHECK(instr->left()->representation().Equals(instr->representation()));
   1532     DCHECK(instr->right()->representation().Equals(instr->representation()));
   1533     LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand());
   1534     LOperand* right = UseRegisterOrConstantAtStart(instr->BetterRightOperand());
   1535     LInstruction* result =
   1536         instr->representation().IsSmi()
   1537             ? DefineAsRegister(new (zone()) LAddS(left, right))
   1538             : DefineAsRegister(new (zone()) LAddI(left, right));
   1539     if (instr->CheckFlag(HValue::kCanOverflow)) {
   1540       result = AssignEnvironment(result);
   1541     }
   1542     return result;
   1543   } else if (instr->representation().IsExternal()) {
   1544     DCHECK(instr->IsConsistentExternalRepresentation());
   1545     DCHECK(!instr->CheckFlag(HValue::kCanOverflow));
   1546     LOperand* left = UseRegisterAtStart(instr->left());
   1547     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
   1548     return DefineAsRegister(new (zone()) LAddE(left, right));
   1549   } else if (instr->representation().IsDouble()) {
   1550     if (kArchVariant == kMips64r2) {
   1551       if (instr->left()->IsMul())
   1552         return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
   1553 
   1554       if (instr->right()->IsMul()) {
   1555         DCHECK(!instr->left()->IsMul());
   1556         return DoMultiplyAdd(HMul::cast(instr->right()), instr->left());
   1557       }
   1558     }
   1559     return DoArithmeticD(Token::ADD, instr);
   1560   } else {
   1561     return DoArithmeticT(Token::ADD, instr);
   1562   }
   1563 }
   1564 
   1565 
   1566 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) {
   1567   LOperand* left = NULL;
   1568   LOperand* right = NULL;
   1569   if (instr->representation().IsSmiOrInteger32()) {
   1570     DCHECK(instr->left()->representation().Equals(instr->representation()));
   1571     DCHECK(instr->right()->representation().Equals(instr->representation()));
   1572     left = UseRegisterAtStart(instr->BetterLeftOperand());
   1573     right = UseOrConstantAtStart(instr->BetterRightOperand());
   1574   } else {
   1575     DCHECK(instr->representation().IsDouble());
   1576     DCHECK(instr->left()->representation().IsDouble());
   1577     DCHECK(instr->right()->representation().IsDouble());
   1578     left = UseRegisterAtStart(instr->left());
   1579     right = UseRegisterAtStart(instr->right());
   1580   }
   1581   return DefineAsRegister(new(zone()) LMathMinMax(left, right));
   1582 }
   1583 
   1584 
   1585 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
   1586   DCHECK(instr->representation().IsDouble());
   1587   // We call a C function for double power. It can't trigger a GC.
   1588   // We need to use fixed result register for the call.
   1589   Representation exponent_type = instr->right()->representation();
   1590   DCHECK(instr->left()->representation().IsDouble());
   1591   LOperand* left = UseFixedDouble(instr->left(), f2);
   1592   LOperand* right =
   1593       exponent_type.IsDouble()
   1594           ? UseFixedDouble(instr->right(), f4)
   1595           : UseFixed(instr->right(), MathPowTaggedDescriptor::exponent());
   1596   LPower* result = new(zone()) LPower(left, right);
   1597   return MarkAsCall(DefineFixedDouble(result, f0),
   1598                     instr,
   1599                     CAN_DEOPTIMIZE_EAGERLY);
   1600 }
   1601 
   1602 
   1603 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) {
   1604   DCHECK(instr->left()->representation().IsTagged());
   1605   DCHECK(instr->right()->representation().IsTagged());
   1606   LOperand* context = UseFixed(instr->context(), cp);
   1607   LOperand* left = UseFixed(instr->left(), a1);
   1608   LOperand* right = UseFixed(instr->right(), a0);
   1609   LCmpT* result = new(zone()) LCmpT(context, left, right);
   1610   return MarkAsCall(DefineFixed(result, v0), instr);
   1611 }
   1612 
   1613 
   1614 LInstruction* LChunkBuilder::DoCompareNumericAndBranch(
   1615     HCompareNumericAndBranch* instr) {
   1616   Representation r = instr->representation();
   1617   if (r.IsSmiOrInteger32()) {
   1618     DCHECK(instr->left()->representation().Equals(r));
   1619     DCHECK(instr->right()->representation().Equals(r));
   1620     LOperand* left = UseRegisterOrConstantAtStart(instr->left());
   1621     LOperand* right = UseRegisterOrConstantAtStart(instr->right());
   1622     return new(zone()) LCompareNumericAndBranch(left, right);
   1623   } else {
   1624     DCHECK(r.IsDouble());
   1625     DCHECK(instr->left()->representation().IsDouble());
   1626     DCHECK(instr->right()->representation().IsDouble());
   1627     LOperand* left = UseRegisterAtStart(instr->left());
   1628     LOperand* right = UseRegisterAtStart(instr->right());
   1629     return new(zone()) LCompareNumericAndBranch(left, right);
   1630   }
   1631 }
   1632 
   1633 
   1634 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch(
   1635     HCompareObjectEqAndBranch* instr) {
   1636   LOperand* left = UseRegisterAtStart(instr->left());
   1637   LOperand* right = UseRegisterAtStart(instr->right());
   1638   return new(zone()) LCmpObjectEqAndBranch(left, right);
   1639 }
   1640 
   1641 
   1642 LInstruction* LChunkBuilder::DoCompareHoleAndBranch(
   1643     HCompareHoleAndBranch* instr) {
   1644   LOperand* value = UseRegisterAtStart(instr->value());
   1645   return new(zone()) LCmpHoleAndBranch(value);
   1646 }
   1647 
   1648 
   1649 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
   1650   DCHECK(instr->value()->representation().IsTagged());
   1651   LOperand* temp = TempRegister();
   1652   return new(zone()) LIsStringAndBranch(UseRegisterAtStart(instr->value()),
   1653                                         temp);
   1654 }
   1655 
   1656 
   1657 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
   1658   DCHECK(instr->value()->representation().IsTagged());
   1659   return new(zone()) LIsSmiAndBranch(Use(instr->value()));
   1660 }
   1661 
   1662 
   1663 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
   1664     HIsUndetectableAndBranch* instr) {
   1665   DCHECK(instr->value()->representation().IsTagged());
   1666   return new(zone()) LIsUndetectableAndBranch(
   1667       UseRegisterAtStart(instr->value()), TempRegister());
   1668 }
   1669 
   1670 
   1671 LInstruction* LChunkBuilder::DoStringCompareAndBranch(
   1672     HStringCompareAndBranch* instr) {
   1673   DCHECK(instr->left()->representation().IsTagged());
   1674   DCHECK(instr->right()->representation().IsTagged());
   1675   LOperand* context = UseFixed(instr->context(), cp);
   1676   LOperand* left = UseFixed(instr->left(), a1);
   1677   LOperand* right = UseFixed(instr->right(), a0);
   1678   LStringCompareAndBranch* result =
   1679       new(zone()) LStringCompareAndBranch(context, left, right);
   1680   return MarkAsCall(result, instr);
   1681 }
   1682 
   1683 
   1684 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
   1685     HHasInstanceTypeAndBranch* instr) {
   1686   DCHECK(instr->value()->representation().IsTagged());
   1687   LOperand* value = UseRegisterAtStart(instr->value());
   1688   return new(zone()) LHasInstanceTypeAndBranch(value);
   1689 }
   1690 
   1691 
   1692 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
   1693     HGetCachedArrayIndex* instr)  {
   1694   DCHECK(instr->value()->representation().IsTagged());
   1695   LOperand* value = UseRegisterAtStart(instr->value());
   1696 
   1697   return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value));
   1698 }
   1699 
   1700 
   1701 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch(
   1702     HHasCachedArrayIndexAndBranch* instr) {
   1703   DCHECK(instr->value()->representation().IsTagged());
   1704   return new(zone()) LHasCachedArrayIndexAndBranch(
   1705       UseRegisterAtStart(instr->value()));
   1706 }
   1707 
   1708 
   1709 LInstruction* LChunkBuilder::DoClassOfTestAndBranch(
   1710     HClassOfTestAndBranch* instr) {
   1711   DCHECK(instr->value()->representation().IsTagged());
   1712   return new(zone()) LClassOfTestAndBranch(UseRegister(instr->value()),
   1713                                            TempRegister());
   1714 }
   1715 
   1716 
   1717 LInstruction* LChunkBuilder::DoSeqStringGetChar(HSeqStringGetChar* instr) {
   1718   LOperand* string = UseRegisterAtStart(instr->string());
   1719   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
   1720   return DefineAsRegister(new(zone()) LSeqStringGetChar(string, index));
   1721 }
   1722 
   1723 
   1724 LInstruction* LChunkBuilder::DoSeqStringSetChar(HSeqStringSetChar* instr) {
   1725   LOperand* string = UseRegisterAtStart(instr->string());
   1726   LOperand* index = FLAG_debug_code
   1727       ? UseRegisterAtStart(instr->index())
   1728       : UseRegisterOrConstantAtStart(instr->index());
   1729   LOperand* value = UseRegisterAtStart(instr->value());
   1730   LOperand* context = FLAG_debug_code ? UseFixed(instr->context(), cp) : NULL;
   1731   return new(zone()) LSeqStringSetChar(context, string, index, value);
   1732 }
   1733 
   1734 
   1735 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
   1736   if (!FLAG_debug_code && instr->skip_check()) return NULL;
   1737   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
   1738   LOperand* length = !index->IsConstantOperand()
   1739   ? UseRegisterOrConstantAtStart(instr->length())
   1740   : UseRegisterAtStart(instr->length());
   1741   LInstruction* result = new(zone()) LBoundsCheck(index, length);
   1742   if (!FLAG_debug_code || !instr->skip_check()) {
   1743     result = AssignEnvironment(result);
   1744   }
   1745 return result;
   1746 }
   1747 
   1748 
   1749 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
   1750   // The control instruction marking the end of a block that completed
   1751   // abruptly (e.g., threw an exception).  There is nothing specific to do.
   1752   return NULL;
   1753 }
   1754 
   1755 
   1756 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) {
   1757   return NULL;
   1758 }
   1759 
   1760 
   1761 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) {
   1762   // All HForceRepresentation instructions should be eliminated in the
   1763   // representation change phase of Hydrogen.
   1764   UNREACHABLE();
   1765   return NULL;
   1766 }
   1767 
   1768 
   1769 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
   1770   Representation from = instr->from();
   1771   Representation to = instr->to();
   1772   HValue* val = instr->value();
   1773   if (from.IsSmi()) {
   1774     if (to.IsTagged()) {
   1775       LOperand* value = UseRegister(val);
   1776       return DefineSameAsFirst(new(zone()) LDummyUse(value));
   1777     }
   1778     from = Representation::Tagged();
   1779   }
   1780   if (from.IsTagged()) {
   1781     if (to.IsDouble()) {
   1782       LOperand* value = UseRegister(val);
   1783       LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value));
   1784       if (!val->representation().IsSmi()) result = AssignEnvironment(result);
   1785       return result;
   1786     } else if (to.IsSmi()) {
   1787       LOperand* value = UseRegister(val);
   1788       if (val->type().IsSmi()) {
   1789         return DefineSameAsFirst(new(zone()) LDummyUse(value));
   1790       }
   1791       return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value)));
   1792     } else {
   1793       DCHECK(to.IsInteger32());
   1794       if (val->type().IsSmi() || val->representation().IsSmi()) {
   1795         LOperand* value = UseRegisterAtStart(val);
   1796         return DefineAsRegister(new(zone()) LSmiUntag(value, false));
   1797       } else {
   1798         LOperand* value = UseRegister(val);
   1799         LOperand* temp1 = TempRegister();
   1800         LOperand* temp2 = TempDoubleRegister();
   1801         LInstruction* result =
   1802             DefineSameAsFirst(new(zone()) LTaggedToI(value, temp1, temp2));
   1803         if (!val->representation().IsSmi()) result = AssignEnvironment(result);
   1804         return result;
   1805       }
   1806     }
   1807   } else if (from.IsDouble()) {
   1808     if (to.IsTagged()) {
   1809       info()->MarkAsDeferredCalling();
   1810       LOperand* value = UseRegister(val);
   1811       LOperand* temp1 = TempRegister();
   1812       LOperand* temp2 = TempRegister();
   1813 
   1814       LUnallocated* result_temp = TempRegister();
   1815       LNumberTagD* result = new(zone()) LNumberTagD(value, temp1, temp2);
   1816       return AssignPointerMap(Define(result, result_temp));
   1817     } else if (to.IsSmi()) {
   1818       LOperand* value = UseRegister(val);
   1819       return AssignEnvironment(
   1820           DefineAsRegister(new(zone()) LDoubleToSmi(value)));
   1821     } else {
   1822       DCHECK(to.IsInteger32());
   1823       LOperand* value = UseRegister(val);
   1824       LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value));
   1825       if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result);
   1826       return result;
   1827     }
   1828   } else if (from.IsInteger32()) {
   1829     info()->MarkAsDeferredCalling();
   1830     if (to.IsTagged()) {
   1831       if (val->CheckFlag(HInstruction::kUint32)) {
   1832         LOperand* value = UseRegisterAtStart(val);
   1833         LOperand* temp1 = TempRegister();
   1834         LOperand* temp2 = TempRegister();
   1835         LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2);
   1836         return AssignPointerMap(DefineAsRegister(result));
   1837       } else {
   1838         STATIC_ASSERT((kMinInt == Smi::kMinValue) &&
   1839                       (kMaxInt == Smi::kMaxValue));
   1840         LOperand* value = UseRegisterAtStart(val);
   1841         return DefineAsRegister(new(zone()) LSmiTag(value));
   1842       }
   1843     } else if (to.IsSmi()) {
   1844       LOperand* value = UseRegister(val);
   1845       LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value));
   1846       if (instr->CheckFlag(HValue::kCanOverflow)) {
   1847         result = AssignEnvironment(result);
   1848       }
   1849       return result;
   1850     } else {
   1851       DCHECK(to.IsDouble());
   1852       if (val->CheckFlag(HInstruction::kUint32)) {
   1853         return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val)));
   1854       } else {
   1855         return DefineAsRegister(new(zone()) LInteger32ToDouble(Use(val)));
   1856       }
   1857     }
   1858   }
   1859   UNREACHABLE();
   1860   return NULL;
   1861 }
   1862 
   1863 
   1864 LInstruction* LChunkBuilder::DoCheckHeapObject(HCheckHeapObject* instr) {
   1865   LOperand* value = UseRegisterAtStart(instr->value());
   1866   LInstruction* result = new(zone()) LCheckNonSmi(value);
   1867   if (!instr->value()->type().IsHeapObject()) {
   1868     result = AssignEnvironment(result);
   1869   }
   1870   return result;
   1871 }
   1872 
   1873 
   1874 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
   1875   LOperand* value = UseRegisterAtStart(instr->value());
   1876   return AssignEnvironment(new(zone()) LCheckSmi(value));
   1877 }
   1878 
   1879 
   1880 LInstruction* LChunkBuilder::DoCheckArrayBufferNotNeutered(
   1881     HCheckArrayBufferNotNeutered* instr) {
   1882   LOperand* view = UseRegisterAtStart(instr->value());
   1883   LCheckArrayBufferNotNeutered* result =
   1884       new (zone()) LCheckArrayBufferNotNeutered(view);
   1885   return AssignEnvironment(result);
   1886 }
   1887 
   1888 
   1889 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   1890   LOperand* value = UseRegisterAtStart(instr->value());
   1891   LInstruction* result = new(zone()) LCheckInstanceType(value);
   1892   return AssignEnvironment(result);
   1893 }
   1894 
   1895 
   1896 LInstruction* LChunkBuilder::DoCheckValue(HCheckValue* instr) {
   1897   LOperand* value = UseRegisterAtStart(instr->value());
   1898   return AssignEnvironment(new(zone()) LCheckValue(value));
   1899 }
   1900 
   1901 
   1902 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
   1903   if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
   1904   LOperand* value = UseRegisterAtStart(instr->value());
   1905   LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value));
   1906   if (instr->HasMigrationTarget()) {
   1907     info()->MarkAsDeferredCalling();
   1908     result = AssignPointerMap(result);
   1909   }
   1910   return result;
   1911 }
   1912 
   1913 
   1914 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
   1915   HValue* value = instr->value();
   1916   Representation input_rep = value->representation();
   1917   LOperand* reg = UseRegister(value);
   1918   if (input_rep.IsDouble()) {
   1919     // Revisit this decision, here and 8 lines below.
   1920     return DefineAsRegister(new(zone()) LClampDToUint8(reg,
   1921         TempDoubleRegister()));
   1922   } else if (input_rep.IsInteger32()) {
   1923     return DefineAsRegister(new(zone()) LClampIToUint8(reg));
   1924   } else {
   1925     DCHECK(input_rep.IsSmiOrTagged());
   1926     LClampTToUint8* result =
   1927         new(zone()) LClampTToUint8(reg, TempDoubleRegister());
   1928     return AssignEnvironment(DefineAsRegister(result));
   1929   }
   1930 }
   1931 
   1932 
   1933 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) {
   1934   HValue* value = instr->value();
   1935   DCHECK(value->representation().IsDouble());
   1936   return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value)));
   1937 }
   1938 
   1939 
   1940 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   1941   LOperand* context = info()->IsStub()
   1942       ? UseFixed(instr->context(), cp)
   1943       : NULL;
   1944   LOperand* parameter_count = UseRegisterOrConstant(instr->parameter_count());
   1945   return new(zone()) LReturn(UseFixed(instr->value(), v0), context,
   1946                              parameter_count);
   1947 }
   1948 
   1949 
   1950 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   1951   Representation r = instr->representation();
   1952   if (r.IsSmi()) {
   1953     return DefineAsRegister(new(zone()) LConstantS);
   1954   } else if (r.IsInteger32()) {
   1955     return DefineAsRegister(new(zone()) LConstantI);
   1956   } else if (r.IsDouble()) {
   1957     return DefineAsRegister(new(zone()) LConstantD);
   1958   } else if (r.IsExternal()) {
   1959     return DefineAsRegister(new(zone()) LConstantE);
   1960   } else if (r.IsTagged()) {
   1961     return DefineAsRegister(new(zone()) LConstantT);
   1962   } else {
   1963     UNREACHABLE();
   1964     return NULL;
   1965   }
   1966 }
   1967 
   1968 
   1969 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   1970   LOperand* context = UseFixed(instr->context(), cp);
   1971   LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
   1972 
   1973   LLoadGlobalGeneric* result = new (zone()) LLoadGlobalGeneric(context, vector);
   1974   return MarkAsCall(DefineFixed(result, v0), instr);
   1975 }
   1976 
   1977 
   1978 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   1979   LOperand* context = UseRegisterAtStart(instr->value());
   1980   LInstruction* result =
   1981       DefineAsRegister(new(zone()) LLoadContextSlot(context));
   1982   if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
   1983     result = AssignEnvironment(result);
   1984   }
   1985   return result;
   1986 }
   1987 
   1988 
   1989 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
   1990   LOperand* context;
   1991   LOperand* value;
   1992   if (instr->NeedsWriteBarrier()) {
   1993     context = UseTempRegister(instr->context());
   1994     value = UseTempRegister(instr->value());
   1995   } else {
   1996     context = UseRegister(instr->context());
   1997     value = UseRegister(instr->value());
   1998   }
   1999   LInstruction* result = new(zone()) LStoreContextSlot(context, value);
   2000   if (instr->RequiresHoleCheck() && instr->DeoptimizesOnHole()) {
   2001     result = AssignEnvironment(result);
   2002   }
   2003   return result;
   2004 }
   2005 
   2006 
   2007 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
   2008   LOperand* obj = UseRegisterAtStart(instr->object());
   2009   return DefineAsRegister(new(zone()) LLoadNamedField(obj));
   2010 }
   2011 
   2012 
   2013 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
   2014   LOperand* context = UseFixed(instr->context(), cp);
   2015   LOperand* object =
   2016       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   2017   LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
   2018 
   2019   LInstruction* result =
   2020       DefineFixed(new(zone()) LLoadNamedGeneric(context, object, vector), v0);
   2021   return MarkAsCall(result, instr);
   2022 }
   2023 
   2024 
   2025 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
   2026     HLoadFunctionPrototype* instr) {
   2027   return AssignEnvironment(DefineAsRegister(
   2028       new(zone()) LLoadFunctionPrototype(UseRegister(instr->function()))));
   2029 }
   2030 
   2031 
   2032 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) {
   2033   return DefineAsRegister(new(zone()) LLoadRoot);
   2034 }
   2035 
   2036 
   2037 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) {
   2038   DCHECK(instr->key()->representation().IsSmiOrInteger32());
   2039   ElementsKind elements_kind = instr->elements_kind();
   2040   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   2041   LInstruction* result = NULL;
   2042 
   2043   if (!instr->is_fixed_typed_array()) {
   2044     LOperand* obj = NULL;
   2045     if (instr->representation().IsDouble()) {
   2046       obj = UseRegister(instr->elements());
   2047     } else {
   2048       DCHECK(instr->representation().IsSmiOrTagged() ||
   2049              instr->representation().IsInteger32());
   2050       obj = UseRegisterAtStart(instr->elements());
   2051     }
   2052     result = DefineAsRegister(new (zone()) LLoadKeyed(obj, key, nullptr));
   2053   } else {
   2054     DCHECK(
   2055         (instr->representation().IsInteger32() &&
   2056          !IsDoubleOrFloatElementsKind(elements_kind)) ||
   2057         (instr->representation().IsDouble() &&
   2058          IsDoubleOrFloatElementsKind(elements_kind)));
   2059     LOperand* backing_store = UseRegister(instr->elements());
   2060     LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
   2061     result = DefineAsRegister(
   2062         new (zone()) LLoadKeyed(backing_store, key, backing_store_owner));
   2063   }
   2064 
   2065   bool needs_environment;
   2066   if (instr->is_fixed_typed_array()) {
   2067     // see LCodeGen::DoLoadKeyedExternalArray
   2068     needs_environment = elements_kind == UINT32_ELEMENTS &&
   2069                         !instr->CheckFlag(HInstruction::kUint32);
   2070   } else {
   2071     // see LCodeGen::DoLoadKeyedFixedDoubleArray and
   2072     // LCodeGen::DoLoadKeyedFixedArray
   2073     needs_environment =
   2074         instr->RequiresHoleCheck() ||
   2075         (instr->hole_mode() == CONVERT_HOLE_TO_UNDEFINED && info()->IsStub());
   2076   }
   2077 
   2078   if (needs_environment) {
   2079     result = AssignEnvironment(result);
   2080   }
   2081   return result;
   2082 }
   2083 
   2084 
   2085 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
   2086   LOperand* context = UseFixed(instr->context(), cp);
   2087   LOperand* object =
   2088       UseFixed(instr->object(), LoadDescriptor::ReceiverRegister());
   2089   LOperand* key = UseFixed(instr->key(), LoadDescriptor::NameRegister());
   2090   LOperand* vector = FixedTemp(LoadWithVectorDescriptor::VectorRegister());
   2091 
   2092   LInstruction* result =
   2093       DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key, vector),
   2094                   v0);
   2095   return MarkAsCall(result, instr);
   2096 }
   2097 
   2098 
   2099 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) {
   2100   if (!instr->is_fixed_typed_array()) {
   2101     DCHECK(instr->elements()->representation().IsTagged());
   2102     bool needs_write_barrier = instr->NeedsWriteBarrier();
   2103     LOperand* object = NULL;
   2104     LOperand* val = NULL;
   2105     LOperand* key = NULL;
   2106 
   2107     if (instr->value()->representation().IsDouble()) {
   2108       object = UseRegisterAtStart(instr->elements());
   2109       key = UseRegisterOrConstantAtStart(instr->key());
   2110       val = UseRegister(instr->value());
   2111     } else {
   2112       DCHECK(instr->value()->representation().IsSmiOrTagged() ||
   2113              instr->value()->representation().IsInteger32());
   2114       if (needs_write_barrier) {
   2115         object = UseTempRegister(instr->elements());
   2116         val = UseTempRegister(instr->value());
   2117         key = UseTempRegister(instr->key());
   2118       } else {
   2119         object = UseRegisterAtStart(instr->elements());
   2120         val = UseRegisterAtStart(instr->value());
   2121         key = UseRegisterOrConstantAtStart(instr->key());
   2122       }
   2123     }
   2124 
   2125     return new (zone()) LStoreKeyed(object, key, val, nullptr);
   2126   }
   2127 
   2128   DCHECK(
   2129       (instr->value()->representation().IsInteger32() &&
   2130        !IsDoubleOrFloatElementsKind(instr->elements_kind())) ||
   2131       (instr->value()->representation().IsDouble() &&
   2132        IsDoubleOrFloatElementsKind(instr->elements_kind())));
   2133   DCHECK(instr->elements()->representation().IsExternal());
   2134   LOperand* val = UseRegister(instr->value());
   2135   LOperand* key = UseRegisterOrConstantAtStart(instr->key());
   2136   LOperand* backing_store = UseRegister(instr->elements());
   2137   LOperand* backing_store_owner = UseAny(instr->backing_store_owner());
   2138   return new (zone()) LStoreKeyed(backing_store, key, val, backing_store_owner);
   2139 }
   2140 
   2141 
   2142 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   2143   LOperand* context = UseFixed(instr->context(), cp);
   2144   LOperand* obj =
   2145       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   2146   LOperand* key = UseFixed(instr->key(), StoreDescriptor::NameRegister());
   2147   LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
   2148 
   2149   DCHECK(instr->object()->representation().IsTagged());
   2150   DCHECK(instr->key()->representation().IsTagged());
   2151   DCHECK(instr->value()->representation().IsTagged());
   2152 
   2153   LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
   2154   LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
   2155 
   2156   LStoreKeyedGeneric* result =
   2157       new (zone()) LStoreKeyedGeneric(context, obj, key, val, slot, vector);
   2158   return MarkAsCall(result, instr);
   2159 }
   2160 
   2161 
   2162 LInstruction* LChunkBuilder::DoTransitionElementsKind(
   2163     HTransitionElementsKind* instr) {
   2164   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
   2165     LOperand* object = UseRegister(instr->object());
   2166     LOperand* new_map_reg = TempRegister();
   2167     LTransitionElementsKind* result =
   2168         new(zone()) LTransitionElementsKind(object, NULL, new_map_reg);
   2169     return result;
   2170   } else {
   2171     LOperand* object = UseFixed(instr->object(), a0);
   2172     LOperand* context = UseFixed(instr->context(), cp);
   2173     LTransitionElementsKind* result =
   2174         new(zone()) LTransitionElementsKind(object, context, NULL);
   2175     return MarkAsCall(result, instr);
   2176   }
   2177 }
   2178 
   2179 
   2180 LInstruction* LChunkBuilder::DoTrapAllocationMemento(
   2181     HTrapAllocationMemento* instr) {
   2182   LOperand* object = UseRegister(instr->object());
   2183   LOperand* temp = TempRegister();
   2184   LTrapAllocationMemento* result =
   2185       new(zone()) LTrapAllocationMemento(object, temp);
   2186   return AssignEnvironment(result);
   2187 }
   2188 
   2189 
   2190 LInstruction* LChunkBuilder::DoMaybeGrowElements(HMaybeGrowElements* instr) {
   2191   info()->MarkAsDeferredCalling();
   2192   LOperand* context = UseFixed(instr->context(), cp);
   2193   LOperand* object = Use(instr->object());
   2194   LOperand* elements = Use(instr->elements());
   2195   LOperand* key = UseRegisterOrConstant(instr->key());
   2196   LOperand* current_capacity = UseRegisterOrConstant(instr->current_capacity());
   2197 
   2198   LMaybeGrowElements* result = new (zone())
   2199       LMaybeGrowElements(context, object, elements, key, current_capacity);
   2200   DefineFixed(result, v0);
   2201   return AssignPointerMap(AssignEnvironment(result));
   2202 }
   2203 
   2204 
   2205 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   2206   bool is_in_object = instr->access().IsInobject();
   2207   bool needs_write_barrier = instr->NeedsWriteBarrier();
   2208   bool needs_write_barrier_for_map = instr->has_transition() &&
   2209       instr->NeedsWriteBarrierForMap();
   2210 
   2211   LOperand* obj;
   2212   if (needs_write_barrier) {
   2213     obj = is_in_object
   2214         ? UseRegister(instr->object())
   2215         : UseTempRegister(instr->object());
   2216   } else {
   2217     obj = needs_write_barrier_for_map
   2218         ? UseRegister(instr->object())
   2219         : UseRegisterAtStart(instr->object());
   2220   }
   2221 
   2222   LOperand* val;
   2223   if (needs_write_barrier) {
   2224     val = UseTempRegister(instr->value());
   2225   } else if (instr->field_representation().IsDouble()) {
   2226     val = UseRegisterAtStart(instr->value());
   2227   } else {
   2228     val = UseRegister(instr->value());
   2229   }
   2230 
   2231   // We need a temporary register for write barrier of the map field.
   2232   LOperand* temp = needs_write_barrier_for_map ? TempRegister() : NULL;
   2233 
   2234   return new(zone()) LStoreNamedField(obj, val, temp);
   2235 }
   2236 
   2237 
   2238 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
   2239   LOperand* context = UseFixed(instr->context(), cp);
   2240   LOperand* obj =
   2241       UseFixed(instr->object(), StoreDescriptor::ReceiverRegister());
   2242   LOperand* val = UseFixed(instr->value(), StoreDescriptor::ValueRegister());
   2243   LOperand* slot = FixedTemp(VectorStoreICDescriptor::SlotRegister());
   2244   LOperand* vector = FixedTemp(VectorStoreICDescriptor::VectorRegister());
   2245 
   2246   LStoreNamedGeneric* result =
   2247       new (zone()) LStoreNamedGeneric(context, obj, val, slot, vector);
   2248   return MarkAsCall(result, instr);
   2249 }
   2250 
   2251 
   2252 LInstruction* LChunkBuilder::DoStringAdd(HStringAdd* instr) {
   2253   LOperand* context = UseFixed(instr->context(), cp);
   2254   LOperand* left = UseFixed(instr->left(), a1);
   2255   LOperand* right = UseFixed(instr->right(), a0);
   2256   return MarkAsCall(
   2257       DefineFixed(new(zone()) LStringAdd(context, left, right), v0),
   2258       instr);
   2259 }
   2260 
   2261 
   2262 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
   2263   LOperand* string = UseTempRegister(instr->string());
   2264   LOperand* index = UseTempRegister(instr->index());
   2265   LOperand* context = UseAny(instr->context());
   2266   LStringCharCodeAt* result =
   2267       new(zone()) LStringCharCodeAt(context, string, index);
   2268   return AssignPointerMap(DefineAsRegister(result));
   2269 }
   2270 
   2271 
   2272 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
   2273   LOperand* char_code = UseRegister(instr->value());
   2274   LOperand* context = UseAny(instr->context());
   2275   LStringCharFromCode* result =
   2276       new(zone()) LStringCharFromCode(context, char_code);
   2277   return AssignPointerMap(DefineAsRegister(result));
   2278 }
   2279 
   2280 
   2281 LInstruction* LChunkBuilder::DoAllocate(HAllocate* instr) {
   2282   LOperand* size = UseRegisterOrConstant(instr->size());
   2283   LOperand* temp1 = TempRegister();
   2284   LOperand* temp2 = TempRegister();
   2285   if (instr->IsAllocationFolded()) {
   2286     LFastAllocate* result = new (zone()) LFastAllocate(size, temp1, temp2);
   2287     return DefineAsRegister(result);
   2288   } else {
   2289     info()->MarkAsDeferredCalling();
   2290     LOperand* context = UseAny(instr->context());
   2291     LAllocate* result = new (zone()) LAllocate(context, size, temp1, temp2);
   2292     return AssignPointerMap(DefineAsRegister(result));
   2293   }
   2294 }
   2295 
   2296 
   2297 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
   2298   DCHECK(argument_count_ == 0);
   2299   allocator_->MarkAsOsrEntry();
   2300   current_block_->last_environment()->set_ast_id(instr->ast_id());
   2301   return AssignEnvironment(new(zone()) LOsrEntry);
   2302 }
   2303 
   2304 
   2305 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
   2306   LParameter* result = new(zone()) LParameter;
   2307   if (instr->kind() == HParameter::STACK_PARAMETER) {
   2308     int spill_index = chunk()->GetParameterStackSlot(instr->index());
   2309     return DefineAsSpilled(result, spill_index);
   2310   } else {
   2311     DCHECK(info()->IsStub());
   2312     CallInterfaceDescriptor descriptor = graph()->descriptor();
   2313     int index = static_cast<int>(instr->index());
   2314     Register reg = descriptor.GetRegisterParameter(index);
   2315     return DefineFixed(result, reg);
   2316   }
   2317 }
   2318 
   2319 
   2320 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
   2321   // Use an index that corresponds to the location in the unoptimized frame,
   2322   // which the optimized frame will subsume.
   2323   int env_index = instr->index();
   2324   int spill_index = 0;
   2325   if (instr->environment()->is_parameter_index(env_index)) {
   2326     spill_index = chunk()->GetParameterStackSlot(env_index);
   2327   } else {
   2328     spill_index = env_index - instr->environment()->first_local_index();
   2329     if (spill_index > LUnallocated::kMaxFixedSlotIndex) {
   2330       Retry(kTooManySpillSlotsNeededForOSR);
   2331       spill_index = 0;
   2332     }
   2333     spill_index += StandardFrameConstants::kFixedSlotCount;
   2334   }
   2335   return DefineAsSpilled(new(zone()) LUnknownOSRValue, spill_index);
   2336 }
   2337 
   2338 
   2339 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
   2340   // There are no real uses of the arguments object.
   2341   // arguments.length and element access are supported directly on
   2342   // stack arguments, and any real arguments object use causes a bailout.
   2343   // So this value is never used.
   2344   return NULL;
   2345 }
   2346 
   2347 
   2348 LInstruction* LChunkBuilder::DoCapturedObject(HCapturedObject* instr) {
   2349   instr->ReplayEnvironment(current_block_->last_environment());
   2350 
   2351   // There are no real uses of a captured object.
   2352   return NULL;
   2353 }
   2354 
   2355 
   2356 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
   2357   info()->MarkAsRequiresFrame();
   2358   LOperand* args = UseRegister(instr->arguments());
   2359   LOperand* length = UseRegisterOrConstantAtStart(instr->length());
   2360   LOperand* index = UseRegisterOrConstantAtStart(instr->index());
   2361   return DefineAsRegister(new(zone()) LAccessArgumentsAt(args, length, index));
   2362 }
   2363 
   2364 
   2365 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
   2366   LOperand* context = UseFixed(instr->context(), cp);
   2367   LOperand* value = UseFixed(instr->value(), a3);
   2368   LTypeof* result = new (zone()) LTypeof(context, value);
   2369   return MarkAsCall(DefineFixed(result, v0), instr);
   2370 }
   2371 
   2372 
   2373 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) {
   2374   return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
   2375 }
   2376 
   2377 
   2378 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
   2379   instr->ReplayEnvironment(current_block_->last_environment());
   2380   return NULL;
   2381 }
   2382 
   2383 
   2384 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
   2385   if (instr->is_function_entry()) {
   2386     LOperand* context = UseFixed(instr->context(), cp);
   2387     return MarkAsCall(new(zone()) LStackCheck(context), instr);
   2388   } else {
   2389     DCHECK(instr->is_backwards_branch());
   2390     LOperand* context = UseAny(instr->context());
   2391     return AssignEnvironment(
   2392         AssignPointerMap(new(zone()) LStackCheck(context)));
   2393   }
   2394 }
   2395 
   2396 
   2397 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
   2398   HEnvironment* outer = current_block_->last_environment();
   2399   outer->set_ast_id(instr->ReturnId());
   2400   HConstant* undefined = graph()->GetConstantUndefined();
   2401   HEnvironment* inner = outer->CopyForInlining(
   2402       instr->closure(), instr->arguments_count(), instr->function(), undefined,
   2403       instr->inlining_kind(), instr->syntactic_tail_call_mode());
   2404   // Only replay binding of arguments object if it wasn't removed from graph.
   2405   if (instr->arguments_var() != NULL && instr->arguments_object()->IsLinked()) {
   2406     inner->Bind(instr->arguments_var(), instr->arguments_object());
   2407   }
   2408   inner->BindContext(instr->closure_context());
   2409   inner->set_entry(instr);
   2410   current_block_->UpdateEnvironment(inner);
   2411   chunk_->AddInlinedFunction(instr->shared());
   2412   return NULL;
   2413 }
   2414 
   2415 
   2416 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
   2417   LInstruction* pop = NULL;
   2418 
   2419   HEnvironment* env = current_block_->last_environment();
   2420 
   2421   if (env->entry()->arguments_pushed()) {
   2422     int argument_count = env->arguments_environment()->parameter_count();
   2423     pop = new(zone()) LDrop(argument_count);
   2424     DCHECK(instr->argument_delta() == -argument_count);
   2425   }
   2426 
   2427   HEnvironment* outer = current_block_->last_environment()->
   2428       DiscardInlined(false);
   2429   current_block_->UpdateEnvironment(outer);
   2430 
   2431   return pop;
   2432 }
   2433 
   2434 
   2435 LInstruction* LChunkBuilder::DoForInPrepareMap(HForInPrepareMap* instr) {
   2436   LOperand* context = UseFixed(instr->context(), cp);
   2437   LOperand* object = UseFixed(instr->enumerable(), a0);
   2438   LForInPrepareMap* result = new(zone()) LForInPrepareMap(context, object);
   2439   return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
   2440 }
   2441 
   2442 
   2443 LInstruction* LChunkBuilder::DoForInCacheArray(HForInCacheArray* instr) {
   2444   LOperand* map = UseRegister(instr->map());
   2445   return AssignEnvironment(DefineAsRegister(new(zone()) LForInCacheArray(map)));
   2446 }
   2447 
   2448 
   2449 LInstruction* LChunkBuilder::DoCheckMapValue(HCheckMapValue* instr) {
   2450   LOperand* value = UseRegisterAtStart(instr->value());
   2451   LOperand* map = UseRegisterAtStart(instr->map());
   2452   return AssignEnvironment(new(zone()) LCheckMapValue(value, map));
   2453 }
   2454 
   2455 
   2456 LInstruction* LChunkBuilder::DoLoadFieldByIndex(HLoadFieldByIndex* instr) {
   2457   LOperand* object = UseRegister(instr->object());
   2458   LOperand* index = UseTempRegister(instr->index());
   2459   LLoadFieldByIndex* load = new(zone()) LLoadFieldByIndex(object, index);
   2460   LInstruction* result = DefineSameAsFirst(load);
   2461   return AssignPointerMap(result);
   2462 }
   2463 
   2464 }  // namespace internal
   2465 }  // namespace v8
   2466 
   2467 #endif  // V8_TARGET_ARCH_MIPS64
   2468