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