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