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