Home | History | Annotate | Download | only in ia32
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "v8.h"
     29 
     30 #if defined(V8_TARGET_ARCH_IA32)
     31 
     32 #include "lithium-allocator-inl.h"
     33 #include "ia32/lithium-ia32.h"
     34 #include "ia32/lithium-codegen-ia32.h"
     35 
     36 namespace v8 {
     37 namespace internal {
     38 
     39 #define DEFINE_COMPILE(type)                            \
     40   void L##type::CompileToNative(LCodeGen* generator) {  \
     41     generator->Do##type(this);                          \
     42   }
     43 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE)
     44 #undef DEFINE_COMPILE
     45 
     46 LOsrEntry::LOsrEntry() {
     47   for (int i = 0; i < Register::kNumAllocatableRegisters; ++i) {
     48     register_spills_[i] = NULL;
     49   }
     50   for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; ++i) {
     51     double_register_spills_[i] = NULL;
     52   }
     53 }
     54 
     55 
     56 void LOsrEntry::MarkSpilledRegister(int allocation_index,
     57                                     LOperand* spill_operand) {
     58   ASSERT(spill_operand->IsStackSlot());
     59   ASSERT(register_spills_[allocation_index] == NULL);
     60   register_spills_[allocation_index] = spill_operand;
     61 }
     62 
     63 
     64 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index,
     65                                           LOperand* spill_operand) {
     66   ASSERT(spill_operand->IsDoubleStackSlot());
     67   ASSERT(double_register_spills_[allocation_index] == NULL);
     68   double_register_spills_[allocation_index] = spill_operand;
     69 }
     70 
     71 
     72 #ifdef DEBUG
     73 void LInstruction::VerifyCall() {
     74   // Call instructions can use only fixed registers as
     75   // temporaries and outputs because all registers
     76   // are blocked by the calling convention.
     77   // Inputs must use a fixed register.
     78   ASSERT(Output() == NULL ||
     79          LUnallocated::cast(Output())->HasFixedPolicy() ||
     80          !LUnallocated::cast(Output())->HasRegisterPolicy());
     81   for (UseIterator it(this); it.HasNext(); it.Advance()) {
     82     LOperand* operand = it.Next();
     83     ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
     84            !LUnallocated::cast(operand)->HasRegisterPolicy());
     85   }
     86   for (TempIterator it(this); it.HasNext(); it.Advance()) {
     87     LOperand* operand = it.Next();
     88     ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() ||
     89            !LUnallocated::cast(operand)->HasRegisterPolicy());
     90   }
     91 }
     92 #endif
     93 
     94 
     95 void LInstruction::PrintTo(StringStream* stream) {
     96   stream->Add("%s ", this->Mnemonic());
     97 
     98   PrintOutputOperandTo(stream);
     99 
    100   PrintDataTo(stream);
    101 
    102   if (HasEnvironment()) {
    103     stream->Add(" ");
    104     environment()->PrintTo(stream);
    105   }
    106 
    107   if (HasPointerMap()) {
    108     stream->Add(" ");
    109     pointer_map()->PrintTo(stream);
    110   }
    111 }
    112 
    113 
    114 template<int R, int I, int T>
    115 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) {
    116   stream->Add("= ");
    117   inputs_.PrintOperandsTo(stream);
    118 }
    119 
    120 
    121 template<int R, int I, int T>
    122 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) {
    123   results_.PrintOperandsTo(stream);
    124 }
    125 
    126 
    127 template<typename T, int N>
    128 void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) {
    129   for (int i = 0; i < N; i++) {
    130     if (i > 0) stream->Add(" ");
    131     elems_[i]->PrintTo(stream);
    132   }
    133 }
    134 
    135 
    136 void LLabel::PrintDataTo(StringStream* stream) {
    137   LGap::PrintDataTo(stream);
    138   LLabel* rep = replacement();
    139   if (rep != NULL) {
    140     stream->Add(" Dead block replaced with B%d", rep->block_id());
    141   }
    142 }
    143 
    144 
    145 bool LGap::IsRedundant() const {
    146   for (int i = 0; i < 4; i++) {
    147     if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) {
    148       return false;
    149     }
    150   }
    151 
    152   return true;
    153 }
    154 
    155 
    156 void LGap::PrintDataTo(StringStream* stream) {
    157   for (int i = 0; i < 4; i++) {
    158     stream->Add("(");
    159     if (parallel_moves_[i] != NULL) {
    160       parallel_moves_[i]->PrintDataTo(stream);
    161     }
    162     stream->Add(") ");
    163   }
    164 }
    165 
    166 
    167 const char* LArithmeticD::Mnemonic() const {
    168   switch (op()) {
    169     case Token::ADD: return "add-d";
    170     case Token::SUB: return "sub-d";
    171     case Token::MUL: return "mul-d";
    172     case Token::DIV: return "div-d";
    173     case Token::MOD: return "mod-d";
    174     default:
    175       UNREACHABLE();
    176       return NULL;
    177   }
    178 }
    179 
    180 
    181 const char* LArithmeticT::Mnemonic() const {
    182   switch (op()) {
    183     case Token::ADD: return "add-t";
    184     case Token::SUB: return "sub-t";
    185     case Token::MUL: return "mul-t";
    186     case Token::MOD: return "mod-t";
    187     case Token::DIV: return "div-t";
    188     case Token::BIT_AND: return "bit-and-t";
    189     case Token::BIT_OR: return "bit-or-t";
    190     case Token::BIT_XOR: return "bit-xor-t";
    191     case Token::SHL: return "sal-t";
    192     case Token::SAR: return "sar-t";
    193     case Token::SHR: return "shr-t";
    194     default:
    195       UNREACHABLE();
    196       return NULL;
    197   }
    198 }
    199 
    200 
    201 void LGoto::PrintDataTo(StringStream* stream) {
    202   stream->Add("B%d", block_id());
    203 }
    204 
    205 
    206 void LBranch::PrintDataTo(StringStream* stream) {
    207   stream->Add("B%d | B%d on ", true_block_id(), false_block_id());
    208   InputAt(0)->PrintTo(stream);
    209 }
    210 
    211 
    212 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) {
    213   stream->Add("if ");
    214   InputAt(0)->PrintTo(stream);
    215   stream->Add(" %s ", Token::String(op()));
    216   InputAt(1)->PrintTo(stream);
    217   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
    218 }
    219 
    220 
    221 void LIsNullAndBranch::PrintDataTo(StringStream* stream) {
    222   stream->Add("if ");
    223   InputAt(0)->PrintTo(stream);
    224   stream->Add(is_strict() ? " === null" : " == null");
    225   stream->Add(" then B%d else B%d", true_block_id(), false_block_id());
    226 }
    227 
    228 
    229 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
    230   stream->Add("if is_object(");
    231   InputAt(0)->PrintTo(stream);
    232   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    233 }
    234 
    235 
    236 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
    237   stream->Add("if is_smi(");
    238   InputAt(0)->PrintTo(stream);
    239   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    240 }
    241 
    242 
    243 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
    244   stream->Add("if has_instance_type(");
    245   InputAt(0)->PrintTo(stream);
    246   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    247 }
    248 
    249 
    250 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) {
    251   stream->Add("if has_cached_array_index(");
    252   InputAt(0)->PrintTo(stream);
    253   stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
    254 }
    255 
    256 
    257 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) {
    258   stream->Add("if class_of_test(");
    259   InputAt(0)->PrintTo(stream);
    260   stream->Add(", \"%o\") then B%d else B%d",
    261               *hydrogen()->class_name(),
    262               true_block_id(),
    263               false_block_id());
    264 }
    265 
    266 
    267 void LTypeofIs::PrintDataTo(StringStream* stream) {
    268   InputAt(0)->PrintTo(stream);
    269   stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString());
    270 }
    271 
    272 
    273 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) {
    274   stream->Add("if typeof ");
    275   InputAt(0)->PrintTo(stream);
    276   stream->Add(" == \"%s\" then B%d else B%d",
    277               *hydrogen()->type_literal()->ToCString(),
    278               true_block_id(), false_block_id());
    279 }
    280 
    281 
    282 void LCallConstantFunction::PrintDataTo(StringStream* stream) {
    283   stream->Add("#%d / ", arity());
    284 }
    285 
    286 
    287 void LUnaryMathOperation::PrintDataTo(StringStream* stream) {
    288   stream->Add("/%s ", hydrogen()->OpName());
    289   InputAt(0)->PrintTo(stream);
    290 }
    291 
    292 
    293 void LLoadContextSlot::PrintDataTo(StringStream* stream) {
    294   InputAt(0)->PrintTo(stream);
    295   stream->Add("[%d]", slot_index());
    296 }
    297 
    298 
    299 void LStoreContextSlot::PrintDataTo(StringStream* stream) {
    300   InputAt(0)->PrintTo(stream);
    301   stream->Add("[%d] <- ", slot_index());
    302   InputAt(1)->PrintTo(stream);
    303 }
    304 
    305 
    306 void LCallKeyed::PrintDataTo(StringStream* stream) {
    307   stream->Add("[ecx] #%d / ", arity());
    308 }
    309 
    310 
    311 void LCallNamed::PrintDataTo(StringStream* stream) {
    312   SmartPointer<char> name_string = name()->ToCString();
    313   stream->Add("%s #%d / ", *name_string, arity());
    314 }
    315 
    316 
    317 void LCallGlobal::PrintDataTo(StringStream* stream) {
    318   SmartPointer<char> name_string = name()->ToCString();
    319   stream->Add("%s #%d / ", *name_string, arity());
    320 }
    321 
    322 
    323 void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
    324   stream->Add("#%d / ", arity());
    325 }
    326 
    327 
    328 void LCallNew::PrintDataTo(StringStream* stream) {
    329   stream->Add("= ");
    330   InputAt(0)->PrintTo(stream);
    331   stream->Add(" #%d / ", arity());
    332 }
    333 
    334 
    335 void LClassOfTest::PrintDataTo(StringStream* stream) {
    336   stream->Add("= class_of_test(");
    337   InputAt(0)->PrintTo(stream);
    338   stream->Add(", \"%o\")", *hydrogen()->class_name());
    339 }
    340 
    341 
    342 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
    343   arguments()->PrintTo(stream);
    344 
    345   stream->Add(" length ");
    346   length()->PrintTo(stream);
    347 
    348   stream->Add(" index ");
    349   index()->PrintTo(stream);
    350 }
    351 
    352 
    353 int LChunk::GetNextSpillIndex(bool is_double) {
    354   // Skip a slot if for a double-width slot.
    355   if (is_double) spill_slot_count_++;
    356   return spill_slot_count_++;
    357 }
    358 
    359 
    360 LOperand* LChunk::GetNextSpillSlot(bool is_double) {
    361   int index = GetNextSpillIndex(is_double);
    362   if (is_double) {
    363     return LDoubleStackSlot::Create(index);
    364   } else {
    365     return LStackSlot::Create(index);
    366   }
    367 }
    368 
    369 
    370 void LChunk::MarkEmptyBlocks() {
    371   HPhase phase("Mark empty blocks", this);
    372   for (int i = 0; i < graph()->blocks()->length(); ++i) {
    373     HBasicBlock* block = graph()->blocks()->at(i);
    374     int first = block->first_instruction_index();
    375     int last = block->last_instruction_index();
    376     LInstruction* first_instr = instructions()->at(first);
    377     LInstruction* last_instr = instructions()->at(last);
    378 
    379     LLabel* label = LLabel::cast(first_instr);
    380     if (last_instr->IsGoto()) {
    381       LGoto* goto_instr = LGoto::cast(last_instr);
    382       if (!goto_instr->include_stack_check() &&
    383           label->IsRedundant() &&
    384           !label->is_loop_header()) {
    385         bool can_eliminate = true;
    386         for (int i = first + 1; i < last && can_eliminate; ++i) {
    387           LInstruction* cur = instructions()->at(i);
    388           if (cur->IsGap()) {
    389             LGap* gap = LGap::cast(cur);
    390             if (!gap->IsRedundant()) {
    391               can_eliminate = false;
    392             }
    393           } else {
    394             can_eliminate = false;
    395           }
    396         }
    397 
    398         if (can_eliminate) {
    399           label->set_replacement(GetLabel(goto_instr->block_id()));
    400         }
    401       }
    402     }
    403   }
    404 }
    405 
    406 
    407 void LStoreNamedField::PrintDataTo(StringStream* stream) {
    408   object()->PrintTo(stream);
    409   stream->Add(".");
    410   stream->Add(*String::cast(*name())->ToCString());
    411   stream->Add(" <- ");
    412   value()->PrintTo(stream);
    413 }
    414 
    415 
    416 void LStoreNamedGeneric::PrintDataTo(StringStream* stream) {
    417   object()->PrintTo(stream);
    418   stream->Add(".");
    419   stream->Add(*String::cast(*name())->ToCString());
    420   stream->Add(" <- ");
    421   value()->PrintTo(stream);
    422 }
    423 
    424 
    425 void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
    426   object()->PrintTo(stream);
    427   stream->Add("[");
    428   key()->PrintTo(stream);
    429   stream->Add("] <- ");
    430   value()->PrintTo(stream);
    431 }
    432 
    433 
    434 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
    435   object()->PrintTo(stream);
    436   stream->Add("[");
    437   key()->PrintTo(stream);
    438   stream->Add("] <- ");
    439   value()->PrintTo(stream);
    440 }
    441 
    442 
    443 void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) {
    444   LGap* gap = new LGap(block);
    445   int index = -1;
    446   if (instr->IsControl()) {
    447     instructions_.Add(gap);
    448     index = instructions_.length();
    449     instructions_.Add(instr);
    450   } else {
    451     index = instructions_.length();
    452     instructions_.Add(instr);
    453     instructions_.Add(gap);
    454   }
    455   if (instr->HasPointerMap()) {
    456     pointer_maps_.Add(instr->pointer_map());
    457     instr->pointer_map()->set_lithium_position(index);
    458   }
    459 }
    460 
    461 
    462 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) {
    463   return LConstantOperand::Create(constant->id());
    464 }
    465 
    466 
    467 int LChunk::GetParameterStackSlot(int index) const {
    468   // The receiver is at index 0, the first parameter at index 1, so we
    469   // shift all parameter indexes down by the number of parameters, and
    470   // make sure they end up negative so they are distinguishable from
    471   // spill slots.
    472   int result = index - info()->scope()->num_parameters() - 1;
    473   ASSERT(result < 0);
    474   return result;
    475 }
    476 
    477 // A parameter relative to ebp in the arguments stub.
    478 int LChunk::ParameterAt(int index) {
    479   ASSERT(-1 <= index);  // -1 is the receiver.
    480   return (1 + info()->scope()->num_parameters() - index) *
    481       kPointerSize;
    482 }
    483 
    484 
    485 LGap* LChunk::GetGapAt(int index) const {
    486   return LGap::cast(instructions_[index]);
    487 }
    488 
    489 
    490 bool LChunk::IsGapAt(int index) const {
    491   return instructions_[index]->IsGap();
    492 }
    493 
    494 
    495 int LChunk::NearestGapPos(int index) const {
    496   while (!IsGapAt(index)) index--;
    497   return index;
    498 }
    499 
    500 
    501 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) {
    502   GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to);
    503 }
    504 
    505 
    506 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const {
    507   return HConstant::cast(graph_->LookupValue(operand->index()))->handle();
    508 }
    509 
    510 
    511 Representation LChunk::LookupLiteralRepresentation(
    512     LConstantOperand* operand) const {
    513   return graph_->LookupValue(operand->index())->representation();
    514 }
    515 
    516 
    517 LChunk* LChunkBuilder::Build() {
    518   ASSERT(is_unused());
    519   chunk_ = new LChunk(info(), graph());
    520   HPhase phase("Building chunk", chunk_);
    521   status_ = BUILDING;
    522   const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
    523   for (int i = 0; i < blocks->length(); i++) {
    524     HBasicBlock* next = NULL;
    525     if (i < blocks->length() - 1) next = blocks->at(i + 1);
    526     DoBasicBlock(blocks->at(i), next);
    527     if (is_aborted()) return NULL;
    528   }
    529   status_ = DONE;
    530   return chunk_;
    531 }
    532 
    533 
    534 void LChunkBuilder::Abort(const char* format, ...) {
    535   if (FLAG_trace_bailout) {
    536     SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
    537     PrintF("Aborting LChunk building in @\"%s\": ", *name);
    538     va_list arguments;
    539     va_start(arguments, format);
    540     OS::VPrint(format, arguments);
    541     va_end(arguments);
    542     PrintF("\n");
    543   }
    544   status_ = ABORTED;
    545 }
    546 
    547 
    548 LRegister* LChunkBuilder::ToOperand(Register reg) {
    549   return LRegister::Create(Register::ToAllocationIndex(reg));
    550 }
    551 
    552 
    553 LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
    554   return new LUnallocated(LUnallocated::FIXED_REGISTER,
    555                           Register::ToAllocationIndex(reg));
    556 }
    557 
    558 
    559 LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
    560   return new LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
    561                           XMMRegister::ToAllocationIndex(reg));
    562 }
    563 
    564 
    565 LOperand* LChunkBuilder::UseFixed(HValue* value, Register fixed_register) {
    566   return Use(value, ToUnallocated(fixed_register));
    567 }
    568 
    569 
    570 LOperand* LChunkBuilder::UseFixedDouble(HValue* value, XMMRegister reg) {
    571   return Use(value, ToUnallocated(reg));
    572 }
    573 
    574 
    575 LOperand* LChunkBuilder::UseRegister(HValue* value) {
    576   return Use(value, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
    577 }
    578 
    579 
    580 LOperand* LChunkBuilder::UseRegisterAtStart(HValue* value) {
    581   return Use(value,
    582              new LUnallocated(LUnallocated::MUST_HAVE_REGISTER,
    583                               LUnallocated::USED_AT_START));
    584 }
    585 
    586 
    587 LOperand* LChunkBuilder::UseTempRegister(HValue* value) {
    588   return Use(value, new LUnallocated(LUnallocated::WRITABLE_REGISTER));
    589 }
    590 
    591 
    592 LOperand* LChunkBuilder::Use(HValue* value) {
    593   return Use(value, new LUnallocated(LUnallocated::NONE));
    594 }
    595 
    596 
    597 LOperand* LChunkBuilder::UseAtStart(HValue* value) {
    598   return Use(value, new LUnallocated(LUnallocated::NONE,
    599                                      LUnallocated::USED_AT_START));
    600 }
    601 
    602 
    603 LOperand* LChunkBuilder::UseOrConstant(HValue* value) {
    604   return value->IsConstant()
    605       ? chunk_->DefineConstantOperand(HConstant::cast(value))
    606       : Use(value);
    607 }
    608 
    609 
    610 LOperand* LChunkBuilder::UseOrConstantAtStart(HValue* value) {
    611   return value->IsConstant()
    612       ? chunk_->DefineConstantOperand(HConstant::cast(value))
    613       : UseAtStart(value);
    614 }
    615 
    616 
    617 LOperand* LChunkBuilder::UseRegisterOrConstant(HValue* value) {
    618   return value->IsConstant()
    619       ? chunk_->DefineConstantOperand(HConstant::cast(value))
    620       : UseRegister(value);
    621 }
    622 
    623 
    624 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) {
    625   return value->IsConstant()
    626       ? chunk_->DefineConstantOperand(HConstant::cast(value))
    627       : UseRegisterAtStart(value);
    628 }
    629 
    630 
    631 LOperand* LChunkBuilder::UseAny(HValue* value) {
    632   return value->IsConstant()
    633       ? chunk_->DefineConstantOperand(HConstant::cast(value))
    634       :  Use(value, new LUnallocated(LUnallocated::ANY));
    635 }
    636 
    637 
    638 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
    639   if (value->EmitAtUses()) {
    640     HInstruction* instr = HInstruction::cast(value);
    641     VisitInstruction(instr);
    642   }
    643   allocator_->RecordUse(value, operand);
    644   return operand;
    645 }
    646 
    647 
    648 template<int I, int T>
    649 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
    650                                     LUnallocated* result) {
    651   allocator_->RecordDefinition(current_instruction_, result);
    652   instr->set_result(result);
    653   return instr;
    654 }
    655 
    656 
    657 template<int I, int T>
    658 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) {
    659   return Define(instr, new LUnallocated(LUnallocated::NONE));
    660 }
    661 
    662 
    663 template<int I, int T>
    664 LInstruction* LChunkBuilder::DefineAsRegister(
    665     LTemplateInstruction<1, I, T>* instr) {
    666   return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
    667 }
    668 
    669 
    670 template<int I, int T>
    671 LInstruction* LChunkBuilder::DefineAsSpilled(
    672     LTemplateInstruction<1, I, T>* instr,
    673     int index) {
    674   return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index));
    675 }
    676 
    677 
    678 template<int I, int T>
    679 LInstruction* LChunkBuilder::DefineSameAsFirst(
    680     LTemplateInstruction<1, I, T>* instr) {
    681   return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
    682 }
    683 
    684 
    685 template<int I, int T>
    686 LInstruction* LChunkBuilder::DefineFixed(LTemplateInstruction<1, I, T>* instr,
    687                                          Register reg) {
    688   return Define(instr, ToUnallocated(reg));
    689 }
    690 
    691 
    692 template<int I, int T>
    693 LInstruction* LChunkBuilder::DefineFixedDouble(
    694     LTemplateInstruction<1, I, T>* instr,
    695     XMMRegister reg) {
    696   return Define(instr, ToUnallocated(reg));
    697 }
    698 
    699 
    700 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) {
    701   HEnvironment* hydrogen_env = current_block_->last_environment();
    702   instr->set_environment(CreateEnvironment(hydrogen_env));
    703   return instr;
    704 }
    705 
    706 
    707 LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment(
    708     LInstruction* instr, int ast_id) {
    709   ASSERT(instruction_pending_deoptimization_environment_ == NULL);
    710   ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber);
    711   instruction_pending_deoptimization_environment_ = instr;
    712   pending_deoptimization_ast_id_ = ast_id;
    713   return instr;
    714 }
    715 
    716 
    717 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() {
    718   instruction_pending_deoptimization_environment_ = NULL;
    719   pending_deoptimization_ast_id_ = AstNode::kNoNumber;
    720 }
    721 
    722 
    723 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr,
    724                                         HInstruction* hinstr,
    725                                         CanDeoptimize can_deoptimize) {
    726 #ifdef DEBUG
    727   instr->VerifyCall();
    728 #endif
    729   instr->MarkAsCall();
    730   instr = AssignPointerMap(instr);
    731 
    732   if (hinstr->HasSideEffects()) {
    733     ASSERT(hinstr->next()->IsSimulate());
    734     HSimulate* sim = HSimulate::cast(hinstr->next());
    735     instr = SetInstructionPendingDeoptimizationEnvironment(
    736         instr, sim->ast_id());
    737   }
    738 
    739   // If instruction does not have side-effects lazy deoptimization
    740   // after the call will try to deoptimize to the point before the call.
    741   // Thus we still need to attach environment to this call even if
    742   // call sequence can not deoptimize eagerly.
    743   bool needs_environment =
    744       (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects();
    745   if (needs_environment && !instr->HasEnvironment()) {
    746     instr = AssignEnvironment(instr);
    747   }
    748 
    749   return instr;
    750 }
    751 
    752 
    753 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) {
    754   instr->MarkAsSaveDoubles();
    755   return instr;
    756 }
    757 
    758 
    759 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) {
    760   ASSERT(!instr->HasPointerMap());
    761   instr->set_pointer_map(new LPointerMap(position_));
    762   return instr;
    763 }
    764 
    765 
    766 LUnallocated* LChunkBuilder::TempRegister() {
    767   LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER);
    768   allocator_->RecordTemporary(operand);
    769   return operand;
    770 }
    771 
    772 
    773 LOperand* LChunkBuilder::FixedTemp(Register reg) {
    774   LUnallocated* operand = ToUnallocated(reg);
    775   allocator_->RecordTemporary(operand);
    776   return operand;
    777 }
    778 
    779 
    780 LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) {
    781   LUnallocated* operand = ToUnallocated(reg);
    782   allocator_->RecordTemporary(operand);
    783   return operand;
    784 }
    785 
    786 
    787 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) {
    788   return new LLabel(instr->block());
    789 }
    790 
    791 
    792 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
    793   return AssignEnvironment(new LDeoptimize);
    794 }
    795 
    796 
    797 LInstruction* LChunkBuilder::DoBit(Token::Value op,
    798                                    HBitwiseBinaryOperation* instr) {
    799   if (instr->representation().IsInteger32()) {
    800     ASSERT(instr->left()->representation().IsInteger32());
    801     ASSERT(instr->right()->representation().IsInteger32());
    802 
    803     LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
    804     LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
    805     return DefineSameAsFirst(new LBitI(op, left, right));
    806   } else {
    807     ASSERT(instr->representation().IsTagged());
    808     ASSERT(instr->left()->representation().IsTagged());
    809     ASSERT(instr->right()->representation().IsTagged());
    810 
    811     LOperand* left = UseFixed(instr->left(), edx);
    812     LOperand* right = UseFixed(instr->right(), eax);
    813     LArithmeticT* result = new LArithmeticT(op, left, right);
    814     return MarkAsCall(DefineFixed(result, eax), instr);
    815   }
    816 }
    817 
    818 
    819 LInstruction* LChunkBuilder::DoShift(Token::Value op,
    820                                      HBitwiseBinaryOperation* instr) {
    821   if (instr->representation().IsTagged()) {
    822     ASSERT(instr->left()->representation().IsTagged());
    823     ASSERT(instr->right()->representation().IsTagged());
    824 
    825     LOperand* left = UseFixed(instr->left(), edx);
    826     LOperand* right = UseFixed(instr->right(), eax);
    827     LArithmeticT* result = new LArithmeticT(op, left, right);
    828     return MarkAsCall(DefineFixed(result, eax), instr);
    829   }
    830 
    831   ASSERT(instr->representation().IsInteger32());
    832   ASSERT(instr->OperandAt(0)->representation().IsInteger32());
    833   ASSERT(instr->OperandAt(1)->representation().IsInteger32());
    834   LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
    835 
    836   HValue* right_value = instr->OperandAt(1);
    837   LOperand* right = NULL;
    838   int constant_value = 0;
    839   if (right_value->IsConstant()) {
    840     HConstant* constant = HConstant::cast(right_value);
    841     right = chunk_->DefineConstantOperand(constant);
    842     constant_value = constant->Integer32Value() & 0x1f;
    843   } else {
    844     right = UseFixed(right_value, ecx);
    845   }
    846 
    847   // Shift operations can only deoptimize if we do a logical shift
    848   // by 0 and the result cannot be truncated to int32.
    849   bool can_deopt = (op == Token::SHR && constant_value == 0);
    850   if (can_deopt) {
    851     bool can_truncate = true;
    852     for (int i = 0; i < instr->uses()->length(); i++) {
    853       if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) {
    854         can_truncate = false;
    855         break;
    856       }
    857     }
    858     can_deopt = !can_truncate;
    859   }
    860 
    861   LShiftI* result = new LShiftI(op, left, right, can_deopt);
    862   return can_deopt
    863       ? AssignEnvironment(DefineSameAsFirst(result))
    864       : DefineSameAsFirst(result);
    865 }
    866 
    867 
    868 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op,
    869                                            HArithmeticBinaryOperation* instr) {
    870   ASSERT(instr->representation().IsDouble());
    871   ASSERT(instr->left()->representation().IsDouble());
    872   ASSERT(instr->right()->representation().IsDouble());
    873   ASSERT(op != Token::MOD);
    874   LOperand* left = UseRegisterAtStart(instr->left());
    875   LOperand* right = UseRegisterAtStart(instr->right());
    876   LArithmeticD* result = new LArithmeticD(op, left, right);
    877   return DefineSameAsFirst(result);
    878 }
    879 
    880 
    881 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op,
    882                                            HArithmeticBinaryOperation* instr) {
    883   ASSERT(op == Token::ADD ||
    884          op == Token::DIV ||
    885          op == Token::MOD ||
    886          op == Token::MUL ||
    887          op == Token::SUB);
    888   HValue* left = instr->left();
    889   HValue* right = instr->right();
    890   ASSERT(left->representation().IsTagged());
    891   ASSERT(right->representation().IsTagged());
    892   LOperand* left_operand = UseFixed(left, edx);
    893   LOperand* right_operand = UseFixed(right, eax);
    894   LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand);
    895   return MarkAsCall(DefineFixed(result, eax), instr);
    896 }
    897 
    898 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) {
    899   ASSERT(is_building());
    900   current_block_ = block;
    901   next_block_ = next_block;
    902   if (block->IsStartBlock()) {
    903     block->UpdateEnvironment(graph_->start_environment());
    904     argument_count_ = 0;
    905   } else if (block->predecessors()->length() == 1) {
    906     // We have a single predecessor => copy environment and outgoing
    907     // argument count from the predecessor.
    908     ASSERT(block->phis()->length() == 0);
    909     HBasicBlock* pred = block->predecessors()->at(0);
    910     HEnvironment* last_environment = pred->last_environment();
    911     ASSERT(last_environment != NULL);
    912     // Only copy the environment, if it is later used again.
    913     if (pred->end()->SecondSuccessor() == NULL) {
    914       ASSERT(pred->end()->FirstSuccessor() == block);
    915     } else {
    916       if (pred->end()->FirstSuccessor()->block_id() > block->block_id() ||
    917           pred->end()->SecondSuccessor()->block_id() > block->block_id()) {
    918         last_environment = last_environment->Copy();
    919       }
    920     }
    921     block->UpdateEnvironment(last_environment);
    922     ASSERT(pred->argument_count() >= 0);
    923     argument_count_ = pred->argument_count();
    924   } else {
    925     // We are at a state join => process phis.
    926     HBasicBlock* pred = block->predecessors()->at(0);
    927     // No need to copy the environment, it cannot be used later.
    928     HEnvironment* last_environment = pred->last_environment();
    929     for (int i = 0; i < block->phis()->length(); ++i) {
    930       HPhi* phi = block->phis()->at(i);
    931       last_environment->SetValueAt(phi->merged_index(), phi);
    932     }
    933     for (int i = 0; i < block->deleted_phis()->length(); ++i) {
    934       last_environment->SetValueAt(block->deleted_phis()->at(i),
    935                                    graph_->GetConstantUndefined());
    936     }
    937     block->UpdateEnvironment(last_environment);
    938     // Pick up the outgoing argument count of one of the predecessors.
    939     argument_count_ = pred->argument_count();
    940   }
    941   HInstruction* current = block->first();
    942   int start = chunk_->instructions()->length();
    943   while (current != NULL && !is_aborted()) {
    944     // Code for constants in registers is generated lazily.
    945     if (!current->EmitAtUses()) {
    946       VisitInstruction(current);
    947     }
    948     current = current->next();
    949   }
    950   int end = chunk_->instructions()->length() - 1;
    951   if (end >= start) {
    952     block->set_first_instruction_index(start);
    953     block->set_last_instruction_index(end);
    954   }
    955   block->set_argument_count(argument_count_);
    956   next_block_ = NULL;
    957   current_block_ = NULL;
    958 }
    959 
    960 
    961 void LChunkBuilder::VisitInstruction(HInstruction* current) {
    962   HInstruction* old_current = current_instruction_;
    963   current_instruction_ = current;
    964   if (current->has_position()) position_ = current->position();
    965   LInstruction* instr = current->CompileToLithium(this);
    966 
    967   if (instr != NULL) {
    968     if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) {
    969       instr = AssignPointerMap(instr);
    970     }
    971     if (FLAG_stress_environments && !instr->HasEnvironment()) {
    972       instr = AssignEnvironment(instr);
    973     }
    974     if (current->IsTest() && !instr->IsGoto()) {
    975       ASSERT(instr->IsControl());
    976       HTest* test = HTest::cast(current);
    977       instr->set_hydrogen_value(test->value());
    978       HBasicBlock* first = test->FirstSuccessor();
    979       HBasicBlock* second = test->SecondSuccessor();
    980       ASSERT(first != NULL && second != NULL);
    981       instr->SetBranchTargets(first->block_id(), second->block_id());
    982     } else {
    983       instr->set_hydrogen_value(current);
    984     }
    985 
    986     chunk_->AddInstruction(instr, current_block_);
    987   }
    988   current_instruction_ = old_current;
    989 }
    990 
    991 
    992 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) {
    993   if (hydrogen_env == NULL) return NULL;
    994 
    995   LEnvironment* outer = CreateEnvironment(hydrogen_env->outer());
    996   int ast_id = hydrogen_env->ast_id();
    997   ASSERT(ast_id != AstNode::kNoNumber);
    998   int value_count = hydrogen_env->length();
    999   LEnvironment* result = new LEnvironment(hydrogen_env->closure(),
   1000                                           ast_id,
   1001                                           hydrogen_env->parameter_count(),
   1002                                           argument_count_,
   1003                                           value_count,
   1004                                           outer);
   1005   int argument_index = 0;
   1006   for (int i = 0; i < value_count; ++i) {
   1007     HValue* value = hydrogen_env->values()->at(i);
   1008     LOperand* op = NULL;
   1009     if (value->IsArgumentsObject()) {
   1010       op = NULL;
   1011     } else if (value->IsPushArgument()) {
   1012       op = new LArgument(argument_index++);
   1013     } else {
   1014       op = UseAny(value);
   1015     }
   1016     result->AddValue(op, value->representation());
   1017   }
   1018 
   1019   return result;
   1020 }
   1021 
   1022 
   1023 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) {
   1024   LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(),
   1025                             instr->include_stack_check());
   1026   return (instr->include_stack_check())
   1027       ? AssignPointerMap(result)
   1028       : result;
   1029 }
   1030 
   1031 
   1032 LInstruction* LChunkBuilder::DoTest(HTest* instr) {
   1033   HValue* v = instr->value();
   1034   if (v->EmitAtUses()) {
   1035     if (v->IsClassOfTest()) {
   1036       HClassOfTest* compare = HClassOfTest::cast(v);
   1037       ASSERT(compare->value()->representation().IsTagged());
   1038 
   1039       return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
   1040                                        TempRegister(),
   1041                                        TempRegister());
   1042     } else if (v->IsCompare()) {
   1043       HCompare* compare = HCompare::cast(v);
   1044       Token::Value op = compare->token();
   1045       HValue* left = compare->left();
   1046       HValue* right = compare->right();
   1047       Representation r = compare->GetInputRepresentation();
   1048       if (r.IsInteger32()) {
   1049         ASSERT(left->representation().IsInteger32());
   1050         ASSERT(right->representation().IsInteger32());
   1051 
   1052         return new LCmpIDAndBranch(UseRegisterAtStart(left),
   1053                                    UseOrConstantAtStart(right));
   1054       } else if (r.IsDouble()) {
   1055         ASSERT(left->representation().IsDouble());
   1056         ASSERT(right->representation().IsDouble());
   1057 
   1058         return new LCmpIDAndBranch(UseRegisterAtStart(left),
   1059                                    UseRegisterAtStart(right));
   1060       } else {
   1061         ASSERT(left->representation().IsTagged());
   1062         ASSERT(right->representation().IsTagged());
   1063         bool reversed = op == Token::GT || op == Token::LTE;
   1064         LOperand* left_operand = UseFixed(left, reversed ? eax : edx);
   1065         LOperand* right_operand = UseFixed(right, reversed ? edx : eax);
   1066         LCmpTAndBranch* result = new LCmpTAndBranch(left_operand,
   1067                                                     right_operand);
   1068         return MarkAsCall(result, instr);
   1069       }
   1070     } else if (v->IsIsSmi()) {
   1071       HIsSmi* compare = HIsSmi::cast(v);
   1072       ASSERT(compare->value()->representation().IsTagged());
   1073 
   1074       return new LIsSmiAndBranch(Use(compare->value()));
   1075     } else if (v->IsHasInstanceType()) {
   1076       HHasInstanceType* compare = HHasInstanceType::cast(v);
   1077       ASSERT(compare->value()->representation().IsTagged());
   1078 
   1079       return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()),
   1080                                            TempRegister());
   1081     } else if (v->IsHasCachedArrayIndex()) {
   1082       HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v);
   1083       ASSERT(compare->value()->representation().IsTagged());
   1084 
   1085       return new LHasCachedArrayIndexAndBranch(
   1086           UseRegisterAtStart(compare->value()));
   1087     } else if (v->IsIsNull()) {
   1088       HIsNull* compare = HIsNull::cast(v);
   1089       ASSERT(compare->value()->representation().IsTagged());
   1090 
   1091       // We only need a temp register for non-strict compare.
   1092       LOperand* temp = compare->is_strict() ? NULL : TempRegister();
   1093       return new LIsNullAndBranch(UseRegisterAtStart(compare->value()),
   1094                                   temp);
   1095     } else if (v->IsIsObject()) {
   1096       HIsObject* compare = HIsObject::cast(v);
   1097       ASSERT(compare->value()->representation().IsTagged());
   1098 
   1099       LOperand* temp1 = TempRegister();
   1100       LOperand* temp2 = TempRegister();
   1101       return new LIsObjectAndBranch(UseRegister(compare->value()),
   1102                                     temp1,
   1103                                     temp2);
   1104     } else if (v->IsCompareJSObjectEq()) {
   1105       HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
   1106       return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
   1107                                          UseRegisterAtStart(compare->right()));
   1108     } else if (v->IsInstanceOf()) {
   1109       HInstanceOf* instance_of = HInstanceOf::cast(v);
   1110       LOperand* left = UseFixed(instance_of->left(), InstanceofStub::left());
   1111       LOperand* right = UseFixed(instance_of->right(), InstanceofStub::right());
   1112       LOperand* context = UseFixed(instance_of->context(), esi);
   1113       LInstanceOfAndBranch* result =
   1114           new LInstanceOfAndBranch(context, left, right);
   1115       return MarkAsCall(result, instr);
   1116     } else if (v->IsTypeofIs()) {
   1117       HTypeofIs* typeof_is = HTypeofIs::cast(v);
   1118       return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
   1119     } else if (v->IsIsConstructCall()) {
   1120       return new LIsConstructCallAndBranch(TempRegister());
   1121     } else {
   1122       if (v->IsConstant()) {
   1123         if (HConstant::cast(v)->ToBoolean()) {
   1124           return new LGoto(instr->FirstSuccessor()->block_id());
   1125         } else {
   1126           return new LGoto(instr->SecondSuccessor()->block_id());
   1127         }
   1128       }
   1129       Abort("Undefined compare before branch");
   1130       return NULL;
   1131     }
   1132   }
   1133   return new LBranch(UseRegisterAtStart(v));
   1134 }
   1135 
   1136 
   1137 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) {
   1138   ASSERT(instr->value()->representation().IsTagged());
   1139   LOperand* value = UseRegisterAtStart(instr->value());
   1140   return new LCmpMapAndBranch(value);
   1141 }
   1142 
   1143 
   1144 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) {
   1145   return DefineAsRegister(new LArgumentsLength(Use(length->value())));
   1146 }
   1147 
   1148 
   1149 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
   1150   return DefineAsRegister(new LArgumentsElements);
   1151 }
   1152 
   1153 
   1154 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
   1155   LOperand* left = UseFixed(instr->left(), InstanceofStub::left());
   1156   LOperand* right = UseFixed(instr->right(), InstanceofStub::right());
   1157   LOperand* context = UseFixed(instr->context(), esi);
   1158   LInstanceOf* result = new LInstanceOf(context, left, right);
   1159   return MarkAsCall(DefineFixed(result, eax), instr);
   1160 }
   1161 
   1162 
   1163 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal(
   1164     HInstanceOfKnownGlobal* instr) {
   1165   LInstanceOfKnownGlobal* result =
   1166       new LInstanceOfKnownGlobal(
   1167           UseFixed(instr->value(), InstanceofStub::left()),
   1168           FixedTemp(edi));
   1169   return MarkAsCall(DefineFixed(result, eax), instr);
   1170 }
   1171 
   1172 
   1173 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) {
   1174   LOperand* function = UseFixed(instr->function(), edi);
   1175   LOperand* receiver = UseFixed(instr->receiver(), eax);
   1176   LOperand* length = UseFixed(instr->length(), ebx);
   1177   LOperand* elements = UseFixed(instr->elements(), ecx);
   1178   LOperand* temp = FixedTemp(edx);
   1179   LApplyArguments* result = new LApplyArguments(function,
   1180                                                 receiver,
   1181                                                 length,
   1182                                                 elements,
   1183                                                 temp);
   1184   return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
   1185 }
   1186 
   1187 
   1188 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) {
   1189   ++argument_count_;
   1190   LOperand* argument = UseAny(instr->argument());
   1191   return new LPushArgument(argument);
   1192 }
   1193 
   1194 
   1195 LInstruction* LChunkBuilder::DoContext(HContext* instr) {
   1196   return DefineAsRegister(new LContext);
   1197 }
   1198 
   1199 
   1200 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
   1201   LOperand* context = UseRegisterAtStart(instr->value());
   1202   return DefineAsRegister(new LOuterContext(context));
   1203 }
   1204 
   1205 
   1206 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
   1207   LOperand* context = UseRegisterAtStart(instr->value());
   1208   return DefineAsRegister(new LGlobalObject(context));
   1209 }
   1210 
   1211 
   1212 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
   1213   LOperand* global_object = UseRegisterAtStart(instr->value());
   1214   return DefineAsRegister(new LGlobalReceiver(global_object));
   1215 }
   1216 
   1217 
   1218 LInstruction* LChunkBuilder::DoCallConstantFunction(
   1219     HCallConstantFunction* instr) {
   1220   argument_count_ -= instr->argument_count();
   1221   return MarkAsCall(DefineFixed(new LCallConstantFunction, eax), instr);
   1222 }
   1223 
   1224 
   1225 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
   1226   BuiltinFunctionId op = instr->op();
   1227   if (op == kMathLog) {
   1228     ASSERT(instr->representation().IsDouble());
   1229     ASSERT(instr->value()->representation().IsDouble());
   1230     LOperand* input = UseRegisterAtStart(instr->value());
   1231     LUnaryMathOperation* result = new LUnaryMathOperation(input);
   1232     return DefineSameAsFirst(result);
   1233   } else if (op == kMathSin || op == kMathCos) {
   1234     LOperand* input = UseFixedDouble(instr->value(), xmm1);
   1235     LUnaryMathOperation* result = new LUnaryMathOperation(input);
   1236     return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
   1237   } else {
   1238     LOperand* input = UseRegisterAtStart(instr->value());
   1239     LUnaryMathOperation* result = new LUnaryMathOperation(input);
   1240     switch (op) {
   1241       case kMathAbs:
   1242         return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
   1243       case kMathFloor:
   1244         return AssignEnvironment(DefineAsRegister(result));
   1245       case kMathRound:
   1246         return AssignEnvironment(DefineAsRegister(result));
   1247       case kMathSqrt:
   1248         return DefineSameAsFirst(result);
   1249       case kMathPowHalf:
   1250         return DefineSameAsFirst(result);
   1251       default:
   1252         UNREACHABLE();
   1253         return NULL;
   1254     }
   1255   }
   1256 }
   1257 
   1258 
   1259 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
   1260   ASSERT(instr->key()->representation().IsTagged());
   1261   LOperand* context = UseFixed(instr->context(), esi);
   1262   LOperand* key = UseFixed(instr->key(), ecx);
   1263   argument_count_ -= instr->argument_count();
   1264   LCallKeyed* result = new LCallKeyed(context, key);
   1265   return MarkAsCall(DefineFixed(result, eax), instr);
   1266 }
   1267 
   1268 
   1269 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
   1270   LOperand* context = UseFixed(instr->context(), esi);
   1271   argument_count_ -= instr->argument_count();
   1272   LCallNamed* result = new LCallNamed(context);
   1273   return MarkAsCall(DefineFixed(result, eax), instr);
   1274 }
   1275 
   1276 
   1277 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) {
   1278   LOperand* context = UseFixed(instr->context(), esi);
   1279   argument_count_ -= instr->argument_count();
   1280   LCallGlobal* result = new LCallGlobal(context);
   1281   return MarkAsCall(DefineFixed(result, eax), instr);
   1282 }
   1283 
   1284 
   1285 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
   1286   argument_count_ -= instr->argument_count();
   1287   return MarkAsCall(DefineFixed(new LCallKnownGlobal, eax), instr);
   1288 }
   1289 
   1290 
   1291 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
   1292   LOperand* context = UseFixed(instr->context(), esi);
   1293   LOperand* constructor = UseFixed(instr->constructor(), edi);
   1294   argument_count_ -= instr->argument_count();
   1295   LCallNew* result = new LCallNew(context, constructor);
   1296   return MarkAsCall(DefineFixed(result, eax), instr);
   1297 }
   1298 
   1299 
   1300 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) {
   1301   LOperand* context = UseFixed(instr->context(), esi);
   1302   argument_count_ -= instr->argument_count();
   1303   LCallFunction* result = new LCallFunction(context);
   1304   return MarkAsCall(DefineFixed(result, eax), instr);
   1305 }
   1306 
   1307 
   1308 LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
   1309   argument_count_ -= instr->argument_count();
   1310   return MarkAsCall(DefineFixed(new LCallRuntime, eax), instr);
   1311 }
   1312 
   1313 
   1314 LInstruction* LChunkBuilder::DoShr(HShr* instr) {
   1315   return DoShift(Token::SHR, instr);
   1316 }
   1317 
   1318 
   1319 LInstruction* LChunkBuilder::DoSar(HSar* instr) {
   1320   return DoShift(Token::SAR, instr);
   1321 }
   1322 
   1323 
   1324 LInstruction* LChunkBuilder::DoShl(HShl* instr) {
   1325   return DoShift(Token::SHL, instr);
   1326 }
   1327 
   1328 
   1329 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
   1330   return DoBit(Token::BIT_AND, instr);
   1331 }
   1332 
   1333 
   1334 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
   1335   ASSERT(instr->value()->representation().IsInteger32());
   1336   ASSERT(instr->representation().IsInteger32());
   1337   LOperand* input = UseRegisterAtStart(instr->value());
   1338   LBitNotI* result = new LBitNotI(input);
   1339   return DefineSameAsFirst(result);
   1340 }
   1341 
   1342 
   1343 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
   1344   return DoBit(Token::BIT_OR, instr);
   1345 }
   1346 
   1347 
   1348 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
   1349   return DoBit(Token::BIT_XOR, instr);
   1350 }
   1351 
   1352 
   1353 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
   1354   if (instr->representation().IsDouble()) {
   1355     return DoArithmeticD(Token::DIV, instr);
   1356   } else if (instr->representation().IsInteger32()) {
   1357     // The temporary operand is necessary to ensure that right is not allocated
   1358     // into edx.
   1359     LOperand* temp = FixedTemp(edx);
   1360     LOperand* dividend = UseFixed(instr->left(), eax);
   1361     LOperand* divisor = UseRegister(instr->right());
   1362     LDivI* result = new LDivI(dividend, divisor, temp);
   1363     return AssignEnvironment(DefineFixed(result, eax));
   1364   } else {
   1365     ASSERT(instr->representation().IsTagged());
   1366     return DoArithmeticT(Token::DIV, instr);
   1367   }
   1368 }
   1369 
   1370 
   1371 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
   1372   if (instr->representation().IsInteger32()) {
   1373     ASSERT(instr->left()->representation().IsInteger32());
   1374     ASSERT(instr->right()->representation().IsInteger32());
   1375 
   1376     LInstruction* result;
   1377     if (instr->HasPowerOf2Divisor()) {
   1378       ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero));
   1379       LOperand* value = UseRegisterAtStart(instr->left());
   1380       LModI* mod = new LModI(value, UseOrConstant(instr->right()), NULL);
   1381       result = DefineSameAsFirst(mod);
   1382     } else {
   1383       // The temporary operand is necessary to ensure that right is
   1384       // not allocated into edx.
   1385       LOperand* temp = FixedTemp(edx);
   1386       LOperand* value = UseFixed(instr->left(), eax);
   1387       LOperand* divisor = UseRegister(instr->right());
   1388       LModI* mod = new LModI(value, divisor, temp);
   1389       result = DefineFixed(mod, edx);
   1390     }
   1391 
   1392     return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
   1393             instr->CheckFlag(HValue::kCanBeDivByZero))
   1394         ? AssignEnvironment(result)
   1395         : result;
   1396   } else if (instr->representation().IsTagged()) {
   1397     return DoArithmeticT(Token::MOD, instr);
   1398   } else {
   1399     ASSERT(instr->representation().IsDouble());
   1400     // We call a C function for double modulo. It can't trigger a GC.
   1401     // We need to use fixed result register for the call.
   1402     // TODO(fschneider): Allow any register as input registers.
   1403     LOperand* left = UseFixedDouble(instr->left(), xmm2);
   1404     LOperand* right = UseFixedDouble(instr->right(), xmm1);
   1405     LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
   1406     return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
   1407   }
   1408 }
   1409 
   1410 
   1411 LInstruction* LChunkBuilder::DoMul(HMul* instr) {
   1412   if (instr->representation().IsInteger32()) {
   1413     ASSERT(instr->left()->representation().IsInteger32());
   1414     ASSERT(instr->right()->representation().IsInteger32());
   1415     LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
   1416     LOperand* right = UseOrConstant(instr->MostConstantOperand());
   1417     LOperand* temp = NULL;
   1418     if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
   1419       temp = TempRegister();
   1420     }
   1421     LMulI* mul = new LMulI(left, right, temp);
   1422     return AssignEnvironment(DefineSameAsFirst(mul));
   1423   } else if (instr->representation().IsDouble()) {
   1424     return DoArithmeticD(Token::MUL, instr);
   1425   } else {
   1426     ASSERT(instr->representation().IsTagged());
   1427     return DoArithmeticT(Token::MUL, instr);
   1428   }
   1429 }
   1430 
   1431 
   1432 LInstruction* LChunkBuilder::DoSub(HSub* instr) {
   1433   if (instr->representation().IsInteger32()) {
   1434     ASSERT(instr->left()->representation().IsInteger32());
   1435     ASSERT(instr->right()->representation().IsInteger32());
   1436     LOperand* left = UseRegisterAtStart(instr->left());
   1437     LOperand* right = UseOrConstantAtStart(instr->right());
   1438     LSubI* sub = new LSubI(left, right);
   1439     LInstruction* result = DefineSameAsFirst(sub);
   1440     if (instr->CheckFlag(HValue::kCanOverflow)) {
   1441       result = AssignEnvironment(result);
   1442     }
   1443     return result;
   1444   } else if (instr->representation().IsDouble()) {
   1445     return DoArithmeticD(Token::SUB, instr);
   1446   } else {
   1447     ASSERT(instr->representation().IsTagged());
   1448     return DoArithmeticT(Token::SUB, instr);
   1449   }
   1450 }
   1451 
   1452 
   1453 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
   1454   if (instr->representation().IsInteger32()) {
   1455     ASSERT(instr->left()->representation().IsInteger32());
   1456     ASSERT(instr->right()->representation().IsInteger32());
   1457     LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
   1458     LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
   1459     LAddI* add = new LAddI(left, right);
   1460     LInstruction* result = DefineSameAsFirst(add);
   1461     if (instr->CheckFlag(HValue::kCanOverflow)) {
   1462       result = AssignEnvironment(result);
   1463     }
   1464     return result;
   1465   } else if (instr->representation().IsDouble()) {
   1466     return DoArithmeticD(Token::ADD, instr);
   1467   } else {
   1468     ASSERT(instr->representation().IsTagged());
   1469     return DoArithmeticT(Token::ADD, instr);
   1470   }
   1471 }
   1472 
   1473 
   1474 LInstruction* LChunkBuilder::DoPower(HPower* instr) {
   1475   ASSERT(instr->representation().IsDouble());
   1476   // We call a C function for double power. It can't trigger a GC.
   1477   // We need to use fixed result register for the call.
   1478   Representation exponent_type = instr->right()->representation();
   1479   ASSERT(instr->left()->representation().IsDouble());
   1480   LOperand* left = UseFixedDouble(instr->left(), xmm1);
   1481   LOperand* right = exponent_type.IsDouble() ?
   1482       UseFixedDouble(instr->right(), xmm2) :
   1483       UseFixed(instr->right(), eax);
   1484   LPower* result = new LPower(left, right);
   1485   return MarkAsCall(DefineFixedDouble(result, xmm3), instr,
   1486                     CAN_DEOPTIMIZE_EAGERLY);
   1487 }
   1488 
   1489 
   1490 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) {
   1491   Token::Value op = instr->token();
   1492   Representation r = instr->GetInputRepresentation();
   1493   if (r.IsInteger32()) {
   1494     ASSERT(instr->left()->representation().IsInteger32());
   1495     ASSERT(instr->right()->representation().IsInteger32());
   1496     LOperand* left = UseRegisterAtStart(instr->left());
   1497     LOperand* right = UseOrConstantAtStart(instr->right());
   1498     return DefineAsRegister(new LCmpID(left, right));
   1499   } else if (r.IsDouble()) {
   1500     ASSERT(instr->left()->representation().IsDouble());
   1501     ASSERT(instr->right()->representation().IsDouble());
   1502     LOperand* left = UseRegisterAtStart(instr->left());
   1503     LOperand* right = UseRegisterAtStart(instr->right());
   1504     return DefineAsRegister(new LCmpID(left, right));
   1505   } else {
   1506     ASSERT(instr->left()->representation().IsTagged());
   1507     ASSERT(instr->right()->representation().IsTagged());
   1508     bool reversed = (op == Token::GT || op == Token::LTE);
   1509     LOperand* left = UseFixed(instr->left(), reversed ? eax : edx);
   1510     LOperand* right = UseFixed(instr->right(), reversed ? edx : eax);
   1511     LCmpT* result = new LCmpT(left, right);
   1512     return MarkAsCall(DefineFixed(result, eax), instr);
   1513   }
   1514 }
   1515 
   1516 
   1517 LInstruction* LChunkBuilder::DoCompareJSObjectEq(
   1518     HCompareJSObjectEq* instr) {
   1519   LOperand* left = UseRegisterAtStart(instr->left());
   1520   LOperand* right = UseRegisterAtStart(instr->right());
   1521   LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right);
   1522   return DefineAsRegister(result);
   1523 }
   1524 
   1525 
   1526 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
   1527   ASSERT(instr->value()->representation().IsTagged());
   1528   LOperand* value = UseRegisterAtStart(instr->value());
   1529 
   1530   return DefineAsRegister(new LIsNull(value));
   1531 }
   1532 
   1533 
   1534 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) {
   1535   ASSERT(instr->value()->representation().IsTagged());
   1536   LOperand* value = UseRegister(instr->value());
   1537 
   1538   return DefineAsRegister(new LIsObject(value, TempRegister()));
   1539 }
   1540 
   1541 
   1542 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) {
   1543   ASSERT(instr->value()->representation().IsTagged());
   1544   LOperand* value = UseAtStart(instr->value());
   1545 
   1546   return DefineAsRegister(new LIsSmi(value));
   1547 }
   1548 
   1549 
   1550 LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) {
   1551   ASSERT(instr->value()->representation().IsTagged());
   1552   LOperand* value = UseRegisterAtStart(instr->value());
   1553 
   1554   return DefineAsRegister(new LHasInstanceType(value));
   1555 }
   1556 
   1557 
   1558 LInstruction* LChunkBuilder::DoGetCachedArrayIndex(
   1559     HGetCachedArrayIndex* instr)  {
   1560   ASSERT(instr->value()->representation().IsTagged());
   1561   LOperand* value = UseRegisterAtStart(instr->value());
   1562 
   1563   return DefineAsRegister(new LGetCachedArrayIndex(value));
   1564 }
   1565 
   1566 
   1567 LInstruction* LChunkBuilder::DoHasCachedArrayIndex(
   1568     HHasCachedArrayIndex* instr) {
   1569   ASSERT(instr->value()->representation().IsTagged());
   1570   LOperand* value = UseRegister(instr->value());
   1571 
   1572   return DefineAsRegister(new LHasCachedArrayIndex(value));
   1573 }
   1574 
   1575 
   1576 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
   1577   ASSERT(instr->value()->representation().IsTagged());
   1578   LOperand* value = UseTempRegister(instr->value());
   1579 
   1580   return DefineSameAsFirst(new LClassOfTest(value, TempRegister()));
   1581 }
   1582 
   1583 
   1584 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) {
   1585   LOperand* array = UseRegisterAtStart(instr->value());
   1586   return DefineAsRegister(new LJSArrayLength(array));
   1587 }
   1588 
   1589 
   1590 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) {
   1591   LOperand* array = UseRegisterAtStart(instr->value());
   1592   return DefineAsRegister(new LFixedArrayLength(array));
   1593 }
   1594 
   1595 
   1596 LInstruction* LChunkBuilder::DoExternalArrayLength(
   1597     HExternalArrayLength* instr) {
   1598   LOperand* array = UseRegisterAtStart(instr->value());
   1599   return DefineAsRegister(new LExternalArrayLength(array));
   1600 }
   1601 
   1602 
   1603 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) {
   1604   LOperand* object = UseRegister(instr->value());
   1605   LValueOf* result = new LValueOf(object, TempRegister());
   1606   return AssignEnvironment(DefineSameAsFirst(result));
   1607 }
   1608 
   1609 
   1610 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) {
   1611   return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()),
   1612                                             Use(instr->length())));
   1613 }
   1614 
   1615 
   1616 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) {
   1617   // The control instruction marking the end of a block that completed
   1618   // abruptly (e.g., threw an exception).  There is nothing specific to do.
   1619   return NULL;
   1620 }
   1621 
   1622 
   1623 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
   1624   LOperand* value = UseFixed(instr->value(), eax);
   1625   return MarkAsCall(new LThrow(value), instr);
   1626 }
   1627 
   1628 
   1629 LInstruction* LChunkBuilder::DoChange(HChange* instr) {
   1630   Representation from = instr->from();
   1631   Representation to = instr->to();
   1632   if (from.IsTagged()) {
   1633     if (to.IsDouble()) {
   1634       LOperand* value = UseRegister(instr->value());
   1635       LNumberUntagD* res = new LNumberUntagD(value);
   1636       return AssignEnvironment(DefineAsRegister(res));
   1637     } else {
   1638       ASSERT(to.IsInteger32());
   1639       LOperand* value = UseRegister(instr->value());
   1640       bool needs_check = !instr->value()->type().IsSmi();
   1641       if (needs_check) {
   1642         LOperand* xmm_temp =
   1643             (instr->CanTruncateToInt32() && CpuFeatures::IsSupported(SSE3))
   1644             ? NULL
   1645             : FixedTemp(xmm1);
   1646         LTaggedToI* res = new LTaggedToI(value, xmm_temp);
   1647         return AssignEnvironment(DefineSameAsFirst(res));
   1648       } else {
   1649         return DefineSameAsFirst(new LSmiUntag(value, needs_check));
   1650       }
   1651     }
   1652   } else if (from.IsDouble()) {
   1653     if (to.IsTagged()) {
   1654       LOperand* value = UseRegister(instr->value());
   1655       LOperand* temp = TempRegister();
   1656 
   1657       // Make sure that temp and result_temp are different registers.
   1658       LUnallocated* result_temp = TempRegister();
   1659       LNumberTagD* result = new LNumberTagD(value, temp);
   1660       return AssignPointerMap(Define(result, result_temp));
   1661     } else {
   1662       ASSERT(to.IsInteger32());
   1663       bool needs_temp = instr->CanTruncateToInt32() &&
   1664           !CpuFeatures::IsSupported(SSE3);
   1665       LOperand* value = needs_temp ?
   1666           UseTempRegister(instr->value()) : UseRegister(instr->value());
   1667       LOperand* temp = needs_temp ? TempRegister() : NULL;
   1668       return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, temp)));
   1669     }
   1670   } else if (from.IsInteger32()) {
   1671     if (to.IsTagged()) {
   1672       HValue* val = instr->value();
   1673       LOperand* value = UseRegister(val);
   1674       if (val->HasRange() && val->range()->IsInSmiRange()) {
   1675         return DefineSameAsFirst(new LSmiTag(value));
   1676       } else {
   1677         LNumberTagI* result = new LNumberTagI(value);
   1678         return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result)));
   1679       }
   1680     } else {
   1681       ASSERT(to.IsDouble());
   1682       return DefineAsRegister(new LInteger32ToDouble(Use(instr->value())));
   1683     }
   1684   }
   1685   UNREACHABLE();
   1686   return NULL;
   1687 }
   1688 
   1689 
   1690 LInstruction* LChunkBuilder::DoCheckNonSmi(HCheckNonSmi* instr) {
   1691   LOperand* value = UseRegisterAtStart(instr->value());
   1692   return AssignEnvironment(new LCheckNonSmi(value));
   1693 }
   1694 
   1695 
   1696 LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) {
   1697   LOperand* value = UseRegisterAtStart(instr->value());
   1698   LOperand* temp = TempRegister();
   1699   LCheckInstanceType* result = new LCheckInstanceType(value, temp);
   1700   return AssignEnvironment(result);
   1701 }
   1702 
   1703 
   1704 LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) {
   1705   LOperand* temp = TempRegister();
   1706   LCheckPrototypeMaps* result = new LCheckPrototypeMaps(temp);
   1707   return AssignEnvironment(result);
   1708 }
   1709 
   1710 
   1711 LInstruction* LChunkBuilder::DoCheckSmi(HCheckSmi* instr) {
   1712   LOperand* value = UseRegisterAtStart(instr->value());
   1713   return AssignEnvironment(new LCheckSmi(value));
   1714 }
   1715 
   1716 
   1717 LInstruction* LChunkBuilder::DoCheckFunction(HCheckFunction* instr) {
   1718   LOperand* value = UseRegisterAtStart(instr->value());
   1719   return AssignEnvironment(new LCheckFunction(value));
   1720 }
   1721 
   1722 
   1723 LInstruction* LChunkBuilder::DoCheckMap(HCheckMap* instr) {
   1724   LOperand* value = UseRegisterAtStart(instr->value());
   1725   LCheckMap* result = new LCheckMap(value);
   1726   return AssignEnvironment(result);
   1727 }
   1728 
   1729 
   1730 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) {
   1731   return new LReturn(UseFixed(instr->value(), eax));
   1732 }
   1733 
   1734 
   1735 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
   1736   Representation r = instr->representation();
   1737   if (r.IsInteger32()) {
   1738     return DefineAsRegister(new LConstantI);
   1739   } else if (r.IsDouble()) {
   1740     double value = instr->DoubleValue();
   1741     LOperand* temp = (BitCast<uint64_t, double>(value) != 0)
   1742         ? TempRegister()
   1743         : NULL;
   1744     return DefineAsRegister(new LConstantD(temp));
   1745   } else if (r.IsTagged()) {
   1746     return DefineAsRegister(new LConstantT);
   1747   } else {
   1748     UNREACHABLE();
   1749     return NULL;
   1750   }
   1751 }
   1752 
   1753 
   1754 LInstruction* LChunkBuilder::DoLoadGlobalCell(HLoadGlobalCell* instr) {
   1755   LLoadGlobalCell* result = new LLoadGlobalCell;
   1756   return instr->check_hole_value()
   1757       ? AssignEnvironment(DefineAsRegister(result))
   1758       : DefineAsRegister(result);
   1759 }
   1760 
   1761 
   1762 LInstruction* LChunkBuilder::DoLoadGlobalGeneric(HLoadGlobalGeneric* instr) {
   1763   LOperand* context = UseFixed(instr->context(), esi);
   1764   LOperand* global_object = UseFixed(instr->global_object(), eax);
   1765   LLoadGlobalGeneric* result = new LLoadGlobalGeneric(context, global_object);
   1766   return MarkAsCall(DefineFixed(result, eax), instr);
   1767 }
   1768 
   1769 
   1770 LInstruction* LChunkBuilder::DoStoreGlobalCell(HStoreGlobalCell* instr) {
   1771   LStoreGlobalCell* result =
   1772       new LStoreGlobalCell(UseRegisterAtStart(instr->value()));
   1773   return instr->check_hole_value() ? AssignEnvironment(result) : result;
   1774 }
   1775 
   1776 
   1777 LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
   1778   LOperand* context = UseFixed(instr->context(), esi);
   1779   LOperand* global_object = UseFixed(instr->global_object(), edx);
   1780   LOperand* value = UseFixed(instr->value(), eax);
   1781   LStoreGlobalGeneric* result =
   1782       new LStoreGlobalGeneric(context, global_object, value);
   1783   return MarkAsCall(result, instr);
   1784 }
   1785 
   1786 
   1787 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
   1788   LOperand* context = UseRegisterAtStart(instr->value());
   1789   return DefineAsRegister(new LLoadContextSlot(context));
   1790 }
   1791 
   1792 
   1793 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) {
   1794   LOperand* context;
   1795   LOperand* value;
   1796   LOperand* temp;
   1797   if (instr->NeedsWriteBarrier()) {
   1798     context = UseTempRegister(instr->context());
   1799     value = UseTempRegister(instr->value());
   1800     temp = TempRegister();
   1801   } else {
   1802     context = UseRegister(instr->context());
   1803     value = UseRegister(instr->value());
   1804     temp = NULL;
   1805   }
   1806   return new LStoreContextSlot(context, value, temp);
   1807 }
   1808 
   1809 
   1810 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) {
   1811   ASSERT(instr->representation().IsTagged());
   1812   LOperand* obj = UseRegisterAtStart(instr->object());
   1813   return DefineAsRegister(new LLoadNamedField(obj));
   1814 }
   1815 
   1816 
   1817 LInstruction* LChunkBuilder::DoLoadNamedFieldPolymorphic(
   1818     HLoadNamedFieldPolymorphic* instr) {
   1819   ASSERT(instr->representation().IsTagged());
   1820   if (instr->need_generic()) {
   1821     LOperand* obj = UseFixed(instr->object(), eax);
   1822     LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
   1823     return MarkAsCall(DefineFixed(result, eax), instr);
   1824   } else {
   1825     LOperand* obj = UseRegisterAtStart(instr->object());
   1826     LLoadNamedFieldPolymorphic* result = new LLoadNamedFieldPolymorphic(obj);
   1827     return AssignEnvironment(DefineAsRegister(result));
   1828   }
   1829 }
   1830 
   1831 
   1832 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
   1833   LOperand* context = UseFixed(instr->context(), esi);
   1834   LOperand* object = UseFixed(instr->object(), eax);
   1835   LLoadNamedGeneric* result = new LLoadNamedGeneric(context, object);
   1836   return MarkAsCall(DefineFixed(result, eax), instr);
   1837 }
   1838 
   1839 
   1840 LInstruction* LChunkBuilder::DoLoadFunctionPrototype(
   1841     HLoadFunctionPrototype* instr) {
   1842   return AssignEnvironment(DefineAsRegister(
   1843       new LLoadFunctionPrototype(UseRegister(instr->function()),
   1844                                  TempRegister())));
   1845 }
   1846 
   1847 
   1848 LInstruction* LChunkBuilder::DoLoadElements(HLoadElements* instr) {
   1849   LOperand* input = UseRegisterAtStart(instr->value());
   1850   return DefineAsRegister(new LLoadElements(input));
   1851 }
   1852 
   1853 
   1854 LInstruction* LChunkBuilder::DoLoadExternalArrayPointer(
   1855     HLoadExternalArrayPointer* instr) {
   1856   LOperand* input = UseRegisterAtStart(instr->value());
   1857   return DefineAsRegister(new LLoadExternalArrayPointer(input));
   1858 }
   1859 
   1860 
   1861 LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
   1862     HLoadKeyedFastElement* instr) {
   1863   ASSERT(instr->representation().IsTagged());
   1864   ASSERT(instr->key()->representation().IsInteger32());
   1865   LOperand* obj = UseRegisterAtStart(instr->object());
   1866   LOperand* key = UseRegisterAtStart(instr->key());
   1867   LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key);
   1868   return AssignEnvironment(DefineSameAsFirst(result));
   1869 }
   1870 
   1871 
   1872 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
   1873     HLoadKeyedSpecializedArrayElement* instr) {
   1874   ExternalArrayType array_type = instr->array_type();
   1875   Representation representation(instr->representation());
   1876   ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
   1877          (representation.IsDouble() && array_type == kExternalFloatArray));
   1878   ASSERT(instr->key()->representation().IsInteger32());
   1879   LOperand* external_pointer = UseRegister(instr->external_pointer());
   1880   LOperand* key = UseRegister(instr->key());
   1881   LLoadKeyedSpecializedArrayElement* result =
   1882       new LLoadKeyedSpecializedArrayElement(external_pointer,
   1883                                             key);
   1884   LInstruction* load_instr = DefineAsRegister(result);
   1885   // An unsigned int array load might overflow and cause a deopt, make sure it
   1886   // has an environment.
   1887   return (array_type == kExternalUnsignedIntArray)
   1888       ? AssignEnvironment(load_instr)
   1889       : load_instr;
   1890 }
   1891 
   1892 
   1893 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
   1894   LOperand* context = UseFixed(instr->context(), esi);
   1895   LOperand* object = UseFixed(instr->object(), edx);
   1896   LOperand* key = UseFixed(instr->key(), eax);
   1897 
   1898   LLoadKeyedGeneric* result = new LLoadKeyedGeneric(context, object, key);
   1899   return MarkAsCall(DefineFixed(result, eax), instr);
   1900 }
   1901 
   1902 
   1903 LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
   1904     HStoreKeyedFastElement* instr) {
   1905   bool needs_write_barrier = instr->NeedsWriteBarrier();
   1906   ASSERT(instr->value()->representation().IsTagged());
   1907   ASSERT(instr->object()->representation().IsTagged());
   1908   ASSERT(instr->key()->representation().IsInteger32());
   1909 
   1910   LOperand* obj = UseTempRegister(instr->object());
   1911   LOperand* val = needs_write_barrier
   1912       ? UseTempRegister(instr->value())
   1913       : UseRegisterAtStart(instr->value());
   1914   LOperand* key = needs_write_barrier
   1915       ? UseTempRegister(instr->key())
   1916       : UseRegisterOrConstantAtStart(instr->key());
   1917 
   1918   return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
   1919 }
   1920 
   1921 
   1922 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
   1923     HStoreKeyedSpecializedArrayElement* instr) {
   1924   Representation representation(instr->value()->representation());
   1925   ExternalArrayType array_type = instr->array_type();
   1926   ASSERT((representation.IsInteger32() && array_type != kExternalFloatArray) ||
   1927          (representation.IsDouble() && array_type == kExternalFloatArray));
   1928   ASSERT(instr->external_pointer()->representation().IsExternal());
   1929   ASSERT(instr->key()->representation().IsInteger32());
   1930 
   1931   LOperand* external_pointer = UseRegister(instr->external_pointer());
   1932   LOperand* key = UseRegister(instr->key());
   1933   LOperand* temp = NULL;
   1934 
   1935   if (array_type == kExternalPixelArray) {
   1936     // The generated code for pixel array stores requires that the clamped value
   1937     // is in a byte register. eax is an arbitrary choice to satisfy this
   1938     // requirement.
   1939     temp = FixedTemp(eax);
   1940   }
   1941 
   1942   LOperand* val = NULL;
   1943   if (array_type == kExternalByteArray ||
   1944       array_type == kExternalUnsignedByteArray) {
   1945     // We need a byte register in this case for the value.
   1946     val = UseFixed(instr->value(), eax);
   1947   } else {
   1948     val = UseRegister(instr->value());
   1949   }
   1950 
   1951   return new LStoreKeyedSpecializedArrayElement(external_pointer,
   1952                                                 key,
   1953                                                 val,
   1954                                                 temp);
   1955 }
   1956 
   1957 
   1958 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {
   1959   LOperand* context = UseFixed(instr->context(), esi);
   1960   LOperand* object = UseFixed(instr->object(), edx);
   1961   LOperand* key = UseFixed(instr->key(), ecx);
   1962   LOperand* value = UseFixed(instr->value(), eax);
   1963 
   1964   ASSERT(instr->object()->representation().IsTagged());
   1965   ASSERT(instr->key()->representation().IsTagged());
   1966   ASSERT(instr->value()->representation().IsTagged());
   1967 
   1968   LStoreKeyedGeneric* result =
   1969       new LStoreKeyedGeneric(context, object, key, value);
   1970   return MarkAsCall(result, instr);
   1971 }
   1972 
   1973 
   1974 LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
   1975   bool needs_write_barrier = instr->NeedsWriteBarrier();
   1976 
   1977   LOperand* obj = needs_write_barrier
   1978       ? UseTempRegister(instr->object())
   1979       : UseRegisterAtStart(instr->object());
   1980 
   1981   LOperand* val = needs_write_barrier
   1982       ? UseTempRegister(instr->value())
   1983       : UseRegister(instr->value());
   1984 
   1985   // We only need a scratch register if we have a write barrier or we
   1986   // have a store into the properties array (not in-object-property).
   1987   LOperand* temp = (!instr->is_in_object() || needs_write_barrier)
   1988       ? TempRegister()
   1989       : NULL;
   1990 
   1991   return new LStoreNamedField(obj, val, temp);
   1992 }
   1993 
   1994 
   1995 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) {
   1996   LOperand* context = UseFixed(instr->context(), esi);
   1997   LOperand* object = UseFixed(instr->object(), edx);
   1998   LOperand* value = UseFixed(instr->value(), eax);
   1999 
   2000   LStoreNamedGeneric* result = new LStoreNamedGeneric(context, object, value);
   2001   return MarkAsCall(result, instr);
   2002 }
   2003 
   2004 
   2005 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) {
   2006   LOperand* string = UseRegister(instr->string());
   2007   LOperand* index = UseRegisterOrConstant(instr->index());
   2008   LStringCharCodeAt* result = new LStringCharCodeAt(string, index);
   2009   return AssignEnvironment(AssignPointerMap(DefineAsRegister(result)));
   2010 }
   2011 
   2012 
   2013 LInstruction* LChunkBuilder::DoStringCharFromCode(HStringCharFromCode* instr) {
   2014   LOperand* char_code = UseRegister(instr->value());
   2015   LStringCharFromCode* result = new LStringCharFromCode(char_code);
   2016   return AssignPointerMap(DefineAsRegister(result));
   2017 }
   2018 
   2019 
   2020 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) {
   2021   LOperand* string = UseRegisterAtStart(instr->value());
   2022   return DefineAsRegister(new LStringLength(string));
   2023 }
   2024 
   2025 
   2026 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) {
   2027   return MarkAsCall(DefineFixed(new LArrayLiteral, eax), instr);
   2028 }
   2029 
   2030 
   2031 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) {
   2032   LOperand* context = UseFixed(instr->context(), esi);
   2033   return MarkAsCall(DefineFixed(new LObjectLiteral(context), eax), instr);
   2034 }
   2035 
   2036 
   2037 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) {
   2038   return MarkAsCall(DefineFixed(new LRegExpLiteral, eax), instr);
   2039 }
   2040 
   2041 
   2042 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) {
   2043   return MarkAsCall(DefineFixed(new LFunctionLiteral, eax), instr);
   2044 }
   2045 
   2046 
   2047 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) {
   2048   LDeleteProperty* result =
   2049       new LDeleteProperty(Use(instr->object()), UseOrConstant(instr->key()));
   2050   return MarkAsCall(DefineFixed(result, eax), instr);
   2051 }
   2052 
   2053 
   2054 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) {
   2055   allocator_->MarkAsOsrEntry();
   2056   current_block_->last_environment()->set_ast_id(instr->ast_id());
   2057   return AssignEnvironment(new LOsrEntry);
   2058 }
   2059 
   2060 
   2061 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
   2062   int spill_index = chunk()->GetParameterStackSlot(instr->index());
   2063   return DefineAsSpilled(new LParameter, spill_index);
   2064 }
   2065 
   2066 
   2067 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) {
   2068   int spill_index = chunk()->GetNextSpillIndex(false);  // Not double-width.
   2069   if (spill_index > LUnallocated::kMaxFixedIndex) {
   2070     Abort("Too many spill slots needed for OSR");
   2071     spill_index = 0;
   2072   }
   2073   return DefineAsSpilled(new LUnknownOSRValue, spill_index);
   2074 }
   2075 
   2076 
   2077 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
   2078   LOperand* context = UseFixed(instr->context(), esi);
   2079   argument_count_ -= instr->argument_count();
   2080   LCallStub* result = new LCallStub(context);
   2081   return MarkAsCall(DefineFixed(result, eax), instr);
   2082 }
   2083 
   2084 
   2085 LInstruction* LChunkBuilder::DoArgumentsObject(HArgumentsObject* instr) {
   2086   // There are no real uses of the arguments object.
   2087   // arguments.length and element access are supported directly on
   2088   // stack arguments, and any real arguments object use causes a bailout.
   2089   // So this value is never used.
   2090   return NULL;
   2091 }
   2092 
   2093 
   2094 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) {
   2095   LOperand* arguments = UseRegister(instr->arguments());
   2096   LOperand* length = UseTempRegister(instr->length());
   2097   LOperand* index = Use(instr->index());
   2098   LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index);
   2099   return AssignEnvironment(DefineAsRegister(result));
   2100 }
   2101 
   2102 
   2103 LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {
   2104   LOperand* object = UseFixed(instr->value(), eax);
   2105   LToFastProperties* result = new LToFastProperties(object);
   2106   return MarkAsCall(DefineFixed(result, eax), instr);
   2107 }
   2108 
   2109 
   2110 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) {
   2111   LTypeof* result = new LTypeof(UseAtStart(instr->value()));
   2112   return MarkAsCall(DefineFixed(result, eax), instr);
   2113 }
   2114 
   2115 
   2116 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) {
   2117   return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
   2118 }
   2119 
   2120 
   2121 LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
   2122   return DefineAsRegister(new LIsConstructCall);
   2123 }
   2124 
   2125 
   2126 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
   2127   HEnvironment* env = current_block_->last_environment();
   2128   ASSERT(env != NULL);
   2129 
   2130   env->set_ast_id(instr->ast_id());
   2131 
   2132   env->Drop(instr->pop_count());
   2133   for (int i = 0; i < instr->values()->length(); ++i) {
   2134     HValue* value = instr->values()->at(i);
   2135     if (instr->HasAssignedIndexAt(i)) {
   2136       env->Bind(instr->GetAssignedIndexAt(i), value);
   2137     } else {
   2138       env->Push(value);
   2139     }
   2140   }
   2141 
   2142   // If there is an instruction pending deoptimization environment create a
   2143   // lazy bailout instruction to capture the environment.
   2144   if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) {
   2145     ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
   2146     LLazyBailout* lazy_bailout = new LLazyBailout;
   2147     LInstruction* result = AssignEnvironment(lazy_bailout);
   2148     instruction_pending_deoptimization_environment_->
   2149         set_deoptimization_environment(result->environment());
   2150     ClearInstructionPendingDeoptimizationEnvironment();
   2151     return result;
   2152   }
   2153 
   2154   return NULL;
   2155 }
   2156 
   2157 
   2158 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) {
   2159   return MarkAsCall(new LStackCheck, instr);
   2160 }
   2161 
   2162 
   2163 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) {
   2164   HEnvironment* outer = current_block_->last_environment();
   2165   HConstant* undefined = graph()->GetConstantUndefined();
   2166   HEnvironment* inner = outer->CopyForInlining(instr->closure(),
   2167                                                instr->function(),
   2168                                                false,
   2169                                                undefined);
   2170   current_block_->UpdateEnvironment(inner);
   2171   chunk_->AddInlinedClosure(instr->closure());
   2172   return NULL;
   2173 }
   2174 
   2175 
   2176 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) {
   2177   HEnvironment* outer = current_block_->last_environment()->outer();
   2178   current_block_->UpdateEnvironment(outer);
   2179   return NULL;
   2180 }
   2181 
   2182 
   2183 } }  // namespace v8::internal
   2184 
   2185 #endif  // V8_TARGET_ARCH_IA32
   2186