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