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