LCOV - code coverage report
Current view: top level - src/crankshaft/x64 - lithium-x64.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 914 1143 80.0 %
Date: 2017-04-26 Functions: 262 311 84.2 %

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

Generated by: LCOV version 1.10