LCOV - code coverage report
Current view: top level - src/compiler - graph-visualizer.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 83 402 20.6 %
Date: 2017-10-20 Functions: 9 36 25.0 %

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

Generated by: LCOV version 1.10