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