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