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