| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/graph-visualizer.h" | 5 #include "src/compiler/graph-visualizer.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 buffer[full_filename.length()] = '\0'; | 74 buffer[full_filename.length()] = '\0'; |
| 75 return std::unique_ptr<char[]>(buffer); | 75 return std::unique_ptr<char[]>(buffer); |
| 76 } | 76 } |
| 77 | 77 |
| 78 | 78 |
| 79 static int SafeId(Node* node) { return node == nullptr ? -1 : node->id(); } | 79 static int SafeId(Node* node) { return node == nullptr ? -1 : node->id(); } |
| 80 static const char* SafeMnemonic(Node* node) { | 80 static const char* SafeMnemonic(Node* node) { |
| 81 return node == nullptr ? "null" : node->op()->mnemonic(); | 81 return node == nullptr ? "null" : node->op()->mnemonic(); |
| 82 } | 82 } |
| 83 | 83 |
| 84 #define DEAD_COLOR "#999999" | 84 class JSONEscaped { |
| 85 public: |
| 86 explicit JSONEscaped(const std::ostringstream& os) : str_(os.str()) {} |
| 85 | 87 |
| 86 class Escaped { | 88 friend std::ostream& operator<<(std::ostream& os, const JSONEscaped& e) { |
| 87 public: | 89 for (char c : e.str_) PipeCharacter(os, c); |
| 88 explicit Escaped(const std::ostringstream& os, | |
| 89 const char* escaped_chars = "<>|{}\\") | |
| 90 : str_(os.str()), escaped_chars_(escaped_chars) {} | |
| 91 | |
| 92 friend std::ostream& operator<<(std::ostream& os, const Escaped& e) { | |
| 93 for (std::string::const_iterator i = e.str_.begin(); i != e.str_.end(); | |
| 94 ++i) { | |
| 95 if (e.needs_escape(*i)) os << "\\"; | |
| 96 os << *i; | |
| 97 } | |
| 98 return os; | 90 return os; |
| 99 } | 91 } |
| 100 | 92 |
| 101 private: | 93 private: |
| 102 bool needs_escape(char ch) const { | 94 static std::ostream& PipeCharacter(std::ostream& os, char c) { |
| 103 for (size_t i = 0; i < strlen(escaped_chars_); ++i) { | 95 if (c == '"') return os << "\\\""; |
| 104 if (ch == escaped_chars_[i]) return true; | 96 if (c == '\\') return os << "\\\\"; |
| 105 } | 97 if (c == '\b') return os << "\\b"; |
| 106 return false; | 98 if (c == '\f') return os << "\\f"; |
| 99 if (c == '\n') return os << "\\n"; |
| 100 if (c == '\r') return os << "\\r"; |
| 101 if (c == '\t') return os << "\\t"; |
| 102 return os << c; |
| 107 } | 103 } |
| 108 | 104 |
| 109 const std::string str_; | 105 const std::string str_; |
| 110 const char* const escaped_chars_; | |
| 111 }; | 106 }; |
| 112 | 107 |
| 113 class JSONGraphNodeWriter { | 108 class JSONGraphNodeWriter { |
| 114 public: | 109 public: |
| 115 JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph, | 110 JSONGraphNodeWriter(std::ostream& os, Zone* zone, const Graph* graph, |
| 116 const SourcePositionTable* positions) | 111 const SourcePositionTable* positions) |
| 117 : os_(os), | 112 : os_(os), |
| 118 all_(zone, graph, false), | 113 all_(zone, graph, false), |
| 119 live_(zone, graph, true), | 114 live_(zone, graph, true), |
| 120 positions_(positions), | 115 positions_(positions), |
| 121 first_node_(true) {} | 116 first_node_(true) {} |
| 122 | 117 |
| 123 void Print() { | 118 void Print() { |
| 124 for (Node* const node : all_.reachable) PrintNode(node); | 119 for (Node* const node : all_.reachable) PrintNode(node); |
| 125 os_ << "\n"; | 120 os_ << "\n"; |
| 126 } | 121 } |
| 127 | 122 |
| 128 void PrintNode(Node* node) { | 123 void PrintNode(Node* node) { |
| 129 if (first_node_) { | 124 if (first_node_) { |
| 130 first_node_ = false; | 125 first_node_ = false; |
| 131 } else { | 126 } else { |
| 132 os_ << ",\n"; | 127 os_ << ",\n"; |
| 133 } | 128 } |
| 134 std::ostringstream label, title, properties; | 129 std::ostringstream label, title, properties; |
| 135 node->op()->PrintTo(label, Operator::PrintVerbosity::kSilent); | 130 node->op()->PrintTo(label, Operator::PrintVerbosity::kSilent); |
| 136 node->op()->PrintTo(title, Operator::PrintVerbosity::kVerbose); | 131 node->op()->PrintTo(title, Operator::PrintVerbosity::kVerbose); |
| 137 node->op()->PrintPropsTo(properties); | 132 node->op()->PrintPropsTo(properties); |
| 138 os_ << "{\"id\":" << SafeId(node) << ",\"label\":\"" | 133 os_ << "{\"id\":" << SafeId(node) << ",\"label\":\"" << JSONEscaped(label) |
| 139 << Escaped(label, "\"\\") << "\"" | 134 << "\"" |
| 140 << ",\"title\":\"" << Escaped(title, "\"\\") << "\"" | 135 << ",\"title\":\"" << JSONEscaped(title) << "\"" |
| 141 << ",\"live\": " << (live_.IsLive(node) ? "true" : "false") | 136 << ",\"live\": " << (live_.IsLive(node) ? "true" : "false") |
| 142 << ",\"properties\":\"" << Escaped(properties, "\"\\") << "\""; | 137 << ",\"properties\":\"" << JSONEscaped(properties) << "\""; |
| 143 IrOpcode::Value opcode = node->opcode(); | 138 IrOpcode::Value opcode = node->opcode(); |
| 144 if (IrOpcode::IsPhiOpcode(opcode)) { | 139 if (IrOpcode::IsPhiOpcode(opcode)) { |
| 145 os_ << ",\"rankInputs\":[0," << NodeProperties::FirstControlIndex(node) | 140 os_ << ",\"rankInputs\":[0," << NodeProperties::FirstControlIndex(node) |
| 146 << "]"; | 141 << "]"; |
| 147 os_ << ",\"rankWithInput\":[" << NodeProperties::FirstControlIndex(node) | 142 os_ << ",\"rankWithInput\":[" << NodeProperties::FirstControlIndex(node) |
| 148 << "]"; | 143 << "]"; |
| 149 } else if (opcode == IrOpcode::kIfTrue || opcode == IrOpcode::kIfFalse || | 144 } else if (opcode == IrOpcode::kIfTrue || opcode == IrOpcode::kIfFalse || |
| 150 opcode == IrOpcode::kLoop) { | 145 opcode == IrOpcode::kLoop) { |
| 151 os_ << ",\"rankInputs\":[" << NodeProperties::FirstControlIndex(node) | 146 os_ << ",\"rankInputs\":[" << NodeProperties::FirstControlIndex(node) |
| 152 << "]"; | 147 << "]"; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 164 os_ << ",\"opinfo\":\"" << node->op()->ValueInputCount() << " v " | 159 os_ << ",\"opinfo\":\"" << node->op()->ValueInputCount() << " v " |
| 165 << node->op()->EffectInputCount() << " eff " | 160 << node->op()->EffectInputCount() << " eff " |
| 166 << node->op()->ControlInputCount() << " ctrl in, " | 161 << node->op()->ControlInputCount() << " ctrl in, " |
| 167 << node->op()->ValueOutputCount() << " v " | 162 << node->op()->ValueOutputCount() << " v " |
| 168 << node->op()->EffectOutputCount() << " eff " | 163 << node->op()->EffectOutputCount() << " eff " |
| 169 << node->op()->ControlOutputCount() << " ctrl out\""; | 164 << node->op()->ControlOutputCount() << " ctrl out\""; |
| 170 if (NodeProperties::IsTyped(node)) { | 165 if (NodeProperties::IsTyped(node)) { |
| 171 Type* type = NodeProperties::GetType(node); | 166 Type* type = NodeProperties::GetType(node); |
| 172 std::ostringstream type_out; | 167 std::ostringstream type_out; |
| 173 type->PrintTo(type_out); | 168 type->PrintTo(type_out); |
| 174 os_ << ",\"type\":\"" << Escaped(type_out, "\"\\") << "\""; | 169 os_ << ",\"type\":\"" << JSONEscaped(type_out) << "\""; |
| 175 } | 170 } |
| 176 os_ << "}"; | 171 os_ << "}"; |
| 177 } | 172 } |
| 178 | 173 |
| 179 private: | 174 private: |
| 180 std::ostream& os_; | 175 std::ostream& os_; |
| 181 AllNodes all_; | 176 AllNodes all_; |
| 182 AllNodes live_; | 177 AllNodes live_; |
| 183 const SourcePositionTable* positions_; | 178 const SourcePositionTable* positions_; |
| 184 bool first_node_; | 179 bool first_node_; |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 os << "]"; | 703 os << "]"; |
| 709 } | 704 } |
| 710 os << std::endl; | 705 os << std::endl; |
| 711 } | 706 } |
| 712 } | 707 } |
| 713 return os; | 708 return os; |
| 714 } | 709 } |
| 715 } // namespace compiler | 710 } // namespace compiler |
| 716 } // namespace internal | 711 } // namespace internal |
| 717 } // namespace v8 | 712 } // namespace v8 |
| OLD | NEW |