duke@435: /* duke@435: * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: #include "incls/_precompiled.incl" duke@435: #include "incls/_idealGraphPrinter.cpp.incl" duke@435: duke@435: #ifndef PRODUCT duke@435: duke@435: // Constants duke@435: // Keep consistent with Java constants duke@435: const char *IdealGraphPrinter::INDENT = " "; duke@435: const char *IdealGraphPrinter::TOP_ELEMENT = "graphDocument"; duke@435: const char *IdealGraphPrinter::GROUP_ELEMENT = "group"; duke@435: const char *IdealGraphPrinter::GRAPH_ELEMENT = "graph"; duke@435: const char *IdealGraphPrinter::PROPERTIES_ELEMENT = "properties"; duke@435: const char *IdealGraphPrinter::EDGES_ELEMENT = "edges"; duke@435: const char *IdealGraphPrinter::PROPERTY_ELEMENT = "p"; duke@435: const char *IdealGraphPrinter::EDGE_ELEMENT = "edge"; duke@435: const char *IdealGraphPrinter::NODE_ELEMENT = "node"; duke@435: const char *IdealGraphPrinter::NODES_ELEMENT = "nodes"; duke@435: const char *IdealGraphPrinter::REMOVE_EDGE_ELEMENT = "removeEdge"; duke@435: const char *IdealGraphPrinter::REMOVE_NODE_ELEMENT = "removeNode"; duke@435: const char *IdealGraphPrinter::METHOD_NAME_PROPERTY = "name"; duke@435: const char *IdealGraphPrinter::METHOD_IS_PUBLIC_PROPERTY = "public"; duke@435: const char *IdealGraphPrinter::METHOD_IS_STATIC_PROPERTY = "static"; duke@435: const char *IdealGraphPrinter::TRUE_VALUE = "true"; duke@435: const char *IdealGraphPrinter::NODE_NAME_PROPERTY = "name"; duke@435: const char *IdealGraphPrinter::EDGE_NAME_PROPERTY = "name"; duke@435: const char *IdealGraphPrinter::NODE_ID_PROPERTY = "id"; duke@435: const char *IdealGraphPrinter::FROM_PROPERTY = "from"; duke@435: const char *IdealGraphPrinter::TO_PROPERTY = "to"; duke@435: const char *IdealGraphPrinter::PROPERTY_NAME_PROPERTY = "name"; duke@435: const char *IdealGraphPrinter::GRAPH_NAME_PROPERTY = "name"; duke@435: const char *IdealGraphPrinter::INDEX_PROPERTY = "index"; duke@435: const char *IdealGraphPrinter::METHOD_ELEMENT = "method"; duke@435: const char *IdealGraphPrinter::INLINE_ELEMENT = "inline"; duke@435: const char *IdealGraphPrinter::BYTECODES_ELEMENT = "bytecodes"; duke@435: const char *IdealGraphPrinter::METHOD_BCI_PROPERTY = "bci"; duke@435: const char *IdealGraphPrinter::METHOD_SHORT_NAME_PROPERTY = "shortName"; duke@435: const char *IdealGraphPrinter::CONTROL_FLOW_ELEMENT = "controlFlow"; duke@435: const char *IdealGraphPrinter::BLOCK_NAME_PROPERTY = "name"; duke@435: const char *IdealGraphPrinter::BLOCK_DOMINATOR_PROPERTY = "dom"; duke@435: const char *IdealGraphPrinter::BLOCK_ELEMENT = "block"; duke@435: const char *IdealGraphPrinter::SUCCESSORS_ELEMENT = "successors"; duke@435: const char *IdealGraphPrinter::SUCCESSOR_ELEMENT = "successor"; duke@435: const char *IdealGraphPrinter::ASSEMBLY_ELEMENT = "assembly"; duke@435: duke@435: int IdealGraphPrinter::_file_count = 0; duke@435: duke@435: IdealGraphPrinter *IdealGraphPrinter::printer() { duke@435: if (PrintIdealGraphLevel == 0) return NULL; duke@435: duke@435: JavaThread *thread = JavaThread::current(); duke@435: if (!thread->is_Compiler_thread()) return NULL; duke@435: duke@435: CompilerThread *compiler_thread = (CompilerThread *)thread; duke@435: if (compiler_thread->ideal_graph_printer() == NULL) { duke@435: IdealGraphPrinter *printer = new IdealGraphPrinter(); duke@435: compiler_thread->set_ideal_graph_printer(printer); duke@435: } duke@435: duke@435: return compiler_thread->ideal_graph_printer(); duke@435: } duke@435: duke@435: void IdealGraphPrinter::clean_up() { duke@435: JavaThread *p; duke@435: for (p = Threads::first(); p; p = p->next()) { duke@435: if (p->is_Compiler_thread()) { duke@435: CompilerThread *c = (CompilerThread *)p; duke@435: IdealGraphPrinter *printer = c->ideal_graph_printer(); duke@435: if (printer) { duke@435: delete printer; duke@435: } duke@435: c->set_ideal_graph_printer(NULL); duke@435: } duke@435: } duke@435: } duke@435: duke@435: // Constructor, either file or network output duke@435: IdealGraphPrinter::IdealGraphPrinter() { duke@435: duke@435: _traverse_outs = false; duke@435: _should_send_method = true; duke@435: _output = NULL; duke@435: buffer[0] = 0; duke@435: _depth = 0; duke@435: _current_method = NULL; duke@435: assert(!_current_method, "current method must be initialized to NULL"); duke@435: _arena = new Arena(); duke@435: duke@435: _stream = new (ResourceObj::C_HEAP) networkStream(); duke@435: duke@435: if (PrintIdealGraphFile != NULL) { duke@435: ThreadCritical tc; duke@435: // User wants all output to go to files duke@435: if (_file_count != 0) { duke@435: ResourceMark rm; duke@435: stringStream st; duke@435: const char* dot = strrchr(PrintIdealGraphFile, '.'); duke@435: if (dot) { duke@435: st.write(PrintIdealGraphFile, dot - PrintIdealGraphFile); duke@435: st.print("%d%s", _file_count, dot); duke@435: } else { duke@435: st.print("%s%d", PrintIdealGraphFile, _file_count); duke@435: } duke@435: _output = new (ResourceObj::C_HEAP) fileStream(st.as_string()); duke@435: } else { duke@435: _output = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile); duke@435: } duke@435: _file_count++; duke@435: } else { duke@435: // Try to connect to visualizer duke@435: if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) { duke@435: char c = 0; duke@435: _stream->read(&c, 1); duke@435: if (c != 'y') { duke@435: tty->print_cr("Client available, but does not want to receive data!"); duke@435: _stream->close(); duke@435: delete _stream; duke@435: _stream = NULL; duke@435: return; duke@435: } duke@435: _output = _stream; duke@435: } else { duke@435: // It would be nice if we could shut down cleanly but it should duke@435: // be an error if we can't connect to the visualizer. duke@435: fatal2("Couldn't connect to visualizer at %s:%d", PrintIdealGraphAddress, PrintIdealGraphPort); duke@435: } duke@435: } duke@435: duke@435: start_element(TOP_ELEMENT); duke@435: } duke@435: duke@435: // Destructor, close file or network stream duke@435: IdealGraphPrinter::~IdealGraphPrinter() { duke@435: duke@435: end_element(TOP_ELEMENT); duke@435: duke@435: if (_stream) { duke@435: delete _stream; duke@435: if (_stream == _output) { duke@435: _output = NULL; duke@435: } duke@435: _stream = NULL; duke@435: } duke@435: duke@435: if (_output) { duke@435: delete _output; duke@435: _output = NULL; duke@435: } duke@435: } duke@435: duke@435: void IdealGraphPrinter::print_ifg(PhaseIFG* ifg) { duke@435: duke@435: // Code to print an interference graph to tty, currently not used duke@435: duke@435: /* duke@435: if (!_current_method) return; duke@435: // Remove neighbor colors duke@435: duke@435: for (uint i = 0; i < ifg._maxlrg; i++) { duke@435: duke@435: IndexSet *s = ifg.neighbors(i); duke@435: IndexSetIterator elements(s); duke@435: uint neighbor; duke@435: while ((neighbor = elements.next()) != 0) { duke@435: tty->print_cr("Edge between %d and %d\n", i, neighbor); duke@435: } duke@435: } duke@435: duke@435: duke@435: for (uint i = 0; i < ifg._maxlrg; i++) { duke@435: LRG &l = ifg.lrgs(i); duke@435: if (l._def) { duke@435: OptoReg::Name name = l.reg(); duke@435: tty->print("OptoReg::dump: "); duke@435: OptoReg::dump(name); duke@435: tty->print_cr(""); duke@435: tty->print_cr("name=%d\n", name); duke@435: if (name) { duke@435: if (OptoReg::is_stack(name)) { duke@435: tty->print_cr("Stack number %d\n", OptoReg::reg2stack(name)); duke@435: duke@435: } else if (!OptoReg::is_valid(name)) { duke@435: tty->print_cr("BAD!!!"); duke@435: } else { duke@435: duke@435: if (OptoReg::is_reg(name)) { duke@435: tty->print_cr(OptoReg::regname(name)); duke@435: } else { duke@435: int x = 0; duke@435: } duke@435: } duke@435: int x = 0; duke@435: } duke@435: duke@435: if (l._def == NodeSentinel) { duke@435: tty->print("multiple mapping from %d: ", i); duke@435: for (int j=0; jlength(); j++) { duke@435: tty->print("%d ", l._defs->at(j)->_idx); duke@435: } duke@435: tty->print_cr(""); duke@435: } else { duke@435: tty->print_cr("mapping between %d and %d\n", i, l._def->_idx); duke@435: } duke@435: } duke@435: }*/ duke@435: } duke@435: duke@435: void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) { duke@435: duke@435: Properties properties; duke@435: stringStream str; duke@435: method->print_name(&str); duke@435: duke@435: stringStream shortStr; duke@435: method->print_short_name(&shortStr); duke@435: duke@435: duke@435: properties.add(new Property(METHOD_NAME_PROPERTY, str.as_string())); duke@435: properties.add(new Property(METHOD_SHORT_NAME_PROPERTY, shortStr.as_string())); duke@435: properties.add(new Property(METHOD_BCI_PROPERTY, bci)); duke@435: start_element(METHOD_ELEMENT, &properties); duke@435: duke@435: start_element(BYTECODES_ELEMENT); duke@435: output()->print_cr("print_codes_on(output()); duke@435: output()->print_cr("]]>"); duke@435: end_element(BYTECODES_ELEMENT); duke@435: duke@435: start_element(INLINE_ELEMENT); duke@435: if (tree != NULL) { duke@435: GrowableArray subtrees = tree->subtrees(); duke@435: for (int i = 0; i < subtrees.length(); i++) { duke@435: print_inline_tree(subtrees.at(i)); duke@435: } duke@435: } duke@435: end_element(INLINE_ELEMENT); duke@435: duke@435: end_element(METHOD_ELEMENT); duke@435: output()->flush(); duke@435: } duke@435: duke@435: void IdealGraphPrinter::print_inline_tree(InlineTree *tree) { duke@435: duke@435: if (tree == NULL) return; duke@435: duke@435: ciMethod *method = tree->method(); duke@435: print_method(tree->method(), tree->caller_bci(), tree); duke@435: duke@435: } duke@435: duke@435: void IdealGraphPrinter::clear_nodes() { duke@435: // for (int i = 0; i < _nodes.length(); i++) { duke@435: // _nodes.at(i)->clear_node(); duke@435: // } duke@435: } duke@435: duke@435: void IdealGraphPrinter::print_inlining(Compile* compile) { duke@435: duke@435: // Print inline tree duke@435: if (_should_send_method) { duke@435: InlineTree *inlineTree = compile->ilt(); duke@435: if (inlineTree != NULL) { duke@435: print_inline_tree(inlineTree); duke@435: } else { duke@435: // print this method only duke@435: } duke@435: } duke@435: } duke@435: duke@435: // Has to be called whenever a method is compiled duke@435: void IdealGraphPrinter::begin_method(Compile* compile) { duke@435: duke@435: ciMethod *method = compile->method(); duke@435: assert(_output, "output stream must exist!"); duke@435: assert(method, "null methods are not allowed!"); duke@435: assert(!_current_method, "current method must be null!"); duke@435: duke@435: _arena->destruct_contents(); duke@435: duke@435: start_element(GROUP_ELEMENT); duke@435: duke@435: // Print properties duke@435: Properties properties; duke@435: duke@435: // Add method name duke@435: stringStream strStream; duke@435: method->print_name(&strStream); duke@435: properties.add(new Property(METHOD_NAME_PROPERTY, strStream.as_string())); duke@435: duke@435: if (method->flags().is_public()) { duke@435: properties.add(new Property(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE)); duke@435: } duke@435: duke@435: if (method->flags().is_static()) { duke@435: properties.add(new Property(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE)); duke@435: } duke@435: duke@435: properties.print(this); duke@435: duke@435: if (_stream) { duke@435: char answer = 0; duke@435: _stream->flush(); duke@435: int result = _stream->read(&answer, 1); duke@435: _should_send_method = (answer == 'y'); duke@435: } duke@435: duke@435: this->_nodes = GrowableArray(_arena, 2, 0, NULL); duke@435: this->_edges = GrowableArray< EdgeDescription * >(_arena, 2, 0, NULL); duke@435: duke@435: duke@435: this->_current_method = method; duke@435: duke@435: duke@435: duke@435: _output->flush(); duke@435: } duke@435: duke@435: // Has to be called whenever a method has finished compilation duke@435: void IdealGraphPrinter::end_method() { duke@435: duke@435: // if (finish && !in_method) return; duke@435: duke@435: nmethod* method = (nmethod*)this->_current_method->code(); duke@435: duke@435: start_element(ASSEMBLY_ELEMENT); duke@435: // Disassembler::decode(method, _output); duke@435: end_element(ASSEMBLY_ELEMENT); duke@435: duke@435: duke@435: end_element(GROUP_ELEMENT); duke@435: _current_method = NULL; duke@435: _output->flush(); duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc) { duke@435: delete desc; duke@435: _nodes.at_put(i, NULL); duke@435: } duke@435: } duke@435: this->_nodes.clear(); duke@435: duke@435: duke@435: for (int i = 0; i < _edges.length(); i++) { duke@435: // for (int j=0; j<_edges.at(i)->length(); j++) { duke@435: EdgeDescription *conn = _edges.at(i); duke@435: conn->print(this); duke@435: if (conn) { duke@435: delete conn; duke@435: _edges.at_put(i, NULL); duke@435: } duke@435: //} duke@435: //_edges.at(i)->clear(); duke@435: //delete _edges.at(i); duke@435: //_edges.at_put(i, NULL); duke@435: } duke@435: this->_edges.clear(); duke@435: duke@435: // in_method = false; duke@435: } duke@435: duke@435: // Outputs an XML start element duke@435: void IdealGraphPrinter::start_element(const char *s, Properties *properties /* = NULL */, bool print_indent /* = false */, bool print_return /* = true */) { duke@435: duke@435: start_element_helper(s, properties, false, print_indent, print_return); duke@435: _depth++; duke@435: duke@435: } duke@435: duke@435: // Outputs an XML start element without body duke@435: void IdealGraphPrinter::simple_element(const char *s, Properties *properties /* = NULL */, bool print_indent /* = false */) { duke@435: start_element_helper(s, properties, true, print_indent, true); duke@435: } duke@435: duke@435: // Outputs an XML start element. If outputEnd is true, the element has no body. duke@435: void IdealGraphPrinter::start_element_helper(const char *s, Properties *properties, bool outputEnd, bool print_indent /* = false */, bool print_return /* = true */) { duke@435: duke@435: assert(_output, "output stream must exist!"); duke@435: duke@435: if (print_indent) this->print_indent(); duke@435: _output->print("<"); duke@435: _output->print(s); duke@435: if (properties) properties->print_as_attributes(this); duke@435: duke@435: if (outputEnd) { duke@435: _output->print("/"); duke@435: } duke@435: duke@435: _output->print(">"); duke@435: if (print_return) _output->print_cr(""); duke@435: duke@435: } duke@435: duke@435: // Print indent duke@435: void IdealGraphPrinter::print_indent() { duke@435: for (int i = 0; i < _depth; i++) { duke@435: _output->print(INDENT); duke@435: } duke@435: } duke@435: duke@435: // Outputs an XML end element duke@435: void IdealGraphPrinter::end_element(const char *s, bool print_indent /* = true */, bool print_return /* = true */) { duke@435: duke@435: assert(_output, "output stream must exist!"); duke@435: duke@435: _depth--; duke@435: duke@435: if (print_indent) this->print_indent(); duke@435: _output->print("print(s); duke@435: _output->print(">"); duke@435: if (print_return) _output->print_cr(""); duke@435: duke@435: } duke@435: duke@435: bool IdealGraphPrinter::traverse_outs() { duke@435: return _traverse_outs; duke@435: } duke@435: duke@435: void IdealGraphPrinter::set_traverse_outs(bool b) { duke@435: _traverse_outs = b; duke@435: } duke@435: duke@435: void IdealGraphPrinter::walk(Node *start) { duke@435: duke@435: duke@435: VectorSet visited(Thread::current()->resource_area()); duke@435: GrowableArray nodeStack(Thread::current()->resource_area(), 0, 0, NULL); duke@435: nodeStack.push(start); duke@435: visited.test_set(start->_idx); duke@435: while(nodeStack.length() > 0) { duke@435: duke@435: Node *n = nodeStack.pop(); duke@435: IdealGraphPrinter::pre_node(n, this); duke@435: duke@435: if (_traverse_outs) { duke@435: for (DUIterator i = n->outs(); n->has_out(i); i++) { duke@435: Node* p = n->out(i); duke@435: if (!visited.test_set(p->_idx)) { duke@435: nodeStack.push(p); duke@435: } duke@435: } duke@435: } duke@435: duke@435: for ( uint i = 0; i < n->len(); i++ ) { duke@435: if ( n->in(i) ) { duke@435: if (!visited.test_set(n->in(i)->_idx)) { duke@435: nodeStack.push(n->in(i)); duke@435: } duke@435: } duke@435: } duke@435: } duke@435: } duke@435: duke@435: void IdealGraphPrinter::compress(int index, GrowableArray* blocks) { duke@435: Block *block = blocks->adr_at(index); duke@435: duke@435: int ancestor = block->ancestor(); duke@435: assert(ancestor != -1, ""); duke@435: duke@435: Block *ancestor_block = blocks->adr_at(ancestor); duke@435: if (ancestor_block->ancestor() != -1) { duke@435: compress(ancestor, blocks); duke@435: duke@435: int label = block->label(); duke@435: Block *label_block = blocks->adr_at(label); duke@435: duke@435: int ancestor_label = ancestor_block->label(); duke@435: Block *ancestor_label_block = blocks->adr_at(label); duke@435: if (ancestor_label_block->semi() < label_block->semi()) { duke@435: block->set_label(ancestor_label); duke@435: } duke@435: duke@435: block->set_ancestor(ancestor_block->ancestor()); duke@435: } duke@435: } duke@435: duke@435: int IdealGraphPrinter::eval(int index, GrowableArray* blocks) { duke@435: Block *block = blocks->adr_at(index); duke@435: if (block->ancestor() == -1) { duke@435: return index; duke@435: } else { duke@435: compress(index, blocks); duke@435: return block->label(); duke@435: } duke@435: } duke@435: duke@435: void IdealGraphPrinter::link(int index1, int index2, GrowableArray* blocks) { duke@435: Block *block2 = blocks->adr_at(index2); duke@435: block2->set_ancestor(index1); duke@435: } duke@435: duke@435: void IdealGraphPrinter::build_dominators(GrowableArray* blocks) { duke@435: duke@435: if (blocks->length() == 0) return; duke@435: duke@435: GrowableArray stack; duke@435: stack.append(0); duke@435: duke@435: GrowableArray array; duke@435: duke@435: assert(blocks->length() > 0, ""); duke@435: blocks->adr_at(0)->set_dominator(0); duke@435: duke@435: int n = 0; duke@435: while(!stack.is_empty()) { duke@435: int index = stack.pop(); duke@435: Block *block = blocks->adr_at(index); duke@435: block->set_semi(n); duke@435: array.append(block); duke@435: n = n + 1; duke@435: for (int i = 0; i < block->succs()->length(); i++) { duke@435: int succ_index = block->succs()->at(i); duke@435: Block *succ = blocks->adr_at(succ_index); duke@435: if (succ->semi() == -1) { duke@435: succ->set_parent(index); duke@435: stack.push(succ_index); duke@435: } duke@435: succ->add_pred(index); duke@435: } duke@435: } duke@435: duke@435: for (int i=n-1; i>0; i--) { duke@435: Block *block = array.at(i); duke@435: int block_index = block->index(); duke@435: for (int j=0; jpred()->length(); j++) { duke@435: int pred_index = block->pred()->at(j); duke@435: int cur_index = eval(pred_index, blocks); duke@435: duke@435: Block *cur_block = blocks->adr_at(cur_index); duke@435: if (cur_block->semi() < block->semi()) { duke@435: block->set_semi(cur_block->semi()); duke@435: } duke@435: } duke@435: duke@435: int semi_index = block->semi(); duke@435: Block *semi_block = array.at(semi_index); duke@435: semi_block->add_to_bucket(block_index); duke@435: duke@435: link(block->parent(), block_index, blocks); duke@435: Block *parent_block = blocks->adr_at(block->parent()); duke@435: duke@435: for (int j=0; jbucket()->length(); j++) { duke@435: int cur_index = parent_block->bucket()->at(j); duke@435: int new_index = eval(cur_index, blocks); duke@435: Block *cur_block = blocks->adr_at(cur_index); duke@435: Block *new_block = blocks->adr_at(new_index); duke@435: int dom = block->parent(); duke@435: duke@435: if (new_block->semi() < cur_block->semi()) { duke@435: dom = new_index; duke@435: } duke@435: duke@435: cur_block->set_dominator(dom); duke@435: } duke@435: duke@435: parent_block->clear_bucket(); duke@435: } duke@435: duke@435: for (int i=1; i < n; i++) { duke@435: duke@435: Block *block = array.at(i); duke@435: int block_index = block->index(); duke@435: duke@435: int semi_index = block->semi(); duke@435: Block *semi_block = array.at(semi_index); duke@435: duke@435: if (block->dominator() != semi_block->index()) { duke@435: int new_dom = blocks->adr_at(block->dominator())->dominator(); duke@435: block->set_dominator(new_dom); duke@435: } duke@435: } duke@435: duke@435: for (int i = 0; i < blocks->length(); i++) { duke@435: if (blocks->adr_at(i)->dominator() == -1) { duke@435: blocks->adr_at(i)->set_dominator(0); duke@435: } duke@435: } duke@435: duke@435: // Build dominates array duke@435: for (int i=1; i < blocks->length(); i++) { duke@435: Block *block = blocks->adr_at(i); duke@435: int dominator = block->dominator(); duke@435: Block *dom_block = blocks->adr_at(dominator); duke@435: dom_block->add_dominates(i); duke@435: dom_block->add_child(i); duke@435: duke@435: while(dominator != 0) { duke@435: dominator = dom_block->dominator(); duke@435: dom_block = blocks->adr_at(dominator); duke@435: dom_block->add_child(i); duke@435: } duke@435: } duke@435: } duke@435: duke@435: void IdealGraphPrinter::build_common_dominator(int **common_dominator, int index, GrowableArray* blocks) { duke@435: duke@435: common_dominator[index][index] = index; duke@435: Block *block = blocks->adr_at(index); duke@435: for (int i = 0; i < block->dominates()->length(); i++) { duke@435: Block *dominated = blocks->adr_at(block->dominates()->at(i)); duke@435: duke@435: for (int j=0; jchildren()->length(); j++) { duke@435: Block *child = blocks->adr_at(dominated->children()->at(j)); duke@435: common_dominator[index][child->index()] = common_dominator[child->index()][index] = index; duke@435: duke@435: for (int k=0; kadr_at(block->dominates()->at(k)); duke@435: common_dominator[child->index()][other_dominated->index()] = common_dominator[other_dominated->index()][child->index()] = index; duke@435: duke@435: for (int l=0 ; lchildren()->length(); l++) { duke@435: Block *other_child = blocks->adr_at(other_dominated->children()->at(l)); duke@435: common_dominator[child->index()][other_child->index()] = common_dominator[other_child->index()][child->index()] = index; duke@435: } duke@435: } duke@435: } duke@435: duke@435: build_common_dominator(common_dominator, dominated->index(), blocks); duke@435: } duke@435: } duke@435: duke@435: void IdealGraphPrinter::schedule_latest(int **common_dominator, GrowableArray* blocks) { duke@435: duke@435: int queue_size = _nodes.length() + 1; duke@435: NodeDescription **queue = NEW_RESOURCE_ARRAY(NodeDescription *, queue_size); duke@435: int queue_start = 0; duke@435: int queue_end = 0; duke@435: Arena *a = new Arena(); duke@435: VectorSet on_queue(a); duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc) { duke@435: desc->init_succs(); duke@435: } duke@435: } duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc) { duke@435: for (uint j=0; jnode()->len(); j++) { duke@435: Node *n = desc->node()->in(j); duke@435: if (n) { duke@435: NodeDescription *other_desc = _nodes.at(n->_idx); duke@435: other_desc->add_succ(desc); duke@435: } duke@435: } duke@435: } duke@435: } duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc && desc->block_index() == -1) { duke@435: duke@435: // Put Phi into same block as region duke@435: if (desc->node()->is_Phi() && desc->node()->in(0) && _nodes.at(desc->node()->in(0)->_idx)->block_index() != -1) { duke@435: int index = _nodes.at(desc->node()->in(0)->_idx)->block_index(); duke@435: desc->set_block_index(index); duke@435: blocks->adr_at(index)->add_node(desc); duke@435: duke@435: // Put Projections to same block as parent duke@435: } else if (desc->node()->is_block_proj() && _nodes.at(desc->node()->is_block_proj()->_idx)->block_index() != -1) { duke@435: int index = _nodes.at(desc->node()->is_block_proj()->_idx)->block_index(); duke@435: desc->set_block_index(index); duke@435: blocks->adr_at(index)->add_node(desc); duke@435: } else { duke@435: queue[queue_end] = desc; duke@435: queue_end++; duke@435: on_queue.set(desc->node()->_idx); duke@435: } duke@435: } duke@435: } duke@435: duke@435: duke@435: int z = 0; duke@435: while(queue_start != queue_end && z < 10000) { duke@435: duke@435: NodeDescription *desc = queue[queue_start]; duke@435: queue_start = (queue_start + 1) % queue_size; duke@435: on_queue >>= desc->node()->_idx; duke@435: duke@435: Node* node = desc->node(); duke@435: duke@435: if (desc->succs()->length() == 0) { duke@435: int x = 0; duke@435: } duke@435: duke@435: int block_index = -1; duke@435: if (desc->succs()->length() != 0) { duke@435: for (int i = 0; i < desc->succs()->length(); i++) { duke@435: NodeDescription *cur_desc = desc->succs()->at(i); duke@435: if (cur_desc != desc) { duke@435: if (cur_desc->succs()->length() == 0) { duke@435: duke@435: // Ignore nodes with 0 successors duke@435: duke@435: } else if (cur_desc->block_index() == -1) { duke@435: duke@435: // Let this node schedule first duke@435: block_index = -1; duke@435: break; duke@435: duke@435: } else if (cur_desc->node()->is_Phi()){ duke@435: duke@435: // Special treatment for Phi functions duke@435: PhiNode *phi = cur_desc->node()->as_Phi(); duke@435: assert(phi->in(0) && phi->in(0)->is_Region(), "Must have region node in first input"); duke@435: RegionNode *region = phi->in(0)->as_Region(); duke@435: duke@435: for (uint j=1; jlen(); j++) { duke@435: Node *cur_phi_input = phi->in(j); duke@435: if (cur_phi_input == desc->node() && region->in(j)) { duke@435: NodeDescription *cur_region_input = _nodes.at(region->in(j)->_idx); duke@435: if (cur_region_input->block_index() == -1) { duke@435: duke@435: // Let this node schedule first duke@435: block_index = -1; duke@435: break; duke@435: } else { duke@435: if (block_index == -1) { duke@435: block_index = cur_region_input->block_index(); duke@435: } else { duke@435: block_index = common_dominator[block_index][cur_region_input->block_index()]; duke@435: } duke@435: } duke@435: } duke@435: } duke@435: duke@435: } else { duke@435: if (block_index == -1) { duke@435: block_index = cur_desc->block_index(); duke@435: } else { duke@435: block_index = common_dominator[block_index][cur_desc->block_index()]; duke@435: } duke@435: } duke@435: } duke@435: } duke@435: } duke@435: duke@435: if (block_index == -1) { duke@435: queue[queue_end] = desc; duke@435: queue_end = (queue_end + 1) % queue_size; duke@435: on_queue.set(desc->node()->_idx); duke@435: z++; duke@435: } else { duke@435: assert(desc->block_index() == -1, ""); duke@435: desc->set_block_index(block_index); duke@435: blocks->adr_at(block_index)->add_node(desc); duke@435: z = 0; duke@435: } duke@435: } duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc && desc->block_index() == -1) { duke@435: duke@435: //if (desc->node()->is_Proj() || desc->node()->is_Con()) { duke@435: Node *parent = desc->node()->in(0); duke@435: uint cur = 1; duke@435: while(!parent && cur < desc->node()->len()) { duke@435: parent = desc->node()->in(cur); duke@435: cur++; duke@435: } duke@435: duke@435: if (parent && _nodes.at(parent->_idx)->block_index() != -1) { duke@435: int index = _nodes.at(parent->_idx)->block_index(); duke@435: desc->set_block_index(index); duke@435: blocks->adr_at(index)->add_node(desc); duke@435: } else { duke@435: desc->set_block_index(0); duke@435: blocks->adr_at(0)->add_node(desc); duke@435: //ShouldNotReachHere(); duke@435: } duke@435: //} duke@435: /* duke@435: if (desc->node()->is_block_proj() && _nodes.at(desc->node()->is_block_proj()->_idx)->block_index() != -1) { duke@435: int index = _nodes.at(desc->node()->is_block_proj()->_idx)->block_index(); duke@435: desc->set_block_index(index); duke@435: blocks->adr_at(index)->add_node(desc); duke@435: } */ duke@435: } duke@435: } duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc) { duke@435: desc->clear_succs(); duke@435: } duke@435: } duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc) { duke@435: int block_index = desc->block_index(); duke@435: duke@435: assert(block_index >= 0 && block_index < blocks->length(), "Block index must be in range"); duke@435: assert(blocks->adr_at(block_index)->nodes()->contains(desc), "Node must be child of block"); duke@435: } duke@435: } duke@435: a->destruct_contents(); duke@435: } duke@435: duke@435: void IdealGraphPrinter::build_blocks(Node *root) { duke@435: duke@435: Arena *a = new Arena(); duke@435: Node_Stack stack(a, 100); duke@435: duke@435: VectorSet visited(a); duke@435: stack.push(root, 0); duke@435: GrowableArray blocks(a, 2, 0, Block(0)); duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: if (_nodes.at(i)) _nodes.at(i)->set_block_index(-1); duke@435: } duke@435: duke@435: duke@435: // Order nodes such that node index is equal to idx duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: duke@435: if (_nodes.at(i)) { duke@435: NodeDescription *node = _nodes.at(i); duke@435: int index = node->node()->_idx; duke@435: if (index != i) { duke@435: _nodes.at_grow(index); duke@435: NodeDescription *tmp = _nodes.at(index); duke@435: *(_nodes.adr_at(index)) = node; duke@435: *(_nodes.adr_at(i)) = tmp; duke@435: i--; duke@435: } duke@435: } duke@435: } duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *node = _nodes.at(i); duke@435: if (node) { duke@435: assert(node->node()->_idx == (uint)i, ""); duke@435: } duke@435: } duke@435: duke@435: while(stack.is_nonempty()) { duke@435: duke@435: //Node *n = stack.node(); duke@435: //int index = stack.index(); duke@435: Node *proj = stack.node();//n->in(index); duke@435: const Node *parent = proj->is_block_proj(); duke@435: if (parent == NULL) { duke@435: parent = proj; duke@435: } duke@435: duke@435: if (!visited.test_set(parent->_idx)) { duke@435: duke@435: NodeDescription *end_desc = _nodes.at(parent->_idx); duke@435: int block_index = blocks.length(); duke@435: Block block(block_index); duke@435: blocks.append(block); duke@435: Block *b = blocks.adr_at(block_index); duke@435: b->set_start(end_desc); duke@435: // assert(end_desc->block_index() == -1, ""); duke@435: end_desc->set_block_index(block_index); duke@435: b->add_node(end_desc); duke@435: duke@435: // Skip any control-pinned middle'in stuff duke@435: Node *p = proj; duke@435: NodeDescription *start_desc = NULL; duke@435: do { duke@435: proj = p; // Update pointer to last Control duke@435: if (p->in(0) == NULL) { duke@435: start_desc = end_desc; duke@435: break; duke@435: } duke@435: p = p->in(0); // Move control forward duke@435: start_desc = _nodes.at(p->_idx); duke@435: assert(start_desc, ""); duke@435: duke@435: if (start_desc != end_desc && start_desc->block_index() == -1) { duke@435: assert(start_desc->block_index() == -1, ""); duke@435: assert(block_index < blocks.length(), ""); duke@435: start_desc->set_block_index(block_index); duke@435: b->add_node(start_desc); duke@435: } duke@435: } while( !p->is_block_proj() && duke@435: !p->is_block_start() ); duke@435: duke@435: for (uint i = 0; i < start_desc->node()->len(); i++) { duke@435: duke@435: Node *pred_node = start_desc->node()->in(i); duke@435: duke@435: duke@435: if (pred_node && pred_node != start_desc->node()) { duke@435: const Node *cur_parent = pred_node->is_block_proj(); duke@435: if (cur_parent != NULL) { duke@435: pred_node = (Node *)cur_parent; duke@435: } duke@435: duke@435: NodeDescription *pred_node_desc = _nodes.at(pred_node->_idx); duke@435: if (pred_node_desc->block_index() != -1) { duke@435: blocks.adr_at(pred_node_desc->block_index())->add_succ(block_index); duke@435: } duke@435: } duke@435: } duke@435: duke@435: for (DUIterator_Fast dmax, i = end_desc->node()->fast_outs(dmax); i < dmax; i++) { duke@435: Node* cur_succ = end_desc->node()->fast_out(i); duke@435: NodeDescription *cur_succ_desc = _nodes.at(cur_succ->_idx); duke@435: duke@435: DUIterator_Fast dmax2, i2 = cur_succ->fast_outs(dmax2); duke@435: if (cur_succ->is_block_proj() && i2 < dmax2 && !cur_succ->is_Root()) { duke@435: duke@435: for (; i2fast_out(i2); duke@435: if (cur_succ2) { duke@435: cur_succ_desc = _nodes.at(cur_succ2->_idx); duke@435: if (cur_succ_desc == NULL) { duke@435: // dead node so skip it duke@435: continue; duke@435: } duke@435: if (cur_succ2 != end_desc->node() && cur_succ_desc->block_index() != -1) { duke@435: b->add_succ(cur_succ_desc->block_index()); duke@435: } duke@435: } duke@435: } duke@435: duke@435: } else { duke@435: duke@435: if (cur_succ != end_desc->node() && cur_succ_desc && cur_succ_desc->block_index() != -1) { duke@435: b->add_succ(cur_succ_desc->block_index()); duke@435: } duke@435: } duke@435: } duke@435: duke@435: duke@435: int num_preds = p->len(); duke@435: int bottom = -1; duke@435: if (p->is_Region() || p->is_Phi()) { duke@435: bottom = 0; duke@435: } duke@435: duke@435: int pushed = 0; duke@435: for (int i=num_preds - 1; i > bottom; i--) { duke@435: if (p->in(i) != NULL && p->in(i) != p) { duke@435: stack.push(p->in(i), 0); duke@435: pushed++; duke@435: } duke@435: } duke@435: duke@435: if (pushed == 0 && p->is_Root() && !_matcher) { duke@435: // Special case when backedges to root are not yet built duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: if (_nodes.at(i) && _nodes.at(i)->node()->is_SafePoint() && _nodes.at(i)->node()->outcnt() == 0) { duke@435: stack.push(_nodes.at(i)->node(), 0); duke@435: } duke@435: } duke@435: } duke@435: duke@435: } else { duke@435: stack.pop(); duke@435: } duke@435: } duke@435: duke@435: build_dominators(&blocks); duke@435: duke@435: int **common_dominator = NEW_RESOURCE_ARRAY(int *, blocks.length()); duke@435: for (int i = 0; i < blocks.length(); i++) { duke@435: int *cur = NEW_RESOURCE_ARRAY(int, blocks.length()); duke@435: common_dominator[i] = cur; duke@435: duke@435: for (int j=0; jadd_child(blocks.adr_at(i)->index()); duke@435: } duke@435: build_common_dominator(common_dominator, 0, &blocks); duke@435: duke@435: schedule_latest(common_dominator, &blocks); duke@435: duke@435: start_element(CONTROL_FLOW_ELEMENT); duke@435: duke@435: for (int i = 0; i < blocks.length(); i++) { duke@435: Block *block = blocks.adr_at(i); duke@435: duke@435: Properties props; duke@435: props.add(new Property(BLOCK_NAME_PROPERTY, i)); duke@435: props.add(new Property(BLOCK_DOMINATOR_PROPERTY, block->dominator())); duke@435: start_element(BLOCK_ELEMENT, &props); duke@435: duke@435: if (block->succs()->length() > 0) { duke@435: start_element(SUCCESSORS_ELEMENT); duke@435: for (int j=0; jsuccs()->length(); j++) { duke@435: int cur_index = block->succs()->at(j); duke@435: if (cur_index != 0 /* start_block has must not have inputs */) { duke@435: Properties properties; duke@435: properties.add(new Property(BLOCK_NAME_PROPERTY, cur_index)); duke@435: simple_element(SUCCESSOR_ELEMENT, &properties); duke@435: } duke@435: } duke@435: end_element(SUCCESSORS_ELEMENT); duke@435: } duke@435: duke@435: start_element(NODES_ELEMENT); duke@435: duke@435: for (int j=0; jnodes()->length(); j++) { duke@435: NodeDescription *n = block->nodes()->at(j); duke@435: Properties properties; duke@435: properties.add(new Property(NODE_ID_PROPERTY, n->id())); duke@435: simple_element(NODE_ELEMENT, &properties); duke@435: } duke@435: duke@435: end_element(NODES_ELEMENT); duke@435: duke@435: end_element(BLOCK_ELEMENT); duke@435: } duke@435: duke@435: duke@435: end_element(CONTROL_FLOW_ELEMENT); duke@435: duke@435: a->destruct_contents(); duke@435: } duke@435: duke@435: void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { duke@435: print(compile, name, (Node *)compile->root(), level, clear_nodes); duke@435: } duke@435: duke@435: // Print current ideal graph duke@435: void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { duke@435: duke@435: // if (finish && !in_method) return; duke@435: if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return; duke@435: duke@435: assert(_current_method, "newMethod has to be called first!"); duke@435: duke@435: if (clear_nodes) { duke@435: int x = 0; duke@435: } duke@435: duke@435: _clear_nodes = clear_nodes; duke@435: duke@435: // Warning, unsafe cast? duke@435: _chaitin = (PhaseChaitin *)compile->regalloc(); duke@435: _matcher = compile->matcher(); duke@435: duke@435: duke@435: // Update nodes duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc) { duke@435: desc->set_state(Invalid); duke@435: } duke@435: } duke@435: Node *n = node; duke@435: walk(n); duke@435: duke@435: // Update edges duke@435: for (int i = 0; i < _edges.length(); i++) { duke@435: _edges.at(i)->set_state(Invalid); duke@435: } duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc && desc->state() != Invalid) { duke@435: duke@435: int to = desc->id(); duke@435: uint len = desc->node()->len(); duke@435: for (uint j=0; jnode()->in(j); duke@435: duke@435: if (n) { duke@435: duke@435: duke@435: intptr_t from = (intptr_t)n; duke@435: duke@435: // Assert from node is valid duke@435: /* duke@435: bool ok = false; duke@435: for (int k=0; k<_nodes.length(); k++) { duke@435: NodeDescription *desc = _nodes.at(k); duke@435: if (desc && desc->id() == from) { duke@435: assert(desc->state() != Invalid, ""); duke@435: ok = true; duke@435: } duke@435: } duke@435: assert(ok, "");*/ duke@435: duke@435: uint index = j; duke@435: if (index >= desc->node()->req()) { duke@435: index = desc->node()->req(); duke@435: } duke@435: duke@435: print_edge(from, to, index); duke@435: } duke@435: } duke@435: } duke@435: } duke@435: duke@435: bool is_different = false; duke@435: duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc && desc->state() != Valid) { duke@435: is_different = true; duke@435: break; duke@435: } duke@435: } duke@435: duke@435: if (!is_different) { duke@435: for (int i = 0; i < _edges.length(); i++) { duke@435: EdgeDescription *conn = _edges.at(i); duke@435: if (conn && conn->state() != Valid) { duke@435: is_different = true; duke@435: break; duke@435: } duke@435: } duke@435: } duke@435: duke@435: // No changes -> do not print graph duke@435: if (!is_different) return; duke@435: duke@435: Properties properties; duke@435: properties.add(new Property(GRAPH_NAME_PROPERTY, (const char *)name)); duke@435: start_element(GRAPH_ELEMENT, &properties); duke@435: duke@435: start_element(NODES_ELEMENT); duke@435: for (int i = 0; i < _nodes.length(); i++) { duke@435: NodeDescription *desc = _nodes.at(i); duke@435: if (desc) { duke@435: desc->print(this); duke@435: if (desc->state() == Invalid) { duke@435: delete desc; duke@435: _nodes.at_put(i, NULL); duke@435: } else { duke@435: desc->set_state(Valid); duke@435: } duke@435: } duke@435: } duke@435: end_element(NODES_ELEMENT); duke@435: duke@435: build_blocks(node); duke@435: duke@435: start_element(EDGES_ELEMENT); duke@435: for (int i = 0; i < _edges.length(); i++) { duke@435: EdgeDescription *conn = _edges.at(i); duke@435: duke@435: // Assert from and to nodes are valid duke@435: /* duke@435: if (!conn->state() == Invalid) { duke@435: bool ok1 = false; duke@435: bool ok2 = false; duke@435: for (int j=0; j<_nodes.length(); j++) { duke@435: NodeDescription *desc = _nodes.at(j); duke@435: if (desc && desc->id() == conn->from()) { duke@435: ok1 = true; duke@435: } duke@435: duke@435: if (desc && desc->id() == conn->to()) { duke@435: ok2 = true; duke@435: } duke@435: } duke@435: duke@435: assert(ok1, "from node not found!"); duke@435: assert(ok2, "to node not found!"); duke@435: }*/ duke@435: duke@435: conn->print(this); duke@435: if (conn->state() == Invalid) { duke@435: _edges.remove_at(i); duke@435: delete conn; duke@435: i--; duke@435: } duke@435: } duke@435: duke@435: end_element(EDGES_ELEMENT); duke@435: duke@435: end_element(GRAPH_ELEMENT); duke@435: duke@435: _output->flush(); duke@435: } duke@435: duke@435: // Print edge duke@435: void IdealGraphPrinter::print_edge(int from, int to, int index) { duke@435: duke@435: EdgeDescription *conn = new EdgeDescription(from, to, index); duke@435: for (int i = 0; i < _edges.length(); i++) { duke@435: if (_edges.at(i)->equals(conn)) { duke@435: conn->set_state(Valid); duke@435: delete _edges.at(i); duke@435: _edges.at_put(i, conn); duke@435: return; duke@435: } duke@435: } duke@435: duke@435: _edges.append(conn); duke@435: } duke@435: duke@435: extern const char *NodeClassNames[]; duke@435: duke@435: // Create node description duke@435: IdealGraphPrinter::NodeDescription *IdealGraphPrinter::create_node_description(Node* node) { duke@435: duke@435: #ifndef PRODUCT duke@435: node->_in_dump_cnt++; duke@435: NodeDescription *desc = new NodeDescription(node); duke@435: desc->properties()->add(new Property(NODE_NAME_PROPERTY, (const char *)node->Name())); duke@435: duke@435: const Type *t = node->bottom_type(); duke@435: desc->properties()->add(new Property("type", (const char *)Type::msg[t->base()])); duke@435: duke@435: desc->properties()->add(new Property("idx", node->_idx)); duke@435: #ifdef ASSERT duke@435: desc->properties()->add(new Property("debug_idx", node->_debug_idx)); duke@435: #endif duke@435: duke@435: duke@435: const jushort flags = node->flags(); duke@435: if (flags & Node::Flag_is_Copy) { duke@435: desc->properties()->add(new Property("is_copy", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_Call) { duke@435: desc->properties()->add(new Property("is_call", "true")); duke@435: } duke@435: if (flags & Node::Flag_rematerialize) { duke@435: desc->properties()->add(new Property("rematerialize", "true")); duke@435: } duke@435: if (flags & Node::Flag_needs_anti_dependence_check) { duke@435: desc->properties()->add(new Property("needs_anti_dependence_check", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_macro) { duke@435: desc->properties()->add(new Property("is_macro", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_Con) { duke@435: desc->properties()->add(new Property("is_con", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_cisc_alternate) { duke@435: desc->properties()->add(new Property("is_cisc_alternate", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_Branch) { duke@435: desc->properties()->add(new Property("is_branch", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_block_start) { duke@435: desc->properties()->add(new Property("is_block_start", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_Goto) { duke@435: desc->properties()->add(new Property("is_goto", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_dead_loop_safe) { duke@435: desc->properties()->add(new Property("is_dead_loop_safe", "true")); duke@435: } duke@435: if (flags & Node::Flag_may_be_short_branch) { duke@435: desc->properties()->add(new Property("may_be_short_branch", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_safepoint_node) { duke@435: desc->properties()->add(new Property("is_safepoint_node", "true")); duke@435: } duke@435: if (flags & Node::Flag_is_pc_relative) { duke@435: desc->properties()->add(new Property("is_pc_relative", "true")); duke@435: } duke@435: duke@435: if (_matcher) { duke@435: if (_matcher->is_shared(desc->node())) { duke@435: desc->properties()->add(new Property("is_shared", "true")); duke@435: } else { duke@435: desc->properties()->add(new Property("is_shared", "false")); duke@435: } duke@435: duke@435: if (_matcher->is_dontcare(desc->node())) { duke@435: desc->properties()->add(new Property("is_dontcare", "true")); duke@435: } else { duke@435: desc->properties()->add(new Property("is_dontcare", "false")); duke@435: } duke@435: } duke@435: duke@435: if (node->is_Proj()) { duke@435: desc->properties()->add(new Property("con", (int)node->as_Proj()->_con)); duke@435: } duke@435: duke@435: if (node->is_Mach()) { duke@435: desc->properties()->add(new Property("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()])); duke@435: } duke@435: duke@435: duke@435: duke@435: duke@435: duke@435: outputStream *oldTty = tty; duke@435: buffer[0] = 0; duke@435: stringStream s2(buffer, sizeof(buffer) - 1); duke@435: duke@435: node->dump_spec(&s2); duke@435: assert(s2.size() < sizeof(buffer), "size in range"); duke@435: desc->properties()->add(new Property("dump_spec", buffer)); duke@435: duke@435: if (node->is_block_proj()) { duke@435: desc->properties()->add(new Property("is_block_proj", "true")); duke@435: } duke@435: duke@435: if (node->is_block_start()) { duke@435: desc->properties()->add(new Property("is_block_start", "true")); duke@435: } duke@435: duke@435: const char *short_name = "short_name"; duke@435: if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { duke@435: int index = node->as_Proj()->_con - TypeFunc::Parms; duke@435: if (index >= 10) { duke@435: desc->properties()->add(new Property(short_name, "PA")); duke@435: } else { duke@435: sprintf(buffer, "P%d", index); duke@435: desc->properties()->add(new Property(short_name, buffer)); duke@435: } duke@435: } else if (strcmp(node->Name(), "IfTrue") == 0) { duke@435: desc->properties()->add(new Property(short_name, "T")); duke@435: } else if (strcmp(node->Name(), "IfFalse") == 0) { duke@435: desc->properties()->add(new Property(short_name, "F")); duke@435: } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) { duke@435: duke@435: if (t->base() == Type::Int && t->is_int()->is_con()) { duke@435: const TypeInt *typeInt = t->is_int(); duke@435: assert(typeInt->is_con(), "must be constant"); duke@435: jint value = typeInt->get_con(); duke@435: duke@435: // max. 2 chars allowed duke@435: if (value >= -9 && value <= 99) { duke@435: sprintf(buffer, "%d", value); duke@435: desc->properties()->add(new Property(short_name, buffer)); duke@435: } duke@435: else duke@435: { duke@435: desc->properties()->add(new Property(short_name, "I")); duke@435: } duke@435: } else if (t == Type::TOP) { duke@435: desc->properties()->add(new Property(short_name, "^")); duke@435: } else if (t->base() == Type::Long && t->is_long()->is_con()) { duke@435: const TypeLong *typeLong = t->is_long(); duke@435: assert(typeLong->is_con(), "must be constant"); duke@435: jlong value = typeLong->get_con(); duke@435: duke@435: // max. 2 chars allowed duke@435: if (value >= -9 && value <= 99) { duke@435: sprintf(buffer, "%d", value); duke@435: desc->properties()->add(new Property(short_name, buffer)); duke@435: } duke@435: else duke@435: { duke@435: desc->properties()->add(new Property(short_name, "L")); duke@435: } duke@435: } else if (t->base() == Type::KlassPtr) { duke@435: const TypeKlassPtr *typeKlass = t->is_klassptr(); duke@435: desc->properties()->add(new Property(short_name, "CP")); duke@435: } else if (t->base() == Type::Control) { duke@435: desc->properties()->add(new Property(short_name, "C")); duke@435: } else if (t->base() == Type::Memory) { duke@435: desc->properties()->add(new Property(short_name, "M")); duke@435: } else if (t->base() == Type::Abio) { duke@435: desc->properties()->add(new Property(short_name, "IO")); duke@435: } else if (t->base() == Type::Return_Address) { duke@435: desc->properties()->add(new Property(short_name, "RA")); duke@435: } else if (t->base() == Type::AnyPtr) { duke@435: desc->properties()->add(new Property(short_name, "P")); duke@435: } else if (t->base() == Type::RawPtr) { duke@435: desc->properties()->add(new Property(short_name, "RP")); duke@435: } else if (t->base() == Type::AryPtr) { duke@435: desc->properties()->add(new Property(short_name, "AP")); duke@435: } duke@435: } duke@435: duke@435: if (node->is_SafePoint()) { duke@435: SafePointNode *safePointNode = node->as_SafePoint(); duke@435: if (safePointNode->jvms()) { duke@435: stringStream bciStream; duke@435: bciStream.print("%d ", safePointNode->jvms()->bci()); duke@435: JVMState *caller = safePointNode->jvms()->caller(); duke@435: while(caller) { duke@435: bciStream.print("%d ", caller->bci()); duke@435: duke@435: caller = caller->caller(); duke@435: } duke@435: desc->properties()->add(new Property("bci", bciStream.as_string())); duke@435: } duke@435: } duke@435: duke@435: if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { duke@435: buffer[0] = 0; duke@435: _chaitin->dump_register(node, buffer); duke@435: desc->properties()->add(new Property("reg", buffer)); duke@435: desc->properties()->add(new Property("lrg", _chaitin->n2lidx(node))); duke@435: } duke@435: duke@435: duke@435: node->_in_dump_cnt--; duke@435: return desc; duke@435: #else duke@435: return NULL; duke@435: #endif duke@435: } duke@435: duke@435: void IdealGraphPrinter::pre_node(Node* node, void *env) { duke@435: duke@435: IdealGraphPrinter *printer = (IdealGraphPrinter *)env; duke@435: duke@435: NodeDescription *newDesc = printer->create_node_description(node); duke@435: duke@435: if (printer->_clear_nodes) { duke@435: duke@435: printer->_nodes.append(newDesc); duke@435: } else { duke@435: duke@435: NodeDescription *desc = printer->_nodes.at_grow(node->_idx, NULL); duke@435: duke@435: if (desc && desc->equals(newDesc)) { duke@435: //desc->set_state(Valid); duke@435: //desc->set_node(node); duke@435: delete desc; duke@435: printer->_nodes.at_put(node->_idx, NULL); duke@435: newDesc->set_state(Valid); duke@435: //printer->_nodes.at_put(node->_idx, newDesc); duke@435: } else { duke@435: duke@435: if (desc && desc->id() == newDesc->id()) { duke@435: delete desc; duke@435: printer->_nodes.at_put(node->_idx, NULL); duke@435: newDesc->set_state(New); duke@435: duke@435: } duke@435: duke@435: //if (desc) { duke@435: // delete desc; duke@435: //} duke@435: duke@435: //printer->_nodes.at_put(node->_idx, newDesc); duke@435: } duke@435: duke@435: printer->_nodes.append(newDesc); duke@435: } duke@435: } duke@435: duke@435: void IdealGraphPrinter::post_node(Node* node, void *env) { duke@435: } duke@435: duke@435: outputStream *IdealGraphPrinter::output() { duke@435: return _output; duke@435: } duke@435: duke@435: IdealGraphPrinter::Description::Description() { duke@435: _state = New; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Description::print(IdealGraphPrinter *printer) { duke@435: if (_state == Invalid) { duke@435: print_removed(printer); duke@435: } else if (_state == New) { duke@435: print_changed(printer); duke@435: } duke@435: } duke@435: duke@435: void IdealGraphPrinter::Description::set_state(State s) { duke@435: _state = s; duke@435: } duke@435: duke@435: IdealGraphPrinter::State IdealGraphPrinter::Description::state() { duke@435: return _state; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::set_proj(NodeDescription *n) { duke@435: _proj = n; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::set_start(NodeDescription *n) { duke@435: _start = n; duke@435: } duke@435: duke@435: int IdealGraphPrinter::Block::semi() { duke@435: return _semi; duke@435: } duke@435: duke@435: int IdealGraphPrinter::Block::parent() { duke@435: return _parent; duke@435: } duke@435: duke@435: GrowableArray* IdealGraphPrinter::Block::bucket() { duke@435: return &_bucket; duke@435: } duke@435: duke@435: GrowableArray* IdealGraphPrinter::Block::children() { duke@435: return &_children; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::add_child(int i) { duke@435: _children.append(i); duke@435: } duke@435: duke@435: GrowableArray* IdealGraphPrinter::Block::dominates() { duke@435: return &_dominates; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::add_dominates(int i) { duke@435: _dominates.append(i); duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::add_to_bucket(int i) { duke@435: _bucket.append(i); duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::clear_bucket() { duke@435: _bucket.clear(); duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::set_dominator(int i) { duke@435: _dominator = i; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::set_label(int i) { duke@435: _label = i; duke@435: } duke@435: duke@435: int IdealGraphPrinter::Block::label() { duke@435: return _label; duke@435: } duke@435: duke@435: int IdealGraphPrinter::Block::ancestor() { duke@435: return _ancestor; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::set_ancestor(int i) { duke@435: _ancestor = i; duke@435: } duke@435: duke@435: int IdealGraphPrinter::Block::dominator() { duke@435: return _dominator; duke@435: } duke@435: duke@435: int IdealGraphPrinter::Block::index() { duke@435: return _index; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::set_parent(int i) { duke@435: _parent = i; duke@435: } duke@435: duke@435: GrowableArray* IdealGraphPrinter::Block::pred() { duke@435: return &_pred; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::set_semi(int i) { duke@435: _semi = i; duke@435: } duke@435: duke@435: IdealGraphPrinter::Block::Block() { duke@435: } duke@435: duke@435: IdealGraphPrinter::Block::Block(int index) { duke@435: _index = index; duke@435: _label = index; duke@435: _semi = -1; duke@435: _ancestor = -1; duke@435: _dominator = -1; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::add_pred(int i) { duke@435: _pred.append(i); duke@435: } duke@435: duke@435: IdealGraphPrinter::NodeDescription *IdealGraphPrinter::Block::proj() { duke@435: return _proj; duke@435: } duke@435: duke@435: IdealGraphPrinter::NodeDescription *IdealGraphPrinter::Block::start() { duke@435: return _start; duke@435: } duke@435: duke@435: GrowableArray* IdealGraphPrinter::Block::succs() { duke@435: return &_succs; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Block::add_succ(int index) { duke@435: duke@435: if (this->_index == 16 && index == 15) { duke@435: int x = 0; duke@435: } duke@435: duke@435: if (!_succs.contains(index)) { duke@435: _succs.append(index); duke@435: } duke@435: } duke@435: duke@435: duke@435: void IdealGraphPrinter::Block::add_node(NodeDescription *n) { duke@435: if (!_nodes.contains(n)) { duke@435: _nodes.append(n); duke@435: } duke@435: } duke@435: duke@435: GrowableArray* IdealGraphPrinter::Block::nodes() { duke@435: return &_nodes; duke@435: } duke@435: duke@435: int IdealGraphPrinter::NodeDescription::count = 0; duke@435: duke@435: IdealGraphPrinter::NodeDescription::NodeDescription(Node* node) : _node(node) { duke@435: _id = (intptr_t)(node); duke@435: _block_index = -1; duke@435: } duke@435: duke@435: IdealGraphPrinter::NodeDescription::~NodeDescription() { duke@435: _properties.clean(); duke@435: } duke@435: duke@435: // void IdealGraphPrinter::NodeDescription::set_node(Node* node) { duke@435: // //this->_node = node; duke@435: // } duke@435: duke@435: int IdealGraphPrinter::NodeDescription::block_index() { duke@435: return _block_index; duke@435: } duke@435: duke@435: duke@435: GrowableArray* IdealGraphPrinter::NodeDescription::succs() { duke@435: return &_succs; duke@435: } duke@435: duke@435: void IdealGraphPrinter::NodeDescription::clear_succs() { duke@435: _succs.clear(); duke@435: } duke@435: duke@435: void IdealGraphPrinter::NodeDescription::init_succs() { duke@435: _succs = GrowableArray(); duke@435: } duke@435: duke@435: void IdealGraphPrinter::NodeDescription::add_succ(NodeDescription *desc) { duke@435: _succs.append(desc); duke@435: } duke@435: duke@435: void IdealGraphPrinter::NodeDescription::set_block_index(int i) { duke@435: _block_index = i; duke@435: } duke@435: duke@435: bool IdealGraphPrinter::NodeDescription::equals(NodeDescription *desc) { duke@435: if (desc == NULL) return false; duke@435: if (desc->id() != id()) return false; duke@435: return properties()->equals(desc->properties()); duke@435: } duke@435: duke@435: Node* IdealGraphPrinter::NodeDescription::node() { duke@435: return _node; duke@435: } duke@435: duke@435: IdealGraphPrinter::Properties* IdealGraphPrinter::NodeDescription::properties() { duke@435: return &_properties; duke@435: } duke@435: duke@435: uint IdealGraphPrinter::NodeDescription::id() { duke@435: return _id; duke@435: } duke@435: duke@435: void IdealGraphPrinter::NodeDescription::print_changed(IdealGraphPrinter *printer) { duke@435: duke@435: duke@435: Properties properties; duke@435: properties.add(new Property(NODE_ID_PROPERTY, id())); duke@435: printer->start_element(NODE_ELEMENT, &properties); duke@435: duke@435: this->properties()->print(printer); duke@435: duke@435: duke@435: printer->end_element(NODE_ELEMENT); duke@435: } duke@435: duke@435: void IdealGraphPrinter::NodeDescription::print_removed(IdealGraphPrinter *printer) { duke@435: duke@435: Properties properties; duke@435: properties.add(new Property(NODE_ID_PROPERTY, id())); duke@435: printer->simple_element(REMOVE_NODE_ELEMENT, &properties); duke@435: } duke@435: duke@435: IdealGraphPrinter::EdgeDescription::EdgeDescription(int from, int to, int index) { duke@435: this->_from = from; duke@435: this->_to = to; duke@435: this->_index = index; duke@435: } duke@435: duke@435: IdealGraphPrinter::EdgeDescription::~EdgeDescription() { duke@435: } duke@435: duke@435: int IdealGraphPrinter::EdgeDescription::from() { duke@435: return _from; duke@435: } duke@435: duke@435: int IdealGraphPrinter::EdgeDescription::to() { duke@435: return _to; duke@435: } duke@435: duke@435: void IdealGraphPrinter::EdgeDescription::print_changed(IdealGraphPrinter *printer) { duke@435: duke@435: Properties properties; duke@435: properties.add(new Property(INDEX_PROPERTY, _index)); duke@435: properties.add(new Property(FROM_PROPERTY, _from)); duke@435: properties.add(new Property(TO_PROPERTY, _to)); duke@435: printer->simple_element(EDGE_ELEMENT, &properties); duke@435: } duke@435: duke@435: void IdealGraphPrinter::EdgeDescription::print_removed(IdealGraphPrinter *printer) { duke@435: duke@435: Properties properties; duke@435: properties.add(new Property(INDEX_PROPERTY, _index)); duke@435: properties.add(new Property(FROM_PROPERTY, _from)); duke@435: properties.add(new Property(TO_PROPERTY, _to)); duke@435: printer->simple_element(REMOVE_EDGE_ELEMENT, &properties); duke@435: } duke@435: duke@435: bool IdealGraphPrinter::EdgeDescription::equals(IdealGraphPrinter::EdgeDescription *desc) { duke@435: if (desc == NULL) return false; duke@435: return (_from == desc->_from && _to == desc->_to && _index == desc->_index); duke@435: } duke@435: duke@435: IdealGraphPrinter::Properties::Properties() : list(new (ResourceObj::C_HEAP) GrowableArray(2, 0, NULL, true)) { duke@435: } duke@435: duke@435: IdealGraphPrinter::Properties::~Properties() { duke@435: clean(); duke@435: delete list; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Properties::add(Property *p) { duke@435: assert(p != NULL, "Property not NULL"); duke@435: list->append(p); duke@435: } duke@435: duke@435: void IdealGraphPrinter::Properties::print(IdealGraphPrinter *printer) { duke@435: printer->start_element(PROPERTIES_ELEMENT); duke@435: duke@435: for (int i = 0; i < list->length(); i++) { duke@435: list->at(i)->print(printer); duke@435: } duke@435: duke@435: printer->end_element(PROPERTIES_ELEMENT); duke@435: } duke@435: duke@435: void IdealGraphPrinter::Properties::clean() { duke@435: for (int i = 0; i < list->length(); i++) { duke@435: delete list->at(i); duke@435: list->at_put(i, NULL); duke@435: } duke@435: list->clear(); duke@435: assert(list->length() == 0, "List cleared"); duke@435: } duke@435: duke@435: void IdealGraphPrinter::Properties::remove(const char *name) { duke@435: for (int i = 0; i < list->length(); i++) { duke@435: if (strcmp(list->at(i)->name(), name) == 0) { duke@435: delete list->at(i); duke@435: list->remove_at(i); duke@435: i--; duke@435: } duke@435: } duke@435: } duke@435: duke@435: void IdealGraphPrinter::Properties::print_as_attributes(IdealGraphPrinter *printer) { duke@435: duke@435: for (int i = 0; i < list->length(); i++) { duke@435: assert(list->at(i) != NULL, "Property not null!"); duke@435: printer->output()->print(" "); duke@435: list->at(i)->print_as_attribute(printer); duke@435: } duke@435: } duke@435: duke@435: bool IdealGraphPrinter::Properties::equals(Properties* p) { duke@435: if (p->list->length() != this->list->length()) return false; duke@435: duke@435: for (int i = 0; i < list->length(); i++) { duke@435: assert(list->at(i) != NULL, "Property not null!"); duke@435: if (!list->at(i)->equals(p->list->at(i))) return false; duke@435: } duke@435: duke@435: return true; duke@435: } duke@435: duke@435: IdealGraphPrinter::Property::Property() { duke@435: _name = NULL; duke@435: _value = NULL; duke@435: } duke@435: duke@435: const char *IdealGraphPrinter::Property::name() { duke@435: return _name; duke@435: } duke@435: duke@435: IdealGraphPrinter::Property::Property(const Property* p) { duke@435: duke@435: this->_name = NULL; duke@435: this->_value = NULL; duke@435: duke@435: if (p->_name != NULL) { duke@435: _name = dup(p->_name); duke@435: } duke@435: duke@435: if (p->_value) { duke@435: _value = dup(p->_value); duke@435: } duke@435: } duke@435: duke@435: IdealGraphPrinter::Property::~Property() { duke@435: duke@435: clean(); duke@435: } duke@435: duke@435: IdealGraphPrinter::Property::Property(const char *name, const char *value) { duke@435: duke@435: assert(name, "Name must not be null!"); duke@435: assert(value, "Value must not be null!"); duke@435: duke@435: _name = dup(name); duke@435: _value = dup(value); duke@435: } duke@435: duke@435: IdealGraphPrinter::Property::Property(const char *name, int intValue) { duke@435: _name = dup(name); duke@435: duke@435: stringStream stream; duke@435: stream.print("%d", intValue); duke@435: _value = dup(stream.as_string()); duke@435: } duke@435: duke@435: void IdealGraphPrinter::Property::clean() { duke@435: if (_name) { duke@435: delete _name; duke@435: _name = NULL; duke@435: } duke@435: duke@435: if (_value) { duke@435: delete _value; duke@435: _value = NULL; duke@435: } duke@435: } duke@435: duke@435: duke@435: bool IdealGraphPrinter::Property::is_null() { duke@435: return _name == NULL; duke@435: } duke@435: duke@435: void IdealGraphPrinter::Property::print(IdealGraphPrinter *printer) { duke@435: duke@435: assert(!is_null(), "null properties cannot be printed!"); duke@435: Properties properties; duke@435: properties.add(new Property(PROPERTY_NAME_PROPERTY, _name)); duke@435: printer->start_element(PROPERTY_ELEMENT, &properties, false, false); duke@435: printer->print_xml(_value); duke@435: printer->end_element(PROPERTY_ELEMENT, false, true); duke@435: } duke@435: duke@435: void IdealGraphPrinter::Property::print_as_attribute(IdealGraphPrinter *printer) { duke@435: duke@435: printer->output()->print(_name); duke@435: printer->output()->print("=\""); duke@435: printer->print_xml(_value); duke@435: printer->output()->print("\""); duke@435: } duke@435: duke@435: duke@435: bool IdealGraphPrinter::Property::equals(Property* p) { duke@435: duke@435: if (is_null() && p->is_null()) return true; duke@435: if (is_null()) return false; duke@435: if (p->is_null()) return false; duke@435: duke@435: int cmp1 = strcmp(p->_name, _name); duke@435: if (cmp1 != 0) return false; duke@435: duke@435: int cmp2 = strcmp(p->_value, _value); duke@435: if (cmp2 != 0) return false; duke@435: duke@435: return true; duke@435: } duke@435: duke@435: void IdealGraphPrinter::print_xml(const char *value) { duke@435: size_t len = strlen(value); duke@435: duke@435: char buf[2]; duke@435: buf[1] = 0; duke@435: for (size_t i = 0; i < len; i++) { duke@435: char c = value[i]; duke@435: duke@435: switch(c) { duke@435: case '<': duke@435: output()->print("<"); duke@435: break; duke@435: duke@435: case '>': duke@435: output()->print(">"); duke@435: break; duke@435: duke@435: default: duke@435: buf[0] = c; duke@435: output()->print(buf); duke@435: break; duke@435: } duke@435: } duke@435: } duke@435: duke@435: #endif