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