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