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