/* * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
CompilerThread *compiler_thread = (CompilerThread *)thread; if (compiler_thread->ideal_graph_printer() == NULL) {
IdealGraphPrinter *printer = new IdealGraphPrinter();
compiler_thread->set_ideal_graph_printer(printer);
}
return compiler_thread->ideal_graph_printer();
}
void IdealGraphPrinter::clean_up() { for (JavaThreadIteratorWithHandle jtiwh; JavaThread* p = jtiwh.next(); ) { if (p->is_Compiler_thread()) {
CompilerThread* c = (CompilerThread*)p;
IdealGraphPrinter* printer = c->ideal_graph_printer(); if (printer) { delete printer;
}
c->set_ideal_graph_printer(NULL);
}
}
IdealGraphPrinter* debug_file_printer = Compile::debug_file_printer(); if (debug_file_printer != NULL) { delete debug_file_printer;
}
IdealGraphPrinter* debug_network_printer = Compile::debug_network_printer(); if (debug_network_printer != NULL) { delete debug_network_printer;
}
}
// Either print methods to file specified with PrintIdealGraphFile or otherwise over the network to the IGV
IdealGraphPrinter::IdealGraphPrinter() {
init(PrintIdealGraphFile, true, false);
}
// Either print methods to the specified file 'file_name' or if NULL over the network to the IGV. If 'append' // is set, the next phase is directly appended to the specified file 'file_name'. This is useful when doing // replay compilation with a tool like rr that cannot alter the current program state but only the file.
IdealGraphPrinter::IdealGraphPrinter(Compile* compile, constchar* file_name, bool append) {
assert(!append || (append && file_name != NULL), "can only use append flag when printing to file");
init(file_name, false, append);
C = compile; if (append) { // When directly appending the next graph, we only need to set _current_method and not set up a new method
_current_method = C->method();
} else {
begin_method();
}
}
void IdealGraphPrinter::init(constchar* file_name, bool use_multiple_files, bool append) { // By default dump both ins and outs since dead or unreachable code // needs to appear in the graph. There are also some special cases // in the mach where kill projections have no users but should // appear in the dump.
_traverse_outs = true;
_should_send_method = true;
_output = NULL;
buffer[0] = 0;
_depth = 0;
_current_method = NULL;
_network_stream = NULL;
if (file_name != NULL) {
init_file_stream(file_name, use_multiple_files, append);
} else {
init_network_stream();
}
_xml = new (mtCompiler) xmlStream(_output); if (!append) {
head(TOP_ELEMENT);
}
}
// Destructor, close file or network stream
IdealGraphPrinter::~IdealGraphPrinter() {
tail(TOP_ELEMENT);
// Print inline tree if (_should_send_method) {
InlineTree *inlineTree = C->ilt(); if (inlineTree != NULL) {
print_inline_tree(inlineTree);
} else { // print this method only
}
}
}
// Has to be called whenever a method is compiled void IdealGraphPrinter::begin_method() {
ciMethod *method = C->method();
assert(_output, "output stream must exist!");
assert(method, "null methods are not allowed!");
assert(!_current_method, "current method must be null!");
// Has to be called whenever a method has finished compilation void IdealGraphPrinter::end_method() {
tail(GROUP_ELEMENT);
_current_method = NULL;
_xml->flush();
}
if (field != NULL) { // Either direct field access or array access
field->print_name_on(&ss); for (uint i = 0; i < depth; i++) { // For arrays: Add [] for each dimension
ss.print("[]");
} if (node->is_Store()) {
print_prop("destination", buffer);
} else {
print_prop("source", buffer);
}
}
}
ciField* IdealGraphPrinter::get_field(const Node* node) { const TypePtr* adr_type = node->adr_type();
Compile::AliasType* atp = NULL; if (C->have_alias_type(adr_type)) {
atp = C->alias_type(adr_type);
} if (atp != NULL) {
ciField* field = atp->field(); if (field != NULL) { // Found field associated with 'node'. return field;
}
} return NULL;
}
// Try to find the field that is associated with a memory node belonging to an array access.
ciField* IdealGraphPrinter::find_source_field_of_array_access(const Node* node, uint& depth) { if (!node->is_Mem()) { // Not an array access return NULL;
}
do { if (node->adr_type() != NULL && node->adr_type()->isa_aryptr()) { // Only process array accesses. Pattern match to find actual field source access.
node = get_load_node(node); if (node != NULL) {
ciField* field = get_field(node); if (field != NULL) { return field;
} // Could be a multi-dimensional array. Repeat loop.
depth++; continue;
}
} // Not an array access with a field source. break;
} while (depth < 256); // Cannot have more than 255 dimensions
return NULL;
}
// Pattern match on the inputs of 'node' to find load node for the field access.
Node* IdealGraphPrinter::get_load_node(const Node* node) {
Node* load = NULL;
Node* addr = node->as_Mem()->in(MemNode::Address); if (addr != NULL && addr->is_AddP()) {
Node* base = addr->as_AddP()->base_node(); if (base != NULL) {
base = base->uncast(); if (base->is_Load()) { // Mem(AddP([ConstraintCast*](LoadP))) for non-compressed oops.
load = base;
} elseif (base->is_DecodeN() && base->in(1)->is_Load()) { // Mem(AddP([ConstraintCast*](DecodeN(LoadN)))) for compressed oops.
load = base->in(1);
}
}
} return load;
}
void IdealGraphPrinter::walk_nodes(Node* start, bool edges, VectorSet* temp_set) {
VectorSet visited;
GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, nullptr);
nodeStack.push(start); if (C->cfg() != nullptr) { // once we have a CFG there are some nodes that aren't really // reachable but are in the CFG so add them here. for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) {
Block* block = C->cfg()->get_block(i); for (uint s = 0; s < block->number_of_nodes(); s++) {
nodeStack.push(block->get_node(s));
}
}
}
while (nodeStack.length() > 0) {
Node* n = nodeStack.pop(); if (visited.test_set(n->_idx)) { continue;
}
visit_node(n, edges, temp_set);
if (_traverse_outs) { for (DUIterator i = n->outs(); n->has_out(i); i++) {
nodeStack.push(n->out(i));
}
}
for (uint i = 0; i < n->len(); i++) { if (n->in(i) != nullptr) {
nodeStack.push(n->in(i));
}
}
}
}
void IdealGraphPrinter::print_method(constchar *name, int level) { if (C->should_print_igv(level)) {
print(name, (Node *) C->root());
}
}
head(NODES_ELEMENT); if (C->cfg() != NULL) { // Compute the maximum estimated frequency in the current graph.
_max_freq = 1.0e-6; for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) {
Block* block = C->cfg()->get_block(i); if (block->_freq > _max_freq) {
_max_freq = block->_freq;
}
}
}
walk_nodes(node, false, &temp_set);
tail(NODES_ELEMENT);
head(EDGES_ELEMENT);
walk_nodes(node, true, &temp_set);
tail(EDGES_ELEMENT); if (C->cfg() != NULL) {
head(CONTROL_FLOW_ELEMENT); for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) {
Block* block = C->cfg()->get_block(i);
begin_head(BLOCK_ELEMENT);
print_attr(BLOCK_NAME_PROPERTY, block->_pre_order);
end_head();
head(SUCCESSORS_ELEMENT); for (uint s = 0; s < block->_num_succs; s++) {
begin_elem(SUCCESSOR_ELEMENT);
print_attr(BLOCK_NAME_PROPERTY, block->_succs[s]->_pre_order);
end_elem();
}
tail(SUCCESSORS_ELEMENT);
head(NODES_ELEMENT); for (uint s = 0; s < block->number_of_nodes(); s++) {
begin_elem(NODE_ELEMENT);
print_attr(NODE_ID_PROPERTY, block->get_node(s)->_igv_idx);
end_elem();
}
tail(NODES_ELEMENT);
void IdealGraphPrinter::init_file_stream(constchar* file_name, bool use_multiple_files, bool append) {
ThreadCritical tc; if (use_multiple_files && _file_count != 0) {
assert(!append, "append should only be used for debugging with a single file");
ResourceMark rm;
stringStream st; constchar* dot = strrchr(file_name, '.'); if (dot) {
st.write(file_name, dot - file_name);
st.print("%d%s", _file_count, dot);
} else {
st.print("%s%d", file_name, _file_count);
}
_output = new (mtCompiler) fileStream(st.as_string(), "w");
} else {
_output = new (mtCompiler) fileStream(file_name, append ? "a" : "w");
} if (use_multiple_files) {
assert(!append, "append should only be used for debugging with a single file");
_file_count++;
}
}
void IdealGraphPrinter::init_network_stream() {
_network_stream = new (mtCompiler) networkStream(); // Try to connect to visualizer if (_network_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) { char c = 0;
_network_stream->read(&c, 1); if (c != 'y') {
tty->print_cr("Client available, but does not want to receive data!");
_network_stream->close(); delete _network_stream;
_network_stream = NULL; return;
}
_output = _network_stream;
} else { // It would be nice if we could shut down cleanly but it should // be an error if we can't connect to the visualizer.
fatal("Couldn't connect to visualizer at %s:" INTX_FORMAT,
PrintIdealGraphAddress, PrintIdealGraphPort);
}
}
void IdealGraphPrinter::update_compiled_method(ciMethod* current_method) {
assert(C != NULL, "must already be set"); if (current_method != _current_method) { // If a different method, end the old and begin with the new one.
end_method();
_current_method = NULL;
begin_method();
}
}
externconstchar *NodeClassNames[];
#endif
Messung V0.5
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.