LCOV - code coverage report
Current view: top level - src/compiler - instruction.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 187 498 37.6 %
Date: 2017-10-20 Functions: 40 70 57.1 %

          Line data    Source code
       1             : // Copyright 2014 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/compiler/instruction.h"
       6             : 
       7             : #include "src/compiler/common-operator.h"
       8             : #include "src/compiler/graph.h"
       9             : #include "src/compiler/schedule.h"
      10             : #include "src/compiler/state-values-utils.h"
      11             : #include "src/source-position.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : namespace compiler {
      16             : 
      17             : const RegisterConfiguration* (*GetRegConfig)() = RegisterConfiguration::Default;
      18             : 
      19      917581 : FlagsCondition CommuteFlagsCondition(FlagsCondition condition) {
      20      917581 :   switch (condition) {
      21             :     case kSignedLessThan:
      22             :       return kSignedGreaterThan;
      23             :     case kSignedGreaterThanOrEqual:
      24         813 :       return kSignedLessThanOrEqual;
      25             :     case kSignedLessThanOrEqual:
      26        5156 :       return kSignedGreaterThanOrEqual;
      27             :     case kSignedGreaterThan:
      28         636 :       return kSignedLessThan;
      29             :     case kUnsignedLessThan:
      30      800868 :       return kUnsignedGreaterThan;
      31             :     case kUnsignedGreaterThanOrEqual:
      32        8653 :       return kUnsignedLessThanOrEqual;
      33             :     case kUnsignedLessThanOrEqual:
      34       40905 :       return kUnsignedGreaterThanOrEqual;
      35             :     case kUnsignedGreaterThan:
      36       18038 :       return kUnsignedLessThan;
      37             :     case kFloatLessThanOrUnordered:
      38           0 :       return kFloatGreaterThanOrUnordered;
      39             :     case kFloatGreaterThanOrEqual:
      40           0 :       return kFloatLessThanOrEqual;
      41             :     case kFloatLessThanOrEqual:
      42           0 :       return kFloatGreaterThanOrEqual;
      43             :     case kFloatGreaterThanOrUnordered:
      44           0 :       return kFloatLessThanOrUnordered;
      45             :     case kFloatLessThan:
      46           0 :       return kFloatGreaterThan;
      47             :     case kFloatGreaterThanOrEqualOrUnordered:
      48           0 :       return kFloatLessThanOrEqualOrUnordered;
      49             :     case kFloatLessThanOrEqualOrUnordered:
      50           0 :       return kFloatGreaterThanOrEqualOrUnordered;
      51             :     case kFloatGreaterThan:
      52           0 :       return kFloatLessThan;
      53             :     case kPositiveOrZero:
      54             :     case kNegative:
      55           0 :       UNREACHABLE();
      56             :       break;
      57             :     case kEqual:
      58             :     case kNotEqual:
      59             :     case kOverflow:
      60             :     case kNotOverflow:
      61             :     case kUnorderedEqual:
      62             :     case kUnorderedNotEqual:
      63         892 :       return condition;
      64             :   }
      65           0 :   UNREACHABLE();
      66             : }
      67             : 
      68    86391079 : bool InstructionOperand::InterferesWith(const InstructionOperand& other) const {
      69             :   if (kSimpleFPAliasing || !this->IsFPLocationOperand() ||
      70             :       !other.IsFPLocationOperand())
      71             :     return EqualsCanonicalized(other);
      72             :   // Aliasing is complex and both operands are fp locations.
      73             :   const LocationOperand& loc = *LocationOperand::cast(this);
      74             :   const LocationOperand& other_loc = LocationOperand::cast(other);
      75             :   LocationOperand::LocationKind kind = loc.location_kind();
      76             :   LocationOperand::LocationKind other_kind = other_loc.location_kind();
      77             :   if (kind != other_kind) return false;
      78             :   MachineRepresentation rep = loc.representation();
      79             :   MachineRepresentation other_rep = other_loc.representation();
      80             :   if (rep == other_rep) return EqualsCanonicalized(other);
      81             :   if (kind == LocationOperand::REGISTER) {
      82             :     // FP register-register interference.
      83             :     return GetRegConfig()->AreAliases(rep, loc.register_code(), other_rep,
      84             :                                       other_loc.register_code());
      85             :   } else {
      86             :     // FP slot-slot interference. Slots of different FP reps can alias because
      87             :     // the gap resolver may break a move into 2 or 4 equivalent smaller moves.
      88             :     DCHECK_EQ(LocationOperand::STACK_SLOT, kind);
      89             :     int index_hi = loc.index();
      90             :     int index_lo = index_hi - (1 << ElementSizeLog2Of(rep)) / kPointerSize + 1;
      91             :     int other_index_hi = other_loc.index();
      92             :     int other_index_lo =
      93             :         other_index_hi - (1 << ElementSizeLog2Of(other_rep)) / kPointerSize + 1;
      94             :     return other_index_hi >= index_lo && index_hi >= other_index_lo;
      95             :   }
      96             :   return false;
      97             : }
      98             : 
      99           0 : void InstructionOperand::Print(const RegisterConfiguration* config) const {
     100           0 :   OFStream os(stdout);
     101             :   PrintableInstructionOperand wrapper;
     102           0 :   wrapper.register_configuration_ = config;
     103           0 :   wrapper.op_ = *this;
     104           0 :   os << wrapper << std::endl;
     105           0 : }
     106             : 
     107           0 : void InstructionOperand::Print() const { Print(GetRegConfig()); }
     108             : 
     109           0 : std::ostream& operator<<(std::ostream& os,
     110             :                          const PrintableInstructionOperand& printable) {
     111             :   const InstructionOperand& op = printable.op_;
     112           0 :   const RegisterConfiguration* conf = printable.register_configuration_;
     113           0 :   switch (op.kind()) {
     114             :     case InstructionOperand::UNALLOCATED: {
     115             :       const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op);
     116           0 :       os << "v" << unalloc->virtual_register();
     117           0 :       if (unalloc->basic_policy() == UnallocatedOperand::FIXED_SLOT) {
     118           0 :         return os << "(=" << unalloc->fixed_slot_index() << "S)";
     119             :       }
     120           0 :       switch (unalloc->extended_policy()) {
     121             :         case UnallocatedOperand::NONE:
     122             :           return os;
     123             :         case UnallocatedOperand::FIXED_REGISTER:
     124           0 :           return os << "(="
     125             :                     << conf->GetGeneralRegisterName(
     126           0 :                            unalloc->fixed_register_index())
     127           0 :                     << ")";
     128             :         case UnallocatedOperand::FIXED_FP_REGISTER:
     129           0 :           return os << "(="
     130             :                     << conf->GetDoubleRegisterName(
     131           0 :                            unalloc->fixed_register_index())
     132           0 :                     << ")";
     133             :         case UnallocatedOperand::MUST_HAVE_REGISTER:
     134           0 :           return os << "(R)";
     135             :         case UnallocatedOperand::MUST_HAVE_SLOT:
     136           0 :           return os << "(S)";
     137             :         case UnallocatedOperand::SAME_AS_FIRST_INPUT:
     138           0 :           return os << "(1)";
     139             :         case UnallocatedOperand::ANY:
     140           0 :           return os << "(-)";
     141             :       }
     142             :     }
     143             :     case InstructionOperand::CONSTANT:
     144           0 :       return os << "[constant:" << ConstantOperand::cast(op).virtual_register()
     145           0 :                 << "]";
     146             :     case InstructionOperand::IMMEDIATE: {
     147             :       ImmediateOperand imm = ImmediateOperand::cast(op);
     148           0 :       switch (imm.type()) {
     149             :         case ImmediateOperand::INLINE:
     150           0 :           return os << "#" << imm.inline_value();
     151             :         case ImmediateOperand::INDEXED:
     152           0 :           return os << "[immediate:" << imm.indexed_value() << "]";
     153             :       }
     154             :     }
     155             :     case InstructionOperand::EXPLICIT:
     156             :     case InstructionOperand::ALLOCATED: {
     157             :       LocationOperand allocated = LocationOperand::cast(op);
     158           0 :       if (op.IsStackSlot()) {
     159           0 :         os << "[stack:" << allocated.index();
     160           0 :       } else if (op.IsFPStackSlot()) {
     161           0 :         os << "[fp_stack:" << allocated.index();
     162           0 :       } else if (op.IsRegister()) {
     163           0 :         os << "["
     164           0 :            << GetRegConfig()->GetGeneralRegisterName(allocated.register_code())
     165           0 :            << "|R";
     166           0 :       } else if (op.IsDoubleRegister()) {
     167           0 :         os << "["
     168           0 :            << GetRegConfig()->GetDoubleRegisterName(allocated.register_code())
     169           0 :            << "|R";
     170           0 :       } else if (op.IsFloatRegister()) {
     171           0 :         os << "["
     172           0 :            << GetRegConfig()->GetFloatRegisterName(allocated.register_code())
     173           0 :            << "|R";
     174             :       } else {
     175             :         DCHECK(op.IsSimd128Register());
     176           0 :         os << "["
     177           0 :            << GetRegConfig()->GetSimd128RegisterName(allocated.register_code())
     178           0 :            << "|R";
     179             :       }
     180           0 :       if (allocated.IsExplicit()) {
     181           0 :         os << "|E";
     182             :       }
     183           0 :       switch (allocated.representation()) {
     184             :         case MachineRepresentation::kNone:
     185           0 :           os << "|-";
     186           0 :           break;
     187             :         case MachineRepresentation::kBit:
     188           0 :           os << "|b";
     189           0 :           break;
     190             :         case MachineRepresentation::kWord8:
     191           0 :           os << "|w8";
     192           0 :           break;
     193             :         case MachineRepresentation::kWord16:
     194           0 :           os << "|w16";
     195           0 :           break;
     196             :         case MachineRepresentation::kWord32:
     197           0 :           os << "|w32";
     198           0 :           break;
     199             :         case MachineRepresentation::kWord64:
     200           0 :           os << "|w64";
     201           0 :           break;
     202             :         case MachineRepresentation::kFloat32:
     203           0 :           os << "|f32";
     204           0 :           break;
     205             :         case MachineRepresentation::kFloat64:
     206           0 :           os << "|f64";
     207           0 :           break;
     208             :         case MachineRepresentation::kSimd128:
     209           0 :           os << "|s128";
     210           0 :           break;
     211             :         case MachineRepresentation::kTaggedSigned:
     212           0 :           os << "|ts";
     213           0 :           break;
     214             :         case MachineRepresentation::kTaggedPointer:
     215           0 :           os << "|tp";
     216           0 :           break;
     217             :         case MachineRepresentation::kTagged:
     218           0 :           os << "|t";
     219           0 :           break;
     220             :       }
     221           0 :       return os << "]";
     222             :     }
     223             :     case InstructionOperand::INVALID:
     224           0 :       return os << "(x)";
     225             :   }
     226           0 :   UNREACHABLE();
     227             : }
     228             : 
     229           0 : void MoveOperands::Print(const RegisterConfiguration* config) const {
     230           0 :   OFStream os(stdout);
     231             :   PrintableInstructionOperand wrapper;
     232           0 :   wrapper.register_configuration_ = config;
     233           0 :   wrapper.op_ = destination();
     234           0 :   os << wrapper << " = ";
     235           0 :   wrapper.op_ = source();
     236           0 :   os << wrapper << std::endl;
     237           0 : }
     238             : 
     239           0 : void MoveOperands::Print() const { Print(GetRegConfig()); }
     240             : 
     241           0 : std::ostream& operator<<(std::ostream& os,
     242             :                          const PrintableMoveOperands& printable) {
     243           0 :   const MoveOperands& mo = *printable.move_operands_;
     244             :   PrintableInstructionOperand printable_op = {printable.register_configuration_,
     245           0 :                                               mo.destination()};
     246           0 :   os << printable_op;
     247           0 :   if (!mo.source().Equals(mo.destination())) {
     248           0 :     printable_op.op_ = mo.source();
     249           0 :     os << " = " << printable_op;
     250             :   }
     251           0 :   return os << ";";
     252             : }
     253             : 
     254             : 
     255    16040996 : bool ParallelMove::IsRedundant() const {
     256    40070309 :   for (MoveOperands* move : *this) {
     257    12741453 :     if (!move->IsRedundant()) return false;
     258             :   }
     259             :   return true;
     260             : }
     261             : 
     262    10333239 : void ParallelMove::PrepareInsertAfter(
     263             :     MoveOperands* move, ZoneVector<MoveOperands*>* to_eliminate) const {
     264             :   bool no_aliasing =
     265             :       kSimpleFPAliasing || !move->destination().IsFPLocationOperand();
     266             :   MoveOperands* replacement = nullptr;
     267             :   MoveOperands* eliminated = nullptr;
     268    37826011 :   for (MoveOperands* curr : *this) {
     269    17167219 :     if (curr->IsEliminated()) continue;
     270    34004190 :     if (curr->destination().EqualsCanonicalized(move->source())) {
     271             :       // We must replace move's source with curr's destination in order to
     272             :       // insert it into this ParallelMove.
     273             :       DCHECK(!replacement);
     274             :       replacement = curr;
     275     1314966 :       if (no_aliasing && eliminated != nullptr) break;
     276    31374264 :     } else if (curr->destination().InterferesWith(move->destination())) {
     277             :       // We can eliminate curr, since move overwrites at least a part of its
     278             :       // destination, implying its value is no longer live.
     279             :       eliminated = curr;
     280       54829 :       to_eliminate->push_back(curr);
     281       54829 :       if (no_aliasing && replacement != nullptr) break;
     282             :     }
     283             :   }
     284    10333245 :   if (replacement != nullptr) move->set_source(replacement->source());
     285    10333245 : }
     286             : 
     287      709638 : ExplicitOperand::ExplicitOperand(LocationKind kind, MachineRepresentation rep,
     288             :                                  int index)
     289             :     : LocationOperand(EXPLICIT, kind, rep, index) {
     290             :   DCHECK_IMPLIES(kind == REGISTER && !IsFloatingPoint(rep),
     291             :                  GetRegConfig()->IsAllocatableGeneralCode(index));
     292             :   DCHECK_IMPLIES(kind == REGISTER && rep == MachineRepresentation::kFloat32,
     293             :                  GetRegConfig()->IsAllocatableFloatCode(index));
     294             :   DCHECK_IMPLIES(kind == REGISTER && (rep == MachineRepresentation::kFloat64),
     295             :                  GetRegConfig()->IsAllocatableDoubleCode(index));
     296      709638 : }
     297             : 
     298           0 : Instruction::Instruction(InstructionCode opcode)
     299             :     : opcode_(opcode),
     300             :       bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
     301             :                  TempCountField::encode(0) | IsCallField::encode(false)),
     302             :       reference_map_(nullptr),
     303           0 :       block_(nullptr) {
     304           0 :   parallel_moves_[0] = nullptr;
     305           0 :   parallel_moves_[1] = nullptr;
     306           0 : }
     307             : 
     308    44727186 : Instruction::Instruction(InstructionCode opcode, size_t output_count,
     309             :                          InstructionOperand* outputs, size_t input_count,
     310             :                          InstructionOperand* inputs, size_t temp_count,
     311             :                          InstructionOperand* temps)
     312             :     : opcode_(opcode),
     313    44727186 :       bit_field_(OutputCountField::encode(output_count) |
     314    44727186 :                  InputCountField::encode(input_count) |
     315             :                  TempCountField::encode(temp_count) |
     316             :                  IsCallField::encode(false)),
     317             :       reference_map_(nullptr),
     318   134181281 :       block_(nullptr) {
     319    44727186 :   parallel_moves_[0] = nullptr;
     320    44727186 :   parallel_moves_[1] = nullptr;
     321             :   size_t offset = 0;
     322    69694765 :   for (size_t i = 0; i < output_count; ++i) {
     323             :     DCHECK(!outputs[i].IsInvalid());
     324    24967579 :     operands_[offset++] = outputs[i];
     325             :   }
     326    92826173 :   for (size_t i = 0; i < input_count; ++i) {
     327             :     DCHECK(!inputs[i].IsInvalid());
     328    92826173 :     operands_[offset++] = inputs[i];
     329             :   }
     330      662858 :   for (size_t i = 0; i < temp_count; ++i) {
     331             :     DCHECK(!temps[i].IsInvalid());
     332      662858 :     operands_[offset++] = temps[i];
     333             :   }
     334    44727186 : }
     335             : 
     336             : 
     337    40187209 : bool Instruction::AreMovesRedundant() const {
     338   111055574 :   for (int i = Instruction::FIRST_GAP_POSITION;
     339             :        i <= Instruction::LAST_GAP_POSITION; i++) {
     340    75621277 :     if (parallel_moves_[i] != nullptr && !parallel_moves_[i]->IsRedundant()) {
     341             :       return false;
     342             :     }
     343             :   }
     344             :   return true;
     345             : }
     346             : 
     347           0 : void Instruction::Print(const RegisterConfiguration* config) const {
     348           0 :   OFStream os(stdout);
     349             :   PrintableInstruction wrapper;
     350           0 :   wrapper.instr_ = this;
     351           0 :   wrapper.register_configuration_ = config;
     352           0 :   os << wrapper << std::endl;
     353           0 : }
     354             : 
     355           0 : void Instruction::Print() const { Print(GetRegConfig()); }
     356             : 
     357           0 : std::ostream& operator<<(std::ostream& os,
     358             :                          const PrintableParallelMove& printable) {
     359           0 :   const ParallelMove& pm = *printable.parallel_move_;
     360             :   bool first = true;
     361           0 :   for (MoveOperands* move : pm) {
     362           0 :     if (move->IsEliminated()) continue;
     363           0 :     if (!first) os << " ";
     364             :     first = false;
     365           0 :     PrintableMoveOperands pmo = {printable.register_configuration_, move};
     366           0 :     os << pmo;
     367             :   }
     368           0 :   return os;
     369             : }
     370             : 
     371             : 
     372    28176239 : void ReferenceMap::RecordReference(const AllocatedOperand& op) {
     373             :   // Do not record arguments as pointers.
     374    71638329 :   if (op.IsStackSlot() && LocationOperand::cast(op).index() < 0) return;
     375             :   DCHECK(!op.IsFPRegister() && !op.IsFPStackSlot());
     376    20412151 :   reference_operands_.push_back(op);
     377             : }
     378             : 
     379             : 
     380           0 : std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm) {
     381           0 :   os << "{";
     382             :   bool first = true;
     383           0 :   PrintableInstructionOperand poi = {GetRegConfig(), InstructionOperand()};
     384           0 :   for (const InstructionOperand& op : pm.reference_operands_) {
     385           0 :     if (!first) {
     386           0 :       os << ";";
     387             :     } else {
     388             :       first = false;
     389             :     }
     390           0 :     poi.op_ = op;
     391           0 :     os << poi;
     392             :   }
     393           0 :   return os << "}";
     394             : }
     395             : 
     396             : 
     397           0 : std::ostream& operator<<(std::ostream& os, const ArchOpcode& ao) {
     398           0 :   switch (ao) {
     399             : #define CASE(Name) \
     400             :   case k##Name:    \
     401             :     return os << #Name;
     402           0 :     ARCH_OPCODE_LIST(CASE)
     403             : #undef CASE
     404             :   }
     405           0 :   UNREACHABLE();
     406             : }
     407             : 
     408             : 
     409           0 : std::ostream& operator<<(std::ostream& os, const AddressingMode& am) {
     410           0 :   switch (am) {
     411             :     case kMode_None:
     412             :       return os;
     413             : #define CASE(Name)   \
     414             :   case kMode_##Name: \
     415             :     return os << #Name;
     416           0 :       TARGET_ADDRESSING_MODE_LIST(CASE)
     417             : #undef CASE
     418             :   }
     419           0 :   UNREACHABLE();
     420             : }
     421             : 
     422             : 
     423           0 : std::ostream& operator<<(std::ostream& os, const FlagsMode& fm) {
     424           0 :   switch (fm) {
     425             :     case kFlags_none:
     426             :       return os;
     427             :     case kFlags_branch:
     428           0 :       return os << "branch";
     429             :     case kFlags_deoptimize:
     430           0 :       return os << "deoptimize";
     431             :     case kFlags_set:
     432           0 :       return os << "set";
     433             :     case kFlags_trap:
     434           0 :       return os << "trap";
     435             :   }
     436           0 :   UNREACHABLE();
     437             : }
     438             : 
     439             : 
     440           0 : std::ostream& operator<<(std::ostream& os, const FlagsCondition& fc) {
     441           0 :   switch (fc) {
     442             :     case kEqual:
     443           0 :       return os << "equal";
     444             :     case kNotEqual:
     445           0 :       return os << "not equal";
     446             :     case kSignedLessThan:
     447           0 :       return os << "signed less than";
     448             :     case kSignedGreaterThanOrEqual:
     449           0 :       return os << "signed greater than or equal";
     450             :     case kSignedLessThanOrEqual:
     451           0 :       return os << "signed less than or equal";
     452             :     case kSignedGreaterThan:
     453           0 :       return os << "signed greater than";
     454             :     case kUnsignedLessThan:
     455           0 :       return os << "unsigned less than";
     456             :     case kUnsignedGreaterThanOrEqual:
     457           0 :       return os << "unsigned greater than or equal";
     458             :     case kUnsignedLessThanOrEqual:
     459           0 :       return os << "unsigned less than or equal";
     460             :     case kUnsignedGreaterThan:
     461           0 :       return os << "unsigned greater than";
     462             :     case kFloatLessThanOrUnordered:
     463           0 :       return os << "less than or unordered (FP)";
     464             :     case kFloatGreaterThanOrEqual:
     465           0 :       return os << "greater than or equal (FP)";
     466             :     case kFloatLessThanOrEqual:
     467           0 :       return os << "less than or equal (FP)";
     468             :     case kFloatGreaterThanOrUnordered:
     469           0 :       return os << "greater than or unordered (FP)";
     470             :     case kFloatLessThan:
     471           0 :       return os << "less than (FP)";
     472             :     case kFloatGreaterThanOrEqualOrUnordered:
     473           0 :       return os << "greater than, equal or unordered (FP)";
     474             :     case kFloatLessThanOrEqualOrUnordered:
     475           0 :       return os << "less than, equal or unordered (FP)";
     476             :     case kFloatGreaterThan:
     477           0 :       return os << "greater than (FP)";
     478             :     case kUnorderedEqual:
     479           0 :       return os << "unordered equal";
     480             :     case kUnorderedNotEqual:
     481           0 :       return os << "unordered not equal";
     482             :     case kOverflow:
     483           0 :       return os << "overflow";
     484             :     case kNotOverflow:
     485           0 :       return os << "not overflow";
     486             :     case kPositiveOrZero:
     487           0 :       return os << "positive or zero";
     488             :     case kNegative:
     489           0 :       return os << "negative";
     490             :   }
     491           0 :   UNREACHABLE();
     492             : }
     493             : 
     494             : 
     495           0 : std::ostream& operator<<(std::ostream& os,
     496             :                          const PrintableInstruction& printable) {
     497           0 :   const Instruction& instr = *printable.instr_;
     498             :   PrintableInstructionOperand printable_op = {printable.register_configuration_,
     499           0 :                                               InstructionOperand()};
     500           0 :   os << "gap ";
     501           0 :   for (int i = Instruction::FIRST_GAP_POSITION;
     502             :        i <= Instruction::LAST_GAP_POSITION; i++) {
     503           0 :     os << "(";
     504           0 :     if (instr.parallel_moves()[i] != nullptr) {
     505             :       PrintableParallelMove ppm = {printable.register_configuration_,
     506           0 :                                    instr.parallel_moves()[i]};
     507           0 :       os << ppm;
     508             :     }
     509           0 :     os << ") ";
     510             :   }
     511           0 :   os << "\n          ";
     512             : 
     513           0 :   if (instr.OutputCount() > 1) os << "(";
     514           0 :   for (size_t i = 0; i < instr.OutputCount(); i++) {
     515           0 :     if (i > 0) os << ", ";
     516           0 :     printable_op.op_ = *instr.OutputAt(i);
     517           0 :     os << printable_op;
     518             :   }
     519             : 
     520           0 :   if (instr.OutputCount() > 1) os << ") = ";
     521           0 :   if (instr.OutputCount() == 1) os << " = ";
     522             : 
     523           0 :   os << ArchOpcodeField::decode(instr.opcode());
     524           0 :   AddressingMode am = AddressingModeField::decode(instr.opcode());
     525           0 :   if (am != kMode_None) {
     526           0 :     os << " : " << AddressingModeField::decode(instr.opcode());
     527             :   }
     528           0 :   FlagsMode fm = FlagsModeField::decode(instr.opcode());
     529           0 :   if (fm != kFlags_none) {
     530           0 :     os << " && " << fm << " if " << FlagsConditionField::decode(instr.opcode());
     531             :   }
     532           0 :   if (instr.InputCount() > 0) {
     533           0 :     for (size_t i = 0; i < instr.InputCount(); i++) {
     534           0 :       printable_op.op_ = *instr.InputAt(i);
     535           0 :       os << " " << printable_op;
     536             :     }
     537             :   }
     538           0 :   return os;
     539             : }
     540             : 
     541             : 
     542    23150331 : Constant::Constant(int32_t v) : type_(kInt32), value_(v) {}
     543             : 
     544      184623 : Constant::Constant(RelocatablePtrConstantInfo info) {
     545      184623 :   if (info.type() == RelocatablePtrConstantInfo::kInt32) {
     546        3256 :     type_ = kInt32;
     547      181367 :   } else if (info.type() == RelocatablePtrConstantInfo::kInt64) {
     548      181367 :     type_ = kInt64;
     549             :   } else {
     550           0 :     UNREACHABLE();
     551             :   }
     552      184623 :   value_ = info.value();
     553      184623 :   rmode_ = info.rmode();
     554      184623 : }
     555             : 
     556    10075274 : Handle<HeapObject> Constant::ToHeapObject() const {
     557             :   DCHECK_EQ(kHeapObject, type());
     558             :   Handle<HeapObject> value(
     559    10075274 :       bit_cast<HeapObject**>(static_cast<intptr_t>(value_)));
     560    10075274 :   return value;
     561             : }
     562             : 
     563     4540908 : Handle<Code> Constant::ToCode() const {
     564             :   DCHECK_EQ(kHeapObject, type());
     565     4540908 :   Handle<Code> value(bit_cast<Code**>(static_cast<intptr_t>(value_)));
     566     4540908 :   return value;
     567             : }
     568             : 
     569           0 : std::ostream& operator<<(std::ostream& os, const Constant& constant) {
     570           0 :   switch (constant.type()) {
     571             :     case Constant::kInt32:
     572           0 :       return os << constant.ToInt32();
     573             :     case Constant::kInt64:
     574           0 :       return os << constant.ToInt64() << "l";
     575             :     case Constant::kFloat32:
     576           0 :       return os << constant.ToFloat32() << "f";
     577             :     case Constant::kFloat64:
     578             :       return os << constant.ToFloat64().value();
     579             :     case Constant::kExternalReference:
     580             :       return os << static_cast<const void*>(
     581             :                        constant.ToExternalReference().address());
     582             :     case Constant::kHeapObject:
     583           0 :       return os << Brief(*constant.ToHeapObject());
     584             :     case Constant::kRpoNumber:
     585           0 :       return os << "RPO" << constant.ToRpoNumber().ToInt();
     586             :   }
     587           0 :   UNREACHABLE();
     588             : }
     589             : 
     590             : 
     591     1426747 : PhiInstruction::PhiInstruction(Zone* zone, int virtual_register,
     592             :                                size_t input_count)
     593             :     : virtual_register_(virtual_register),
     594             :       output_(UnallocatedOperand(UnallocatedOperand::NONE, virtual_register)),
     595             :       operands_(input_count, InstructionOperand::kInvalidVirtualRegister,
     596     4280255 :                 zone) {}
     597             : 
     598             : 
     599     3541053 : void PhiInstruction::SetInput(size_t offset, int virtual_register) {
     600             :   DCHECK_EQ(InstructionOperand::kInvalidVirtualRegister, operands_[offset]);
     601     7082106 :   operands_[offset] = virtual_register;
     602     3541053 : }
     603             : 
     604       64363 : void PhiInstruction::RenameInput(size_t offset, int virtual_register) {
     605             :   DCHECK_NE(InstructionOperand::kInvalidVirtualRegister, operands_[offset]);
     606      128726 :   operands_[offset] = virtual_register;
     607       64363 : }
     608             : 
     609        8814 : InstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number,
     610             :                                    RpoNumber loop_header, RpoNumber loop_end,
     611             :                                    bool deferred, bool handler)
     612             :     : successors_(zone),
     613             :       predecessors_(zone),
     614             :       phis_(zone),
     615             :       ao_number_(rpo_number),
     616             :       rpo_number_(rpo_number),
     617             :       loop_header_(loop_header),
     618             :       loop_end_(loop_end),
     619             :       code_start_(-1),
     620             :       code_end_(-1),
     621             :       deferred_(deferred),
     622             :       handler_(handler),
     623             :       needs_frame_(false),
     624             :       must_construct_frame_(false),
     625    13054328 :       must_deconstruct_frame_(false) {}
     626             : 
     627    15708622 : size_t InstructionBlock::PredecessorIndexOf(RpoNumber rpo_number) const {
     628             :   size_t j = 0;
     629  1550048850 :   for (InstructionBlock::Predecessors::const_iterator i = predecessors_.begin();
     630             :        i != predecessors_.end(); ++i, ++j) {
     631  1550048815 :     if (*i == rpo_number) break;
     632             :   }
     633    15708622 :   return j;
     634             : }
     635             : 
     636             : 
     637    46357838 : static RpoNumber GetRpo(const BasicBlock* block) {
     638    57846611 :   if (block == nullptr) return RpoNumber::Invalid();
     639             :   return RpoNumber::FromInt(block->rpo_number());
     640             : }
     641             : 
     642             : 
     643    13045489 : static RpoNumber GetLoopEndRpo(const BasicBlock* block) {
     644    13045489 :   if (!block->IsLoopHeader()) return RpoNumber::Invalid();
     645      138647 :   return RpoNumber::FromInt(block->loop_end()->rpo_number());
     646             : }
     647             : 
     648             : 
     649    13045489 : static InstructionBlock* InstructionBlockFor(Zone* zone,
     650    26090978 :                                              const BasicBlock* block) {
     651             :   bool is_handler =
     652    24825507 :       !block->empty() && block->front()->opcode() == IrOpcode::kIfException;
     653             :   InstructionBlock* instr_block = new (zone)
     654             :       InstructionBlock(zone, GetRpo(block), GetRpo(block->loop_header()),
     655             :                        GetLoopEndRpo(block), block->deferred(), is_handler);
     656             :   // Map successors and precessors
     657    13045514 :   instr_block->successors().reserve(block->SuccessorCount());
     658    41968885 :   for (BasicBlock* successor : block->successors()) {
     659    31755674 :     instr_block->successors().push_back(GetRpo(successor));
     660             :   }
     661    13045527 :   instr_block->predecessors().reserve(block->PredecessorCount());
     662    41968784 :   for (BasicBlock* predecessor : block->predecessors()) {
     663    31755588 :     instr_block->predecessors().push_back(GetRpo(predecessor));
     664             :   }
     665    13045489 :   return instr_block;
     666             : }
     667             : 
     668           0 : std::ostream& operator<<(std::ostream& os,
     669             :                          PrintableInstructionBlock& printable_block) {
     670           0 :   const InstructionBlock* block = printable_block.block_;
     671           0 :   const RegisterConfiguration* config = printable_block.register_configuration_;
     672           0 :   const InstructionSequence* code = printable_block.code_;
     673             : 
     674           0 :   os << "B" << block->rpo_number();
     675           0 :   os << ": AO#" << block->ao_number();
     676           0 :   if (block->IsDeferred()) os << " (deferred)";
     677           0 :   if (!block->needs_frame()) os << " (no frame)";
     678           0 :   if (block->must_construct_frame()) os << " (construct frame)";
     679           0 :   if (block->must_deconstruct_frame()) os << " (deconstruct frame)";
     680           0 :   if (block->IsLoopHeader()) {
     681           0 :     os << " loop blocks: [" << block->rpo_number() << ", " << block->loop_end()
     682           0 :        << ")";
     683             :   }
     684           0 :   os << "  instructions: [" << block->code_start() << ", " << block->code_end()
     685           0 :      << ")" << std::endl
     686           0 :      << " predecessors:";
     687             : 
     688           0 :   for (RpoNumber pred : block->predecessors()) {
     689           0 :     os << " B" << pred.ToInt();
     690             :   }
     691             :   os << std::endl;
     692             : 
     693           0 :   for (const PhiInstruction* phi : block->phis()) {
     694           0 :     PrintableInstructionOperand printable_op = {config, phi->output()};
     695           0 :     os << "     phi: " << printable_op << " =";
     696           0 :     for (int input : phi->operands()) {
     697           0 :       os << " v" << input;
     698             :     }
     699             :     os << std::endl;
     700             :   }
     701             : 
     702             :   ScopedVector<char> buf(32);
     703             :   PrintableInstruction printable_instr;
     704           0 :   printable_instr.register_configuration_ = config;
     705           0 :   for (int j = block->first_instruction_index();
     706             :        j <= block->last_instruction_index(); j++) {
     707             :     // TODO(svenpanne) Add some basic formatting to our streams.
     708           0 :     SNPrintF(buf, "%5d", j);
     709           0 :     printable_instr.instr_ = code->InstructionAt(j);
     710           0 :     os << "   " << buf.start() << ": " << printable_instr << std::endl;
     711             :   }
     712             : 
     713           0 :   for (RpoNumber succ : block->successors()) {
     714           0 :     os << " B" << succ.ToInt();
     715             :   }
     716             :   os << std::endl;
     717           0 :   return os;
     718             : }
     719             : 
     720     1301774 : InstructionBlocks* InstructionSequence::InstructionBlocksFor(
     721             :     Zone* zone, const Schedule* schedule) {
     722             :   InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
     723             :   new (blocks) InstructionBlocks(
     724     2603670 :       static_cast<int>(schedule->rpo_order()->size()), nullptr, zone);
     725             :   size_t rpo_number = 0;
     726    28694650 :   for (BasicBlockVector::const_iterator it = schedule->rpo_order()->begin();
     727    14347325 :        it != schedule->rpo_order()->end(); ++it, ++rpo_number) {
     728             :     DCHECK(!(*blocks)[rpo_number]);
     729             :     DCHECK(GetRpo(*it).ToSize() == rpo_number);
     730    26090974 :     (*blocks)[rpo_number] = InstructionBlockFor(zone, *it);
     731             :   }
     732     1301838 :   ComputeAssemblyOrder(blocks);
     733     1301838 :   return blocks;
     734             : }
     735             : 
     736           0 : void InstructionSequence::ValidateEdgeSplitForm() const {
     737             :   // Validate blocks are in edge-split form: no block with multiple successors
     738             :   // has an edge to a block (== a successor) with more than one predecessors.
     739           0 :   for (const InstructionBlock* block : instruction_blocks()) {
     740           0 :     if (block->SuccessorCount() > 1) {
     741           0 :       for (const RpoNumber& successor_id : block->successors()) {
     742           0 :         const InstructionBlock* successor = InstructionBlockAt(successor_id);
     743             :         // Expect precisely one predecessor: "block".
     744           0 :         CHECK(successor->PredecessorCount() == 1 &&
     745             :               successor->predecessors()[0] == block->rpo_number());
     746             :       }
     747             :     }
     748             :   }
     749           0 : }
     750             : 
     751           0 : void InstructionSequence::ValidateDeferredBlockExitPaths() const {
     752             :   // A deferred block with more than one successor must have all its successors
     753             :   // deferred.
     754           0 :   for (const InstructionBlock* block : instruction_blocks()) {
     755           0 :     if (!block->IsDeferred() || block->SuccessorCount() <= 1) continue;
     756           0 :     for (RpoNumber successor_id : block->successors()) {
     757           0 :       CHECK(InstructionBlockAt(successor_id)->IsDeferred());
     758             :     }
     759             :   }
     760           0 : }
     761             : 
     762           0 : void InstructionSequence::ValidateDeferredBlockEntryPaths() const {
     763             :   // If a deferred block has multiple predecessors, they have to
     764             :   // all be deferred. Otherwise, we can run into a situation where a range
     765             :   // that spills only in deferred blocks inserts its spill in the block, but
     766             :   // other ranges need moves inserted by ResolveControlFlow in the predecessors,
     767             :   // which may clobber the register of this range.
     768           0 :   for (const InstructionBlock* block : instruction_blocks()) {
     769           0 :     if (!block->IsDeferred() || block->PredecessorCount() <= 1) continue;
     770           0 :     for (RpoNumber predecessor_id : block->predecessors()) {
     771           0 :       CHECK(InstructionBlockAt(predecessor_id)->IsDeferred());
     772             :     }
     773             :   }
     774           0 : }
     775             : 
     776           0 : void InstructionSequence::ValidateSSA() const {
     777             :   // TODO(mtrofin): We could use a local zone here instead.
     778           0 :   BitVector definitions(VirtualRegisterCount(), zone());
     779           0 :   for (const Instruction* instruction : *this) {
     780           0 :     for (size_t i = 0; i < instruction->OutputCount(); ++i) {
     781           0 :       const InstructionOperand* output = instruction->OutputAt(i);
     782             :       int vreg = (output->IsConstant())
     783             :                      ? ConstantOperand::cast(output)->virtual_register()
     784           0 :                      : UnallocatedOperand::cast(output)->virtual_register();
     785           0 :       CHECK(!definitions.Contains(vreg));
     786             :       definitions.Add(vreg);
     787             :     }
     788             :   }
     789           0 : }
     790             : 
     791     1301836 : void InstructionSequence::ComputeAssemblyOrder(InstructionBlocks* blocks) {
     792             :   int ao = 0;
     793    15649214 :   for (InstructionBlock* const block : *blocks) {
     794    13045542 :     if (!block->IsDeferred()) {
     795     9961385 :       block->set_ao_number(RpoNumber::FromInt(ao++));
     796             :     }
     797             :   }
     798    15649223 :   for (InstructionBlock* const block : *blocks) {
     799    13045551 :     if (block->IsDeferred()) {
     800     3084180 :       block->set_ao_number(RpoNumber::FromInt(ao++));
     801             :     }
     802             :   }
     803     1301836 : }
     804             : 
     805     1303313 : InstructionSequence::InstructionSequence(Isolate* isolate,
     806             :                                          Zone* instruction_zone,
     807     2606604 :                                          InstructionBlocks* instruction_blocks)
     808             :     : isolate_(isolate),
     809             :       zone_(instruction_zone),
     810             :       instruction_blocks_(instruction_blocks),
     811             :       source_positions_(zone()),
     812             :       constants_(ConstantMap::key_compare(),
     813             :                  ConstantMap::allocator_type(zone())),
     814             :       immediates_(zone()),
     815             :       instructions_(zone()),
     816             :       next_virtual_register_(0),
     817             :       reference_maps_(zone()),
     818             :       representations_(zone()),
     819             :       representation_mask_(0),
     820             :       deoptimization_entries_(zone()),
     821     5213220 :       current_block_(nullptr) {}
     822             : 
     823    28117298 : int InstructionSequence::NextVirtualRegister() {
     824    28117298 :   int virtual_register = next_virtual_register_++;
     825    28117298 :   CHECK_NE(virtual_register, InstructionOperand::kInvalidVirtualRegister);
     826    28117298 :   return virtual_register;
     827             : }
     828             : 
     829             : 
     830           0 : Instruction* InstructionSequence::GetBlockStart(RpoNumber rpo) const {
     831           0 :   const InstructionBlock* block = InstructionBlockAt(rpo);
     832           0 :   return InstructionAt(block->code_start());
     833             : }
     834             : 
     835             : 
     836    13053866 : void InstructionSequence::StartBlock(RpoNumber rpo) {
     837             :   DCHECK_NULL(current_block_);
     838    13053866 :   current_block_ = InstructionBlockAt(rpo);
     839    13053976 :   int code_start = static_cast<int>(instructions_.size());
     840             :   current_block_->set_code_start(code_start);
     841    13053976 : }
     842             : 
     843             : 
     844    14355289 : void InstructionSequence::EndBlock(RpoNumber rpo) {
     845    13053883 :   int end = static_cast<int>(instructions_.size());
     846             :   DCHECK_EQ(current_block_->rpo_number(), rpo);
     847    13053883 :   if (current_block_->code_start() == end) {  // Empty block.  Insert a nop.
     848     1301406 :     AddInstruction(Instruction::New(zone(), kArchNop));
     849     1301348 :     end = static_cast<int>(instructions_.size());
     850             :   }
     851             :   DCHECK(current_block_->code_start() >= 0 &&
     852             :          current_block_->code_start() < end);
     853    13053825 :   current_block_->set_code_end(end);
     854    13053825 :   current_block_ = nullptr;
     855    13053825 : }
     856             : 
     857             : 
     858    49312935 : int InstructionSequence::AddInstruction(Instruction* instr) {
     859             :   DCHECK_NOT_NULL(current_block_);
     860    44726679 :   int index = static_cast<int>(instructions_.size());
     861    44726679 :   instr->set_block(current_block_);
     862    44726679 :   instructions_.push_back(instr);
     863    89453288 :   if (instr->NeedsReferenceMap()) {
     864             :     DCHECK_NULL(instr->reference_map());
     865     4586247 :     ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
     866             :     reference_map->set_instruction_position(index);
     867     4586247 :     instr->set_reference_map(reference_map);
     868     4586247 :     reference_maps_.push_back(reference_map);
     869             :   }
     870    44726637 :   return index;
     871             : }
     872             : 
     873             : 
     874   110309429 : InstructionBlock* InstructionSequence::GetInstructionBlock(
     875             :     int instruction_index) const {
     876   110309916 :   return instructions()[instruction_index]->block();
     877             : }
     878             : 
     879             : 
     880    19914105 : static MachineRepresentation FilterRepresentation(MachineRepresentation rep) {
     881    19914105 :   switch (rep) {
     882             :     case MachineRepresentation::kBit:
     883             :     case MachineRepresentation::kWord8:
     884             :     case MachineRepresentation::kWord16:
     885             :       return InstructionSequence::DefaultRepresentation();
     886             :     case MachineRepresentation::kWord32:
     887             :     case MachineRepresentation::kWord64:
     888             :     case MachineRepresentation::kTaggedSigned:
     889             :     case MachineRepresentation::kTaggedPointer:
     890             :     case MachineRepresentation::kTagged:
     891             :     case MachineRepresentation::kFloat32:
     892             :     case MachineRepresentation::kFloat64:
     893             :     case MachineRepresentation::kSimd128:
     894    19698208 :       return rep;
     895             :     case MachineRepresentation::kNone:
     896             :       break;
     897             :   }
     898             : 
     899           0 :   UNREACHABLE();
     900             : }
     901             : 
     902             : 
     903   109783145 : MachineRepresentation InstructionSequence::GetRepresentation(
     904             :     int virtual_register) const {
     905             :   DCHECK_LE(0, virtual_register);
     906             :   DCHECK_LT(virtual_register, VirtualRegisterCount());
     907   219566290 :   if (virtual_register >= static_cast<int>(representations_.size())) {
     908             :     return DefaultRepresentation();
     909             :   }
     910   207250708 :   return representations_[virtual_register];
     911             : }
     912             : 
     913             : 
     914    19914079 : void InstructionSequence::MarkAsRepresentation(MachineRepresentation rep,
     915    11375174 :                                                int virtual_register) {
     916             :   DCHECK_LE(0, virtual_register);
     917             :   DCHECK_LT(virtual_register, VirtualRegisterCount());
     918    59742333 :   if (virtual_register >= static_cast<int>(representations_.size())) {
     919    22750348 :     representations_.resize(VirtualRegisterCount(), DefaultRepresentation());
     920             :   }
     921    19914113 :   rep = FilterRepresentation(rep);
     922             :   DCHECK_IMPLIES(representations_[virtual_register] != rep,
     923             :                  representations_[virtual_register] == DefaultRepresentation());
     924    39828350 :   representations_[virtual_register] = rep;
     925    19914175 :   representation_mask_ |= 1 << static_cast<int>(rep);
     926    19914175 : }
     927             : 
     928     3087697 : int InstructionSequence::AddDeoptimizationEntry(
     929             :     FrameStateDescriptor* descriptor, DeoptimizeKind kind,
     930             :     DeoptimizeReason reason) {
     931     6175394 :   int deoptimization_id = static_cast<int>(deoptimization_entries_.size());
     932             :   deoptimization_entries_.push_back(
     933     6175407 :       DeoptimizationEntry(descriptor, kind, reason));
     934     3087710 :   return deoptimization_id;
     935             : }
     936             : 
     937     5821406 : DeoptimizationEntry const& InstructionSequence::GetDeoptimizationEntry(
     938             :     int state_id) {
     939    11642812 :   return deoptimization_entries_[state_id];
     940             : }
     941             : 
     942             : 
     943     4759032 : RpoNumber InstructionSequence::InputRpo(Instruction* instr, size_t index) {
     944     4759032 :   InstructionOperand* operand = instr->InputAt(index);
     945             :   Constant constant =
     946             :       operand->IsImmediate()
     947             :           ? GetImmediate(ImmediateOperand::cast(operand))
     948     4759032 :           : GetConstant(ConstantOperand::cast(operand)->virtual_register());
     949     4759063 :   return constant.ToRpoNumber();
     950             : }
     951             : 
     952             : 
     953    27414681 : bool InstructionSequence::GetSourcePosition(const Instruction* instr,
     954             :                                             SourcePosition* result) const {
     955             :   auto it = source_positions_.find(instr);
     956    27414724 :   if (it == source_positions_.end()) return false;
     957     4219960 :   *result = it->second;
     958     4219960 :   return true;
     959             : }
     960             : 
     961             : 
     962     4723253 : void InstructionSequence::SetSourcePosition(const Instruction* instr,
     963             :                                             SourcePosition value) {
     964     9446520 :   source_positions_.insert(std::make_pair(instr, value));
     965     4723267 : }
     966             : 
     967           0 : void InstructionSequence::Print(const RegisterConfiguration* config) const {
     968           0 :   OFStream os(stdout);
     969             :   PrintableInstructionSequence wrapper;
     970           0 :   wrapper.register_configuration_ = config;
     971           0 :   wrapper.sequence_ = this;
     972           0 :   os << wrapper << std::endl;
     973           0 : }
     974             : 
     975           0 : void InstructionSequence::Print() const { Print(GetRegConfig()); }
     976             : 
     977           0 : void InstructionSequence::PrintBlock(const RegisterConfiguration* config,
     978           0 :                                      int block_id) const {
     979           0 :   OFStream os(stdout);
     980             :   RpoNumber rpo = RpoNumber::FromInt(block_id);
     981           0 :   const InstructionBlock* block = InstructionBlockAt(rpo);
     982           0 :   CHECK(block->rpo_number() == rpo);
     983           0 :   PrintableInstructionBlock printable_block = {config, block, this};
     984           0 :   os << printable_block << std::endl;
     985           0 : }
     986             : 
     987           0 : void InstructionSequence::PrintBlock(int block_id) const {
     988           0 :   PrintBlock(GetRegConfig(), block_id);
     989           0 : }
     990             : 
     991             : const RegisterConfiguration*
     992             :     InstructionSequence::registerConfigurationForTesting_ = nullptr;
     993             : 
     994             : const RegisterConfiguration*
     995           0 : InstructionSequence::RegisterConfigurationForTesting() {
     996             :   DCHECK_NOT_NULL(registerConfigurationForTesting_);
     997           0 :   return registerConfigurationForTesting_;
     998             : }
     999             : 
    1000          52 : void InstructionSequence::SetRegisterConfigurationForTesting(
    1001             :     const RegisterConfiguration* regConfig) {
    1002          52 :   registerConfigurationForTesting_ = regConfig;
    1003          52 :   GetRegConfig = InstructionSequence::RegisterConfigurationForTesting;
    1004          52 : }
    1005             : 
    1006     3360385 : FrameStateDescriptor::FrameStateDescriptor(
    1007             :     Zone* zone, FrameStateType type, BailoutId bailout_id,
    1008             :     OutputFrameStateCombine state_combine, size_t parameters_count,
    1009             :     size_t locals_count, size_t stack_count,
    1010             :     MaybeHandle<SharedFunctionInfo> shared_info,
    1011             :     FrameStateDescriptor* outer_state)
    1012             :     : type_(type),
    1013             :       bailout_id_(bailout_id),
    1014             :       frame_state_combine_(state_combine),
    1015             :       parameters_count_(parameters_count),
    1016             :       locals_count_(locals_count),
    1017             :       stack_count_(stack_count),
    1018             :       values_(zone),
    1019             :       shared_info_(shared_info),
    1020     6720770 :       outer_state_(outer_state) {}
    1021             : 
    1022    99119349 : size_t FrameStateDescriptor::GetSize() const {
    1023    99119349 :   return 1 + parameters_count() + locals_count() + stack_count() +
    1024    33039783 :          (HasContext() ? 1 : 0);
    1025             : }
    1026             : 
    1027             : 
    1028     3087711 : size_t FrameStateDescriptor::GetTotalSize() const {
    1029             :   size_t total_size = 0;
    1030     6448090 :   for (const FrameStateDescriptor* iter = this; iter != nullptr;
    1031             :        iter = iter->outer_state_) {
    1032     3360378 :     total_size += iter->GetSize();
    1033             :   }
    1034     3087712 :   return total_size;
    1035             : }
    1036             : 
    1037             : 
    1038     3087695 : size_t FrameStateDescriptor::GetFrameCount() const {
    1039             :   size_t count = 0;
    1040     6448062 :   for (const FrameStateDescriptor* iter = this; iter != nullptr;
    1041             :        iter = iter->outer_state_) {
    1042     3360367 :     ++count;
    1043             :   }
    1044     3087695 :   return count;
    1045             : }
    1046             : 
    1047             : 
    1048     3087701 : size_t FrameStateDescriptor::GetJSFrameCount() const {
    1049             :   size_t count = 0;
    1050     6448063 :   for (const FrameStateDescriptor* iter = this; iter != nullptr;
    1051             :        iter = iter->outer_state_) {
    1052     6720724 :     if (FrameStateFunctionInfo::IsJSFunctionType(iter->type_)) {
    1053     3259924 :       ++count;
    1054             :     }
    1055             :   }
    1056     3087701 :   return count;
    1057             : }
    1058             : 
    1059             : 
    1060           0 : std::ostream& operator<<(std::ostream& os, const RpoNumber& rpo) {
    1061           0 :   return os << rpo.ToSize();
    1062             : }
    1063             : 
    1064             : 
    1065           0 : std::ostream& operator<<(std::ostream& os,
    1066             :                          const PrintableInstructionSequence& printable) {
    1067           0 :   const InstructionSequence& code = *printable.sequence_;
    1068           0 :   for (size_t i = 0; i < code.immediates_.size(); ++i) {
    1069           0 :     Constant constant = code.immediates_[i];
    1070           0 :     os << "IMM#" << i << ": " << constant << "\n";
    1071             :   }
    1072             :   int i = 0;
    1073           0 :   for (ConstantMap::const_iterator it = code.constants_.begin();
    1074             :        it != code.constants_.end(); ++i, ++it) {
    1075           0 :     os << "CST#" << i << ": v" << it->first << " = " << it->second << "\n";
    1076             :   }
    1077             :   PrintableInstructionBlock printable_block = {
    1078           0 :       printable.register_configuration_, nullptr, printable.sequence_};
    1079           0 :   for (int i = 0; i < code.InstructionBlockCount(); i++) {
    1080           0 :     printable_block.block_ = code.InstructionBlockAt(RpoNumber::FromInt(i));
    1081           0 :     os << printable_block;
    1082             :   }
    1083           0 :   return os;
    1084             : }
    1085             : 
    1086             : }  // namespace compiler
    1087             : }  // namespace internal
    1088             : }  // namespace v8

Generated by: LCOV version 1.10