LCOV - code coverage report
Current view: top level - src/compiler - graph-visualizer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 83 359 23.1 %
Date: 2017-04-26 Functions: 9 32 28.1 %

          Line data    Source code
       1             : // Copyright 2013 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/graph-visualizer.h"
       6             : 
       7             : #include <memory>
       8             : #include <sstream>
       9             : #include <string>
      10             : 
      11             : #include "src/code-stubs.h"
      12             : #include "src/compilation-info.h"
      13             : #include "src/compiler/all-nodes.h"
      14             : #include "src/compiler/compiler-source-position-table.h"
      15             : #include "src/compiler/graph.h"
      16             : #include "src/compiler/node-properties.h"
      17             : #include "src/compiler/node.h"
      18             : #include "src/compiler/opcodes.h"
      19             : #include "src/compiler/operator-properties.h"
      20             : #include "src/compiler/operator.h"
      21             : #include "src/compiler/register-allocator.h"
      22             : #include "src/compiler/schedule.h"
      23             : #include "src/compiler/scheduler.h"
      24             : #include "src/interpreter/bytecodes.h"
      25             : #include "src/objects-inl.h"
      26             : #include "src/ostreams.h"
      27             : 
      28             : namespace v8 {
      29             : namespace internal {
      30             : namespace compiler {
      31             : 
      32           0 : std::unique_ptr<char[]> GetVisualizerLogFileName(CompilationInfo* info,
      33             :                                                  const char* phase,
      34             :                                                  const char* suffix) {
      35             :   EmbeddedVector<char, 256> filename(0);
      36           0 :   std::unique_ptr<char[]> debug_name = info->GetDebugName();
      37           0 :   if (strlen(debug_name.get()) > 0) {
      38           0 :     if (info->has_shared_info()) {
      39           0 :       int attempt = info->shared_info()->opt_count();
      40           0 :       SNPrintF(filename, "turbo-%s-%i", debug_name.get(), attempt);
      41             :     } else {
      42           0 :       SNPrintF(filename, "turbo-%s", debug_name.get());
      43             :     }
      44           0 :   } else if (info->has_shared_info()) {
      45           0 :     int attempt = info->shared_info()->opt_count();
      46           0 :     SNPrintF(filename, "turbo-%p-%i", static_cast<void*>(info), attempt);
      47             :   } else {
      48           0 :     SNPrintF(filename, "turbo-none-%s", phase);
      49             :   }
      50             :   EmbeddedVector<char, 256> source_file(0);
      51             :   bool source_available = false;
      52           0 :   if (FLAG_trace_file_names && info->parse_info()) {
      53           0 :     Object* source_name = info->script()->name();
      54           0 :     if (source_name->IsString()) {
      55             :       String* str = String::cast(source_name);
      56           0 :       if (str->length() > 0) {
      57           0 :         SNPrintF(source_file, "%s", str->ToCString().get());
      58             :         std::replace(source_file.start(),
      59           0 :                      source_file.start() + source_file.length(), '/', '_');
      60             :         source_available = true;
      61             :       }
      62             :     }
      63             :   }
      64           0 :   std::replace(filename.start(), filename.start() + filename.length(), ' ',
      65           0 :                '_');
      66             : 
      67             :   EmbeddedVector<char, 256> full_filename;
      68           0 :   if (phase == nullptr && !source_available) {
      69           0 :     SNPrintF(full_filename, "%s.%s", filename.start(), suffix);
      70           0 :   } else if (phase != nullptr && !source_available) {
      71           0 :     SNPrintF(full_filename, "%s-%s.%s", filename.start(), phase, suffix);
      72           0 :   } else if (phase == nullptr && source_available) {
      73             :     SNPrintF(full_filename, "%s_%s.%s", filename.start(), source_file.start(),
      74           0 :              suffix);
      75             :   } else {
      76             :     SNPrintF(full_filename, "%s_%s-%s.%s", filename.start(),
      77           0 :              source_file.start(), phase, suffix);
      78             :   }
      79             : 
      80           0 :   char* buffer = new char[full_filename.length() + 1];
      81           0 :   memcpy(buffer, full_filename.start(), full_filename.length());
      82           0 :   buffer[full_filename.length()] = '\0';
      83           0 :   return std::unique_ptr<char[]>(buffer);
      84             : }
      85             : 
      86             : 
      87         700 : static int SafeId(Node* node) { return node == nullptr ? -1 : node->id(); }
      88           0 : static const char* SafeMnemonic(Node* node) {
      89           0 :   return node == nullptr ? "null" : node->op()->mnemonic();
      90             : }
      91             : 
      92             : class JSONEscaped {
      93             :  public:
      94             :   explicit JSONEscaped(const std::ostringstream& os) : str_(os.str()) {}
      95             : 
      96         420 :   friend std::ostream& operator<<(std::ostream& os, const JSONEscaped& e) {
      97        5516 :     for (char c : e.str_) PipeCharacter(os, c);
      98         420 :     return os;
      99             :   }
     100             : 
     101             :  private:
     102        4676 :   static std::ostream& PipeCharacter(std::ostream& os, char c) {
     103        4676 :     if (c == '"') return os << "\\\"";
     104        4676 :     if (c == '\\') return os << "\\\\";
     105        4676 :     if (c == '\b') return os << "\\b";
     106        4676 :     if (c == '\f') return os << "\\f";
     107        4676 :     if (c == '\n') return os << "\\n";
     108        4676 :     if (c == '\r') return os << "\\r";
     109        4676 :     if (c == '\t') return os << "\\t";
     110        4676 :     return os << c;
     111             :   }
     112             : 
     113             :   const std::string str_;
     114             : };
     115             : 
     116             : class JSONGraphNodeWriter {
     117             :  public:
     118          35 :   JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph,
     119             :                       const SourcePositionTable* positions)
     120             :       : os_(os),
     121             :         all_(zone, graph, false),
     122             :         live_(zone, graph, true),
     123             :         positions_(positions),
     124          35 :         first_node_(true) {}
     125             : 
     126          35 :   void Print() {
     127         210 :     for (Node* const node : all_.reachable) PrintNode(node);
     128          35 :     os_ << "\n";
     129          35 :   }
     130             : 
     131         980 :   void PrintNode(Node* node) {
     132         140 :     if (first_node_) {
     133          35 :       first_node_ = false;
     134             :     } else {
     135         105 :       os_ << ",\n";
     136             :     }
     137         280 :     std::ostringstream label, title, properties;
     138             :     node->op()->PrintTo(label, Operator::PrintVerbosity::kSilent);
     139             :     node->op()->PrintTo(title, Operator::PrintVerbosity::kVerbose);
     140         140 :     node->op()->PrintPropsTo(properties);
     141         280 :     os_ << "{\"id\":" << SafeId(node) << ",\"label\":\"" << JSONEscaped(label)
     142         140 :         << "\""
     143         280 :         << ",\"title\":\"" << JSONEscaped(title) << "\""
     144         280 :         << ",\"live\": " << (live_.IsLive(node) ? "true" : "false")
     145         280 :         << ",\"properties\":\"" << JSONEscaped(properties) << "\"";
     146             :     IrOpcode::Value opcode = node->opcode();
     147         140 :     if (IrOpcode::IsPhiOpcode(opcode)) {
     148          21 :       os_ << ",\"rankInputs\":[0," << NodeProperties::FirstControlIndex(node)
     149          21 :           << "]";
     150          21 :       os_ << ",\"rankWithInput\":[" << NodeProperties::FirstControlIndex(node)
     151          21 :           << "]";
     152         238 :     } else if (opcode == IrOpcode::kIfTrue || opcode == IrOpcode::kIfFalse ||
     153         119 :                opcode == IrOpcode::kLoop) {
     154           0 :       os_ << ",\"rankInputs\":[" << NodeProperties::FirstControlIndex(node)
     155           0 :           << "]";
     156             :     }
     157         140 :     if (opcode == IrOpcode::kBranch) {
     158           0 :       os_ << ",\"rankInputs\":[0]";
     159             :     }
     160         140 :     SourcePosition position = positions_->GetSourcePosition(node);
     161         140 :     if (position.IsKnown()) {
     162           0 :       os_ << ",\"pos\":" << position.ScriptOffset();
     163             :     }
     164         140 :     os_ << ",\"opcode\":\"" << IrOpcode::Mnemonic(node->opcode()) << "\"";
     165         140 :     os_ << ",\"control\":" << (NodeProperties::IsControl(node) ? "true"
     166         280 :                                                                : "false");
     167         280 :     os_ << ",\"opinfo\":\"" << node->op()->ValueInputCount() << " v "
     168         280 :         << node->op()->EffectInputCount() << " eff "
     169         280 :         << node->op()->ControlInputCount() << " ctrl in, "
     170         280 :         << node->op()->ValueOutputCount() << " v "
     171         280 :         << node->op()->EffectOutputCount() << " eff "
     172         280 :         << node->op()->ControlOutputCount() << " ctrl out\"";
     173         140 :     if (NodeProperties::IsTyped(node)) {
     174             :       Type* type = NodeProperties::GetType(node);
     175           0 :       std::ostringstream type_out;
     176           0 :       type->PrintTo(type_out);
     177           0 :       os_ << ",\"type\":\"" << JSONEscaped(type_out) << "\"";
     178             :     }
     179         280 :     os_ << "}";
     180         140 :   }
     181             : 
     182             :  private:
     183             :   std::ostream& os_;
     184             :   AllNodes all_;
     185             :   AllNodes live_;
     186             :   const SourcePositionTable* positions_;
     187             :   bool first_node_;
     188             : 
     189             :   DISALLOW_COPY_AND_ASSIGN(JSONGraphNodeWriter);
     190             : };
     191             : 
     192             : 
     193             : class JSONGraphEdgeWriter {
     194             :  public:
     195             :   JSONGraphEdgeWriter(std::ostream& os, Zone* zone, const Graph* graph)
     196          35 :       : os_(os), all_(zone, graph, false), first_edge_(true) {}
     197             : 
     198          35 :   void Print() {
     199         210 :     for (Node* const node : all_.reachable) PrintEdges(node);
     200          35 :     os_ << "\n";
     201          35 :   }
     202             : 
     203         140 :   void PrintEdges(Node* node) {
     204         616 :     for (int i = 0; i < node->InputCount(); i++) {
     205             :       Node* input = node->InputAt(i);
     206         168 :       if (input == nullptr) continue;
     207         140 :       PrintEdge(node, i, input);
     208             :     }
     209         140 :   }
     210             : 
     211         140 :   void PrintEdge(Node* from, int index, Node* to) {
     212         140 :     if (first_edge_) {
     213          35 :       first_edge_ = false;
     214             :     } else {
     215         105 :       os_ << ",\n";
     216             :     }
     217             :     const char* edge_type = nullptr;
     218         140 :     if (index < NodeProperties::FirstValueIndex(from)) {
     219             :       edge_type = "unknown";
     220         140 :     } else if (index < NodeProperties::FirstContextIndex(from)) {
     221             :       edge_type = "value";
     222          21 :     } else if (index < NodeProperties::FirstFrameStateIndex(from)) {
     223             :       edge_type = "context";
     224          21 :     } else if (index < NodeProperties::FirstEffectIndex(from)) {
     225             :       edge_type = "frame-state";
     226          21 :     } else if (index < NodeProperties::FirstControlIndex(from)) {
     227             :       edge_type = "effect";
     228             :     } else {
     229             :       edge_type = "control";
     230             :     }
     231         140 :     os_ << "{\"source\":" << SafeId(to) << ",\"target\":" << SafeId(from)
     232         140 :         << ",\"index\":" << index << ",\"type\":\"" << edge_type << "\"}";
     233         140 :   }
     234             : 
     235             :  private:
     236             :   std::ostream& os_;
     237             :   AllNodes all_;
     238             :   bool first_edge_;
     239             : 
     240             :   DISALLOW_COPY_AND_ASSIGN(JSONGraphEdgeWriter);
     241             : };
     242             : 
     243             : 
     244          35 : std::ostream& operator<<(std::ostream& os, const AsJSON& ad) {
     245          35 :   AccountingAllocator allocator;
     246          70 :   Zone tmp_zone(&allocator, ZONE_NAME);
     247          35 :   os << "{\n\"nodes\":[";
     248          35 :   JSONGraphNodeWriter(os, &tmp_zone, &ad.graph, ad.positions).Print();
     249          35 :   os << "],\n\"edges\":[";
     250          70 :   JSONGraphEdgeWriter(os, &tmp_zone, &ad.graph).Print();
     251          35 :   os << "]}";
     252          35 :   return os;
     253             : }
     254             : 
     255             : 
     256             : class GraphC1Visualizer {
     257             :  public:
     258             :   GraphC1Visualizer(std::ostream& os, Zone* zone);  // NOLINT
     259             : 
     260             :   void PrintCompilation(const CompilationInfo* info);
     261             :   void PrintSchedule(const char* phase, const Schedule* schedule,
     262             :                      const SourcePositionTable* positions,
     263             :                      const InstructionSequence* instructions);
     264             :   void PrintLiveRanges(const char* phase, const RegisterAllocationData* data);
     265             :   Zone* zone() const { return zone_; }
     266             : 
     267             :  private:
     268             :   void PrintIndent();
     269             :   void PrintStringProperty(const char* name, const char* value);
     270             :   void PrintLongProperty(const char* name, int64_t value);
     271             :   void PrintIntProperty(const char* name, int value);
     272             :   void PrintBlockProperty(const char* name, int rpo_number);
     273             :   void PrintNodeId(Node* n);
     274             :   void PrintNode(Node* n);
     275             :   void PrintInputs(Node* n);
     276             :   template <typename InputIterator>
     277             :   void PrintInputs(InputIterator* i, int count, const char* prefix);
     278             :   void PrintType(Node* node);
     279             : 
     280             :   void PrintLiveRange(const LiveRange* range, const char* type, int vreg);
     281             :   void PrintLiveRangeChain(const TopLevelLiveRange* range, const char* type);
     282             : 
     283             :   class Tag final BASE_EMBEDDED {
     284             :    public:
     285           0 :     Tag(GraphC1Visualizer* visualizer, const char* name) {
     286           0 :       name_ = name;
     287           0 :       visualizer_ = visualizer;
     288             :       visualizer->PrintIndent();
     289           0 :       visualizer_->os_ << "begin_" << name << "\n";
     290           0 :       visualizer->indent_++;
     291           0 :     }
     292             : 
     293           0 :     ~Tag() {
     294           0 :       visualizer_->indent_--;
     295             :       visualizer_->PrintIndent();
     296           0 :       visualizer_->os_ << "end_" << name_ << "\n";
     297             :       DCHECK(visualizer_->indent_ >= 0);
     298           0 :     }
     299             : 
     300             :    private:
     301             :     GraphC1Visualizer* visualizer_;
     302             :     const char* name_;
     303             :   };
     304             : 
     305             :   std::ostream& os_;
     306             :   int indent_;
     307             :   Zone* zone_;
     308             : 
     309             :   DISALLOW_COPY_AND_ASSIGN(GraphC1Visualizer);
     310             : };
     311             : 
     312             : 
     313           0 : void GraphC1Visualizer::PrintIndent() {
     314           0 :   for (int i = 0; i < indent_; i++) {
     315           0 :     os_ << "  ";
     316             :   }
     317           0 : }
     318             : 
     319             : 
     320           0 : GraphC1Visualizer::GraphC1Visualizer(std::ostream& os, Zone* zone)
     321           0 :     : os_(os), indent_(0), zone_(zone) {}
     322             : 
     323             : 
     324           0 : void GraphC1Visualizer::PrintStringProperty(const char* name,
     325             :                                             const char* value) {
     326             :   PrintIndent();
     327           0 :   os_ << name << " \"" << value << "\"\n";
     328           0 : }
     329             : 
     330             : 
     331           0 : void GraphC1Visualizer::PrintLongProperty(const char* name, int64_t value) {
     332             :   PrintIndent();
     333           0 :   os_ << name << " " << static_cast<int>(value / 1000) << "\n";
     334           0 : }
     335             : 
     336             : 
     337           0 : void GraphC1Visualizer::PrintBlockProperty(const char* name, int rpo_number) {
     338             :   PrintIndent();
     339           0 :   os_ << name << " \"B" << rpo_number << "\"\n";
     340           0 : }
     341             : 
     342             : 
     343           0 : void GraphC1Visualizer::PrintIntProperty(const char* name, int value) {
     344             :   PrintIndent();
     345           0 :   os_ << name << " " << value << "\n";
     346           0 : }
     347             : 
     348             : 
     349           0 : void GraphC1Visualizer::PrintCompilation(const CompilationInfo* info) {
     350           0 :   Tag tag(this, "compilation");
     351           0 :   std::unique_ptr<char[]> name = info->GetDebugName();
     352           0 :   if (info->IsOptimizing()) {
     353           0 :     PrintStringProperty("name", name.get());
     354             :     PrintIndent();
     355           0 :     os_ << "method \"" << name.get() << ":" << info->optimization_id()
     356           0 :         << "\"\n";
     357             :   } else {
     358           0 :     PrintStringProperty("name", name.get());
     359           0 :     PrintStringProperty("method", "stub");
     360             :   }
     361             :   PrintLongProperty("date",
     362           0 :                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
     363           0 : }
     364             : 
     365             : 
     366           0 : void GraphC1Visualizer::PrintNodeId(Node* n) { os_ << "n" << SafeId(n); }
     367             : 
     368             : 
     369           0 : void GraphC1Visualizer::PrintNode(Node* n) {
     370           0 :   PrintNodeId(n);
     371           0 :   os_ << " " << *n->op() << " ";
     372           0 :   PrintInputs(n);
     373           0 : }
     374             : 
     375             : 
     376             : template <typename InputIterator>
     377           0 : void GraphC1Visualizer::PrintInputs(InputIterator* i, int count,
     378             :                                     const char* prefix) {
     379           0 :   if (count > 0) {
     380           0 :     os_ << prefix;
     381             :   }
     382           0 :   while (count > 0) {
     383           0 :     os_ << " ";
     384           0 :     PrintNodeId(**i);
     385             :     ++(*i);
     386           0 :     count--;
     387             :   }
     388           0 : }
     389             : 
     390             : 
     391           0 : void GraphC1Visualizer::PrintInputs(Node* node) {
     392             :   auto i = node->inputs().begin();
     393           0 :   PrintInputs(&i, node->op()->ValueInputCount(), " ");
     394             :   PrintInputs(&i, OperatorProperties::GetContextInputCount(node->op()),
     395           0 :               " Ctx:");
     396             :   PrintInputs(&i, OperatorProperties::GetFrameStateInputCount(node->op()),
     397           0 :               " FS:");
     398           0 :   PrintInputs(&i, node->op()->EffectInputCount(), " Eff:");
     399           0 :   PrintInputs(&i, node->op()->ControlInputCount(), " Ctrl:");
     400           0 : }
     401             : 
     402             : 
     403           0 : void GraphC1Visualizer::PrintType(Node* node) {
     404           0 :   if (NodeProperties::IsTyped(node)) {
     405             :     Type* type = NodeProperties::GetType(node);
     406           0 :     os_ << " type:";
     407           0 :     type->PrintTo(os_);
     408             :   }
     409           0 : }
     410             : 
     411             : 
     412           0 : void GraphC1Visualizer::PrintSchedule(const char* phase,
     413             :                                       const Schedule* schedule,
     414             :                                       const SourcePositionTable* positions,
     415           0 :                                       const InstructionSequence* instructions) {
     416           0 :   Tag tag(this, "cfg");
     417           0 :   PrintStringProperty("name", phase);
     418             :   const BasicBlockVector* rpo = schedule->rpo_order();
     419           0 :   for (size_t i = 0; i < rpo->size(); i++) {
     420           0 :     BasicBlock* current = (*rpo)[i];
     421           0 :     Tag block_tag(this, "block");
     422           0 :     PrintBlockProperty("name", current->rpo_number());
     423           0 :     PrintIntProperty("from_bci", -1);
     424           0 :     PrintIntProperty("to_bci", -1);
     425             : 
     426             :     PrintIndent();
     427           0 :     os_ << "predecessors";
     428           0 :     for (BasicBlock* predecessor : current->predecessors()) {
     429           0 :       os_ << " \"B" << predecessor->rpo_number() << "\"";
     430             :     }
     431           0 :     os_ << "\n";
     432             : 
     433             :     PrintIndent();
     434           0 :     os_ << "successors";
     435           0 :     for (BasicBlock* successor : current->successors()) {
     436           0 :       os_ << " \"B" << successor->rpo_number() << "\"";
     437             :     }
     438           0 :     os_ << "\n";
     439             : 
     440             :     PrintIndent();
     441           0 :     os_ << "xhandlers\n";
     442             : 
     443             :     PrintIndent();
     444           0 :     os_ << "flags\n";
     445             : 
     446           0 :     if (current->dominator() != nullptr) {
     447           0 :       PrintBlockProperty("dominator", current->dominator()->rpo_number());
     448             :     }
     449             : 
     450           0 :     PrintIntProperty("loop_depth", current->loop_depth());
     451             : 
     452           0 :     const InstructionBlock* instruction_block =
     453             :         instructions->InstructionBlockAt(
     454           0 :             RpoNumber::FromInt(current->rpo_number()));
     455           0 :     if (instruction_block->code_start() >= 0) {
     456             :       int first_index = instruction_block->first_instruction_index();
     457             :       int last_index = instruction_block->last_instruction_index();
     458             :       PrintIntProperty(
     459             :           "first_lir_id",
     460           0 :           LifetimePosition::GapFromInstructionIndex(first_index).value());
     461             :       PrintIntProperty("last_lir_id",
     462             :                        LifetimePosition::InstructionFromInstructionIndex(
     463           0 :                            last_index).value());
     464             :     }
     465             : 
     466             :     {
     467           0 :       Tag states_tag(this, "states");
     468           0 :       Tag locals_tag(this, "locals");
     469             :       int total = 0;
     470           0 :       for (BasicBlock::const_iterator i = current->begin(); i != current->end();
     471             :            ++i) {
     472           0 :         if ((*i)->opcode() == IrOpcode::kPhi) total++;
     473             :       }
     474           0 :       PrintIntProperty("size", total);
     475           0 :       PrintStringProperty("method", "None");
     476             :       int index = 0;
     477           0 :       for (BasicBlock::const_iterator i = current->begin(); i != current->end();
     478             :            ++i) {
     479           0 :         if ((*i)->opcode() != IrOpcode::kPhi) continue;
     480             :         PrintIndent();
     481           0 :         os_ << index << " ";
     482           0 :         PrintNodeId(*i);
     483           0 :         os_ << " [";
     484           0 :         PrintInputs(*i);
     485           0 :         os_ << "]\n";
     486           0 :         index++;
     487           0 :       }
     488             :     }
     489             : 
     490             :     {
     491           0 :       Tag HIR_tag(this, "HIR");
     492           0 :       for (BasicBlock::const_iterator i = current->begin(); i != current->end();
     493             :            ++i) {
     494           0 :         Node* node = *i;
     495           0 :         if (node->opcode() == IrOpcode::kPhi) continue;
     496           0 :         int uses = node->UseCount();
     497             :         PrintIndent();
     498           0 :         os_ << "0 " << uses << " ";
     499           0 :         PrintNode(node);
     500           0 :         if (FLAG_trace_turbo_types) {
     501           0 :           os_ << " ";
     502           0 :           PrintType(node);
     503             :         }
     504           0 :         if (positions != nullptr) {
     505           0 :           SourcePosition position = positions->GetSourcePosition(node);
     506           0 :           if (position.IsKnown()) {
     507           0 :             os_ << " pos:";
     508           0 :             if (position.isInlined()) {
     509           0 :               os_ << "inlining(" << position.InliningId() << "),";
     510             :             }
     511           0 :             os_ << position.ScriptOffset();
     512             :           }
     513             :         }
     514           0 :         os_ << " <|@\n";
     515             :       }
     516             : 
     517             :       BasicBlock::Control control = current->control();
     518           0 :       if (control != BasicBlock::kNone) {
     519             :         PrintIndent();
     520           0 :         os_ << "0 0 ";
     521           0 :         if (current->control_input() != nullptr) {
     522           0 :           PrintNode(current->control_input());
     523             :         } else {
     524           0 :           os_ << -1 - current->rpo_number() << " Goto";
     525             :         }
     526           0 :         os_ << " ->";
     527           0 :         for (BasicBlock* successor : current->successors()) {
     528           0 :           os_ << " B" << successor->rpo_number();
     529             :         }
     530           0 :         if (FLAG_trace_turbo_types && current->control_input() != nullptr) {
     531           0 :           os_ << " ";
     532           0 :           PrintType(current->control_input());
     533             :         }
     534           0 :         os_ << " <|@\n";
     535           0 :       }
     536             :     }
     537             : 
     538           0 :     if (instructions != nullptr) {
     539           0 :       Tag LIR_tag(this, "LIR");
     540           0 :       for (int j = instruction_block->first_instruction_index();
     541             :            j <= instruction_block->last_instruction_index(); j++) {
     542             :         PrintIndent();
     543           0 :         PrintableInstruction printable = {RegisterConfiguration::Turbofan(),
     544           0 :                                           instructions->InstructionAt(j)};
     545           0 :         os_ << j << " " << printable << " <|@\n";
     546           0 :       }
     547             :     }
     548           0 :   }
     549           0 : }
     550             : 
     551             : 
     552           0 : void GraphC1Visualizer::PrintLiveRanges(const char* phase,
     553             :                                         const RegisterAllocationData* data) {
     554           0 :   Tag tag(this, "intervals");
     555           0 :   PrintStringProperty("name", phase);
     556             : 
     557           0 :   for (const TopLevelLiveRange* range : data->fixed_double_live_ranges()) {
     558           0 :     PrintLiveRangeChain(range, "fixed");
     559             :   }
     560             : 
     561           0 :   for (const TopLevelLiveRange* range : data->fixed_live_ranges()) {
     562           0 :     PrintLiveRangeChain(range, "fixed");
     563             :   }
     564             : 
     565           0 :   for (const TopLevelLiveRange* range : data->live_ranges()) {
     566           0 :     PrintLiveRangeChain(range, "object");
     567           0 :   }
     568           0 : }
     569             : 
     570           0 : void GraphC1Visualizer::PrintLiveRangeChain(const TopLevelLiveRange* range,
     571             :                                             const char* type) {
     572           0 :   if (range == nullptr || range->IsEmpty()) return;
     573             :   int vreg = range->vreg();
     574           0 :   for (const LiveRange* child = range; child != nullptr;
     575             :        child = child->next()) {
     576           0 :     PrintLiveRange(child, type, vreg);
     577             :   }
     578             : }
     579             : 
     580           0 : void GraphC1Visualizer::PrintLiveRange(const LiveRange* range, const char* type,
     581             :                                        int vreg) {
     582           0 :   if (range != nullptr && !range->IsEmpty()) {
     583             :     PrintIndent();
     584           0 :     os_ << vreg << ":" << range->relative_id() << " " << type;
     585           0 :     if (range->HasRegisterAssigned()) {
     586           0 :       AllocatedOperand op = AllocatedOperand::cast(range->GetAssignedOperand());
     587           0 :       const auto config = RegisterConfiguration::Turbofan();
     588           0 :       if (op.IsRegister()) {
     589           0 :         os_ << " \"" << config->GetGeneralRegisterName(op.register_code())
     590           0 :             << "\"";
     591           0 :       } else if (op.IsDoubleRegister()) {
     592           0 :         os_ << " \"" << config->GetDoubleRegisterName(op.register_code())
     593           0 :             << "\"";
     594             :       } else {
     595             :         DCHECK(op.IsFloatRegister());
     596           0 :         os_ << " \"" << config->GetFloatRegisterName(op.register_code())
     597           0 :             << "\"";
     598             :       }
     599           0 :     } else if (range->spilled()) {
     600           0 :       const TopLevelLiveRange* top = range->TopLevel();
     601             :       int index = -1;
     602           0 :       if (top->HasSpillRange()) {
     603             :         index = kMaxInt;  // This hasn't been set yet.
     604           0 :       } else if (top->GetSpillOperand()->IsConstant()) {
     605           0 :         os_ << " \"const(nostack):"
     606           0 :             << ConstantOperand::cast(top->GetSpillOperand())->virtual_register()
     607           0 :             << "\"";
     608             :       } else {
     609             :         index = AllocatedOperand::cast(top->GetSpillOperand())->index();
     610           0 :         if (IsFloatingPoint(top->representation())) {
     611           0 :           os_ << " \"fp_stack:" << index << "\"";
     612             :         } else {
     613           0 :           os_ << " \"stack:" << index << "\"";
     614             :         }
     615             :       }
     616             :     }
     617             : 
     618           0 :     os_ << " " << vreg;
     619           0 :     for (const UseInterval* interval = range->first_interval();
     620             :          interval != nullptr; interval = interval->next()) {
     621           0 :       os_ << " [" << interval->start().value() << ", "
     622           0 :           << interval->end().value() << "[";
     623             :     }
     624             : 
     625           0 :     UsePosition* current_pos = range->first_pos();
     626           0 :     while (current_pos != nullptr) {
     627           0 :       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
     628           0 :         os_ << " " << current_pos->pos().value() << " M";
     629             :       }
     630             :       current_pos = current_pos->next();
     631             :     }
     632             : 
     633           0 :     os_ << " \"\"\n";
     634             :   }
     635           0 : }
     636             : 
     637             : 
     638           0 : std::ostream& operator<<(std::ostream& os, const AsC1VCompilation& ac) {
     639           0 :   AccountingAllocator allocator;
     640           0 :   Zone tmp_zone(&allocator, ZONE_NAME);
     641           0 :   GraphC1Visualizer(os, &tmp_zone).PrintCompilation(ac.info_);
     642           0 :   return os;
     643             : }
     644             : 
     645             : 
     646           0 : std::ostream& operator<<(std::ostream& os, const AsC1V& ac) {
     647           0 :   AccountingAllocator allocator;
     648           0 :   Zone tmp_zone(&allocator, ZONE_NAME);
     649             :   GraphC1Visualizer(os, &tmp_zone)
     650           0 :       .PrintSchedule(ac.phase_, ac.schedule_, ac.positions_, ac.instructions_);
     651           0 :   return os;
     652             : }
     653             : 
     654             : 
     655           0 : std::ostream& operator<<(std::ostream& os,
     656             :                          const AsC1VRegisterAllocationData& ac) {
     657           0 :   AccountingAllocator allocator;
     658           0 :   Zone tmp_zone(&allocator, ZONE_NAME);
     659           0 :   GraphC1Visualizer(os, &tmp_zone).PrintLiveRanges(ac.phase_, ac.data_);
     660           0 :   return os;
     661             : }
     662             : 
     663             : const int kUnvisited = 0;
     664             : const int kOnStack = 1;
     665             : const int kVisited = 2;
     666             : 
     667           0 : std::ostream& operator<<(std::ostream& os, const AsRPO& ar) {
     668           0 :   AccountingAllocator allocator;
     669           0 :   Zone local_zone(&allocator, ZONE_NAME);
     670             : 
     671             :   // Do a post-order depth-first search on the RPO graph. For every node,
     672             :   // print:
     673             :   //
     674             :   //   - the node id
     675             :   //   - the operator mnemonic
     676             :   //   - in square brackets its parameter (if present)
     677             :   //   - in parentheses the list of argument ids and their mnemonics
     678             :   //   - the node type (if it is typed)
     679             : 
     680             :   // Post-order guarantees that all inputs of a node will be printed before
     681             :   // the node itself, if there are no cycles. Any cycles are broken
     682             :   // arbitrarily.
     683             : 
     684           0 :   ZoneVector<byte> state(ar.graph.NodeCount(), kUnvisited, &local_zone);
     685           0 :   ZoneStack<Node*> stack(&local_zone);
     686             : 
     687           0 :   stack.push(ar.graph.end());
     688           0 :   state[ar.graph.end()->id()] = kOnStack;
     689           0 :   while (!stack.empty()) {
     690           0 :     Node* n = stack.top();
     691             :     bool pop = true;
     692           0 :     for (Node* const i : n->inputs()) {
     693           0 :       if (state[i->id()] == kUnvisited) {
     694           0 :         state[i->id()] = kOnStack;
     695             :         stack.push(i);
     696             :         pop = false;
     697           0 :         break;
     698             :       }
     699             :     }
     700           0 :     if (pop) {
     701           0 :       state[n->id()] = kVisited;
     702             :       stack.pop();
     703           0 :       os << "#" << n->id() << ":" << *n->op() << "(";
     704             :       // Print the inputs.
     705             :       int j = 0;
     706           0 :       for (Node* const i : n->inputs()) {
     707           0 :         if (j++ > 0) os << ", ";
     708           0 :         os << "#" << SafeId(i) << ":" << SafeMnemonic(i);
     709             :       }
     710           0 :       os << ")";
     711             :       // Print the node type, if any.
     712           0 :       if (NodeProperties::IsTyped(n)) {
     713           0 :         os << "  [Type: ";
     714           0 :         NodeProperties::GetType(n)->PrintTo(os);
     715           0 :         os << "]";
     716             :       }
     717             :       os << std::endl;
     718             :     }
     719             :   }
     720           0 :   return os;
     721             : }
     722             : }  // namespace compiler
     723             : }  // namespace internal
     724             : }  // namespace v8

Generated by: LCOV version 1.10