hotspot/src/share/vm/opto/idealGraphPrinter.cpp

Print this page
rev 611 : Merge

*** 1,10 **** - #ifdef USE_PRAGMA_IDENT_HDR - #pragma ident "@(#)idealGraphPrinter.cpp 1.2 07/10/02 11:32:04 JVM" - #endif /* ! * Copyright 2007 Sun Microsystems, Inc. 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. --- 1,7 ---- /* ! * Copyright 2007-2008 Sun Microsystems, Inc. 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.
*** 101,120 **** } // Constructor, either file or network output IdealGraphPrinter::IdealGraphPrinter() { ! _traverse_outs = false; _should_send_method = true; _output = NULL; buffer[0] = 0; _depth = 0; _current_method = NULL; assert(!_current_method, "current method must be initialized to NULL"); ! _arena = new Arena(); ! ! _stream = new (ResourceObj::C_HEAP) networkStream(); if (PrintIdealGraphFile != NULL) { ThreadCritical tc; // User wants all output to go to files if (_file_count != 0) { --- 98,119 ---- } // Constructor, either file or network output IdealGraphPrinter::IdealGraphPrinter() { ! // 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; assert(!_current_method, "current method must be initialized to NULL"); ! _stream = NULL; if (PrintIdealGraphFile != NULL) { ThreadCritical tc; // User wants all output to go to files if (_file_count != 0) {
*** 125,140 **** st.write(PrintIdealGraphFile, dot - PrintIdealGraphFile); st.print("%d%s", _file_count, dot); } else { st.print("%s%d", PrintIdealGraphFile, _file_count); } ! _output = new (ResourceObj::C_HEAP) fileStream(st.as_string()); } else { ! _output = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile); } _file_count++; } else { // Try to connect to visualizer if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) { char c = 0; _stream->read(&c, 1); if (c != 'y') { --- 124,143 ---- st.write(PrintIdealGraphFile, dot - PrintIdealGraphFile); st.print("%d%s", _file_count, dot); } else { st.print("%s%d", PrintIdealGraphFile, _file_count); } ! fileStream *stream = new (ResourceObj::C_HEAP) fileStream(st.as_string()); ! _output = stream; } else { ! fileStream *stream = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile); ! _output = stream; } _file_count++; } else { + _stream = new (ResourceObj::C_HEAP) networkStream(); + // Try to connect to visualizer if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) { char c = 0; _stream->read(&c, 1); if (c != 'y') {
*** 150,166 **** // be an error if we can't connect to the visualizer. fatal2("Couldn't connect to visualizer at %s:%d", PrintIdealGraphAddress, PrintIdealGraphPort); } } ! start_element(TOP_ELEMENT); } // Destructor, close file or network stream IdealGraphPrinter::~IdealGraphPrinter() { ! end_element(TOP_ELEMENT); if (_stream) { delete _stream; if (_stream == _output) { _output = NULL; --- 153,180 ---- // be an error if we can't connect to the visualizer. fatal2("Couldn't connect to visualizer at %s:%d", PrintIdealGraphAddress, PrintIdealGraphPort); } } ! _xml = new (ResourceObj::C_HEAP) xmlStream(_output); ! ! head(TOP_ELEMENT); } // Destructor, close file or network stream IdealGraphPrinter::~IdealGraphPrinter() { ! tail(TOP_ELEMENT); ! ! // tty->print_cr("Walk time: %d", (int)_walk_time.milliseconds()); ! // tty->print_cr("Output time: %d", (int)_output_time.milliseconds()); ! // tty->print_cr("Build blocks time: %d", (int)_build_blocks_time.milliseconds()); ! ! if(_xml) { ! delete _xml; ! _xml = NULL; ! } if (_stream) { delete _stream; if (_stream == _output) { _output = NULL;
*** 172,269 **** delete _output; _output = NULL; } } - void IdealGraphPrinter::print_ifg(PhaseIFG* ifg) { ! // Code to print an interference graph to tty, currently not used ! /* ! if (!_current_method) return; ! // Remove neighbor colors ! for (uint i = 0; i < ifg._maxlrg; i++) { ! IndexSet *s = ifg.neighbors(i); ! IndexSetIterator elements(s); ! uint neighbor; ! while ((neighbor = elements.next()) != 0) { ! tty->print_cr("Edge between %d and %d\n", i, neighbor); ! } ! } ! for (uint i = 0; i < ifg._maxlrg; i++) { ! LRG &l = ifg.lrgs(i); ! if (l._def) { ! OptoReg::Name name = l.reg(); ! tty->print("OptoReg::dump: "); ! OptoReg::dump(name); ! tty->print_cr(""); ! tty->print_cr("name=%d\n", name); ! if (name) { ! if (OptoReg::is_stack(name)) { ! tty->print_cr("Stack number %d\n", OptoReg::reg2stack(name)); ! } else if (!OptoReg::is_valid(name)) { ! tty->print_cr("BAD!!!"); ! } else { ! if (OptoReg::is_reg(name)) { ! tty->print_cr(OptoReg::regname(name)); ! } else { ! int x = 0; ! } ! } ! int x = 0; ! } ! if (l._def == NodeSentinel) { ! tty->print("multiple mapping from %d: ", i); ! for (int j=0; j<l._defs->length(); j++) { ! tty->print("%d ", l._defs->at(j)->_idx); ! } ! tty->print_cr(""); ! } else { ! tty->print_cr("mapping between %d and %d\n", i, l._def->_idx); ! } ! } ! }*/ } void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) { - Properties properties; stringStream str; method->print_name(&str); stringStream shortStr; method->print_short_name(&shortStr); ! properties.add(new Property(METHOD_NAME_PROPERTY, str.as_string())); ! properties.add(new Property(METHOD_SHORT_NAME_PROPERTY, shortStr.as_string())); ! properties.add(new Property(METHOD_BCI_PROPERTY, bci)); ! start_element(METHOD_ELEMENT, &properties); ! start_element(BYTECODES_ELEMENT); output()->print_cr("<![CDATA["); method->print_codes_on(output()); output()->print_cr("]]>"); ! end_element(BYTECODES_ELEMENT); ! start_element(INLINE_ELEMENT); if (tree != NULL) { GrowableArray<InlineTree *> subtrees = tree->subtrees(); for (int i = 0; i < subtrees.length(); i++) { print_inline_tree(subtrees.at(i)); } } ! end_element(INLINE_ELEMENT); ! end_element(METHOD_ELEMENT); output()->flush(); } void IdealGraphPrinter::print_inline_tree(InlineTree *tree) { --- 186,282 ---- delete _output; _output = NULL; } } ! void IdealGraphPrinter::begin_elem(const char *s) { ! _xml->begin_elem(s); ! } ! ! void IdealGraphPrinter::end_elem() { ! _xml->end_elem(); ! } ! void IdealGraphPrinter::begin_head(const char *s) { ! _xml->begin_head(s); ! } ! void IdealGraphPrinter::end_head() { ! _xml->end_head(); ! } ! void IdealGraphPrinter::print_attr(const char *name, intptr_t val) { ! stringStream stream; ! stream.print(INTX_FORMAT, val); ! print_attr(name, stream.as_string()); ! } + void IdealGraphPrinter::print_attr(const char *name, const char *val) { + _xml->print(" %s='", name); + text(val); + _xml->print("'"); + } ! void IdealGraphPrinter::head(const char *name) { ! _xml->head(name); ! } ! void IdealGraphPrinter::tail(const char *name) { ! _xml->tail(name); ! } ! void IdealGraphPrinter::text(const char *s) { ! _xml->text(s); ! } ! void IdealGraphPrinter::print_prop(const char *name, int val) { ! ! stringStream stream; ! stream.print("%d", val); ! print_prop(name, stream.as_string()); ! } ! ! void IdealGraphPrinter::print_prop(const char *name, const char *val) { ! begin_head(PROPERTY_ELEMENT); ! print_attr(PROPERTY_NAME_PROPERTY, name); ! end_head(); ! text(val); ! tail(PROPERTY_ELEMENT); } void IdealGraphPrinter::print_method(ciMethod *method, int bci, InlineTree *tree) { + begin_head(METHOD_ELEMENT); stringStream str; method->print_name(&str); stringStream shortStr; method->print_short_name(&shortStr); + print_attr(METHOD_NAME_PROPERTY, str.as_string()); + print_attr(METHOD_SHORT_NAME_PROPERTY, shortStr.as_string()); + print_attr(METHOD_BCI_PROPERTY, bci); ! end_head(); ! head(BYTECODES_ELEMENT); output()->print_cr("<![CDATA["); method->print_codes_on(output()); output()->print_cr("]]>"); ! tail(BYTECODES_ELEMENT); ! head(INLINE_ELEMENT); if (tree != NULL) { GrowableArray<InlineTree *> subtrees = tree->subtrees(); for (int i = 0; i < subtrees.length(); i++) { print_inline_tree(subtrees.at(i)); } } ! tail(INLINE_ELEMENT); ! tail(METHOD_ELEMENT); output()->flush(); } void IdealGraphPrinter::print_inline_tree(InlineTree *tree) {
*** 272,287 **** ciMethod *method = tree->method(); print_method(tree->method(), tree->caller_bci(), tree); } - void IdealGraphPrinter::clear_nodes() { - // for (int i = 0; i < _nodes.length(); i++) { - // _nodes.at(i)->clear_node(); - // } - } - void IdealGraphPrinter::print_inlining(Compile* compile) { // Print inline tree if (_should_send_method) { InlineTree *inlineTree = compile->ilt(); --- 285,294 ----
*** 299,1922 **** ciMethod *method = compile->method(); assert(_output, "output stream must exist!"); assert(method, "null methods are not allowed!"); assert(!_current_method, "current method must be null!"); ! _arena->destruct_contents(); ! start_element(GROUP_ELEMENT); // Print properties - Properties properties; - // Add method name stringStream strStream; method->print_name(&strStream); ! properties.add(new Property(METHOD_NAME_PROPERTY, strStream.as_string())); if (method->flags().is_public()) { ! properties.add(new Property(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE)); } if (method->flags().is_static()) { ! properties.add(new Property(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE)); } ! properties.print(this); if (_stream) { char answer = 0; ! _stream->flush(); int result = _stream->read(&answer, 1); _should_send_method = (answer == 'y'); } - this->_nodes = GrowableArray<NodeDescription *>(_arena, 2, 0, NULL); - this->_edges = GrowableArray< EdgeDescription * >(_arena, 2, 0, NULL); - - this->_current_method = method; ! ! ! _output->flush(); } // Has to be called whenever a method has finished compilation void IdealGraphPrinter::end_method() { - // if (finish && !in_method) return; - nmethod* method = (nmethod*)this->_current_method->code(); ! start_element(ASSEMBLY_ELEMENT); ! // Disassembler::decode(method, _output); ! end_element(ASSEMBLY_ELEMENT); ! ! ! end_element(GROUP_ELEMENT); _current_method = NULL; ! _output->flush(); ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc) { ! delete desc; ! _nodes.at_put(i, NULL); ! } ! } ! this->_nodes.clear(); ! ! ! for (int i = 0; i < _edges.length(); i++) { ! // for (int j=0; j<_edges.at(i)->length(); j++) { ! EdgeDescription *conn = _edges.at(i); ! conn->print(this); ! if (conn) { ! delete conn; ! _edges.at_put(i, NULL); ! } ! //} ! //_edges.at(i)->clear(); ! //delete _edges.at(i); ! //_edges.at_put(i, NULL); ! } ! this->_edges.clear(); ! ! // in_method = false; ! } ! ! // Outputs an XML start element ! void IdealGraphPrinter::start_element(const char *s, Properties *properties /* = NULL */, bool print_indent /* = false */, bool print_return /* = true */) { ! ! start_element_helper(s, properties, false, print_indent, print_return); ! _depth++; ! ! } ! ! // Outputs an XML start element without body ! void IdealGraphPrinter::simple_element(const char *s, Properties *properties /* = NULL */, bool print_indent /* = false */) { ! start_element_helper(s, properties, true, print_indent, true); ! } ! ! // Outputs an XML start element. If outputEnd is true, the element has no body. ! void IdealGraphPrinter::start_element_helper(const char *s, Properties *properties, bool outputEnd, bool print_indent /* = false */, bool print_return /* = true */) { ! ! assert(_output, "output stream must exist!"); ! ! if (print_indent) this->print_indent(); ! _output->print("<"); ! _output->print(s); ! if (properties) properties->print_as_attributes(this); ! ! if (outputEnd) { ! _output->print("/"); ! } ! ! _output->print(">"); ! if (print_return) _output->print_cr(""); ! } // Print indent void IdealGraphPrinter::print_indent() { for (int i = 0; i < _depth; i++) { ! _output->print(INDENT); } } - // Outputs an XML end element - void IdealGraphPrinter::end_element(const char *s, bool print_indent /* = true */, bool print_return /* = true */) { - - assert(_output, "output stream must exist!"); - - _depth--; - - if (print_indent) this->print_indent(); - _output->print("</"); - _output->print(s); - _output->print(">"); - if (print_return) _output->print_cr(""); - - } - bool IdealGraphPrinter::traverse_outs() { return _traverse_outs; } void IdealGraphPrinter::set_traverse_outs(bool b) { _traverse_outs = b; } ! void IdealGraphPrinter::walk(Node *start) { ! ! ! VectorSet visited(Thread::current()->resource_area()); ! GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); ! nodeStack.push(start); ! visited.test_set(start->_idx); ! while(nodeStack.length() > 0) { ! Node *n = nodeStack.pop(); ! IdealGraphPrinter::pre_node(n, this); ! if (_traverse_outs) { ! for (DUIterator i = n->outs(); n->has_out(i); i++) { ! Node* p = n->out(i); ! if (!visited.test_set(p->_idx)) { ! nodeStack.push(p); ! } ! } ! } for ( uint i = 0; i < n->len(); i++ ) { if ( n->in(i) ) { ! if (!visited.test_set(n->in(i)->_idx)) { ! nodeStack.push(n->in(i)); ! } ! } ! } } - } - - void IdealGraphPrinter::compress(int index, GrowableArray<Block>* blocks) { - Block *block = blocks->adr_at(index); - - int ancestor = block->ancestor(); - assert(ancestor != -1, ""); - - Block *ancestor_block = blocks->adr_at(ancestor); - if (ancestor_block->ancestor() != -1) { - compress(ancestor, blocks); - - int label = block->label(); - Block *label_block = blocks->adr_at(label); - - int ancestor_label = ancestor_block->label(); - Block *ancestor_label_block = blocks->adr_at(label); - if (ancestor_label_block->semi() < label_block->semi()) { - block->set_label(ancestor_label); - } - - block->set_ancestor(ancestor_block->ancestor()); } - } - int IdealGraphPrinter::eval(int index, GrowableArray<Block>* blocks) { - Block *block = blocks->adr_at(index); - if (block->ancestor() == -1) { - return index; } else { - compress(index, blocks); - return block->label(); - } - } - - void IdealGraphPrinter::link(int index1, int index2, GrowableArray<Block>* blocks) { - Block *block2 = blocks->adr_at(index2); - block2->set_ancestor(index1); - } - - void IdealGraphPrinter::build_dominators(GrowableArray<Block>* blocks) { ! if (blocks->length() == 0) return; ! GrowableArray<int> stack; ! stack.append(0); ! GrowableArray<Block *> array; ! ! assert(blocks->length() > 0, ""); ! blocks->adr_at(0)->set_dominator(0); ! int n = 0; ! while(!stack.is_empty()) { ! int index = stack.pop(); ! Block *block = blocks->adr_at(index); ! block->set_semi(n); ! array.append(block); ! n = n + 1; ! for (int i = 0; i < block->succs()->length(); i++) { ! int succ_index = block->succs()->at(i); ! Block *succ = blocks->adr_at(succ_index); ! if (succ->semi() == -1) { ! succ->set_parent(index); ! stack.push(succ_index); ! } ! succ->add_pred(index); } } ! for (int i=n-1; i>0; i--) { ! Block *block = array.at(i); ! int block_index = block->index(); ! for (int j=0; j<block->pred()->length(); j++) { ! int pred_index = block->pred()->at(j); ! int cur_index = eval(pred_index, blocks); ! ! Block *cur_block = blocks->adr_at(cur_index); ! if (cur_block->semi() < block->semi()) { ! block->set_semi(cur_block->semi()); ! } } ! ! int semi_index = block->semi(); ! Block *semi_block = array.at(semi_index); ! semi_block->add_to_bucket(block_index); ! ! link(block->parent(), block_index, blocks); ! Block *parent_block = blocks->adr_at(block->parent()); ! ! for (int j=0; j<parent_block->bucket()->length(); j++) { ! int cur_index = parent_block->bucket()->at(j); ! int new_index = eval(cur_index, blocks); ! Block *cur_block = blocks->adr_at(cur_index); ! Block *new_block = blocks->adr_at(new_index); ! int dom = block->parent(); ! ! if (new_block->semi() < cur_block->semi()) { ! dom = new_index; } ! ! cur_block->set_dominator(dom); } ! ! parent_block->clear_bucket(); } ! ! for (int i=1; i < n; i++) { ! ! Block *block = array.at(i); ! int block_index = block->index(); ! ! int semi_index = block->semi(); ! Block *semi_block = array.at(semi_index); ! ! if (block->dominator() != semi_block->index()) { ! int new_dom = blocks->adr_at(block->dominator())->dominator(); ! block->set_dominator(new_dom); } } ! ! for (int i = 0; i < blocks->length(); i++) { ! if (blocks->adr_at(i)->dominator() == -1) { ! blocks->adr_at(i)->set_dominator(0); } } ! ! // Build dominates array ! for (int i=1; i < blocks->length(); i++) { ! Block *block = blocks->adr_at(i); ! int dominator = block->dominator(); ! Block *dom_block = blocks->adr_at(dominator); ! dom_block->add_dominates(i); ! dom_block->add_child(i); ! ! while(dominator != 0) { ! dominator = dom_block->dominator(); ! dom_block = blocks->adr_at(dominator); ! dom_block->add_child(i); } } ! } ! ! void IdealGraphPrinter::build_common_dominator(int **common_dominator, int index, GrowableArray<Block>* blocks) { ! ! common_dominator[index][index] = index; ! Block *block = blocks->adr_at(index); ! for (int i = 0; i < block->dominates()->length(); i++) { ! Block *dominated = blocks->adr_at(block->dominates()->at(i)); ! ! for (int j=0; j<dominated->children()->length(); j++) { ! Block *child = blocks->adr_at(dominated->children()->at(j)); ! common_dominator[index][child->index()] = common_dominator[child->index()][index] = index; ! ! for (int k=0; k<i; k++) { ! Block *other_dominated = blocks->adr_at(block->dominates()->at(k)); ! common_dominator[child->index()][other_dominated->index()] = common_dominator[other_dominated->index()][child->index()] = index; ! ! for (int l=0 ; l<other_dominated->children()->length(); l++) { ! Block *other_child = blocks->adr_at(other_dominated->children()->at(l)); ! common_dominator[child->index()][other_child->index()] = common_dominator[other_child->index()][child->index()] = index; } } } ! ! build_common_dominator(common_dominator, dominated->index(), blocks); } - } ! void IdealGraphPrinter::schedule_latest(int **common_dominator, GrowableArray<Block>* blocks) { ! ! int queue_size = _nodes.length() + 1; ! NodeDescription **queue = NEW_RESOURCE_ARRAY(NodeDescription *, queue_size); ! int queue_start = 0; ! int queue_end = 0; ! Arena *a = new Arena(); ! VectorSet on_queue(a); ! ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc) { ! desc->init_succs(); } } ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc) { ! for (uint j=0; j<desc->node()->len(); j++) { ! Node *n = desc->node()->in(j); ! if (n) { ! NodeDescription *other_desc = _nodes.at(n->_idx); ! other_desc->add_succ(desc); ! } ! } } } ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc && desc->block_index() == -1) { ! ! // Put Phi into same block as region ! if (desc->node()->is_Phi() && desc->node()->in(0) && _nodes.at(desc->node()->in(0)->_idx)->block_index() != -1) { ! int index = _nodes.at(desc->node()->in(0)->_idx)->block_index(); ! desc->set_block_index(index); ! blocks->adr_at(index)->add_node(desc); ! ! // Put Projections to same block as parent ! } else if (desc->node()->is_block_proj() && _nodes.at(desc->node()->is_block_proj()->_idx)->block_index() != -1) { ! int index = _nodes.at(desc->node()->is_block_proj()->_idx)->block_index(); ! desc->set_block_index(index); ! blocks->adr_at(index)->add_node(desc); ! } else { ! queue[queue_end] = desc; ! queue_end++; ! on_queue.set(desc->node()->_idx); ! } ! } } ! ! int z = 0; ! while(queue_start != queue_end && z < 10000) { ! ! NodeDescription *desc = queue[queue_start]; ! queue_start = (queue_start + 1) % queue_size; ! on_queue >>= desc->node()->_idx; ! ! Node* node = desc->node(); ! ! if (desc->succs()->length() == 0) { ! int x = 0; } ! int block_index = -1; ! if (desc->succs()->length() != 0) { ! for (int i = 0; i < desc->succs()->length(); i++) { ! NodeDescription *cur_desc = desc->succs()->at(i); ! if (cur_desc != desc) { ! if (cur_desc->succs()->length() == 0) { ! // Ignore nodes with 0 successors ! } else if (cur_desc->block_index() == -1) { ! // Let this node schedule first ! block_index = -1; ! break; ! } else if (cur_desc->node()->is_Phi()){ ! // Special treatment for Phi functions ! PhiNode *phi = cur_desc->node()->as_Phi(); ! assert(phi->in(0) && phi->in(0)->is_Region(), "Must have region node in first input"); ! RegionNode *region = phi->in(0)->as_Region(); ! for (uint j=1; j<phi->len(); j++) { ! Node *cur_phi_input = phi->in(j); ! if (cur_phi_input == desc->node() && region->in(j)) { ! NodeDescription *cur_region_input = _nodes.at(region->in(j)->_idx); ! if (cur_region_input->block_index() == -1) { ! // Let this node schedule first ! block_index = -1; ! break; ! } else { ! if (block_index == -1) { ! block_index = cur_region_input->block_index(); } else { ! block_index = common_dominator[block_index][cur_region_input->block_index()]; ! } ! } ! } } } else { ! if (block_index == -1) { ! block_index = cur_desc->block_index(); ! } else { ! block_index = common_dominator[block_index][cur_desc->block_index()]; ! } ! } } } } ! if (block_index == -1) { ! queue[queue_end] = desc; ! queue_end = (queue_end + 1) % queue_size; ! on_queue.set(desc->node()->_idx); ! z++; } else { ! assert(desc->block_index() == -1, ""); ! desc->set_block_index(block_index); ! blocks->adr_at(block_index)->add_node(desc); ! z = 0; } } ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc && desc->block_index() == -1) { ! ! //if (desc->node()->is_Proj() || desc->node()->is_Con()) { ! Node *parent = desc->node()->in(0); ! uint cur = 1; ! while(!parent && cur < desc->node()->len()) { ! parent = desc->node()->in(cur); ! cur++; ! } ! ! if (parent && _nodes.at(parent->_idx)->block_index() != -1) { ! int index = _nodes.at(parent->_idx)->block_index(); ! desc->set_block_index(index); ! blocks->adr_at(index)->add_node(desc); ! } else { ! desc->set_block_index(0); ! blocks->adr_at(0)->add_node(desc); ! //ShouldNotReachHere(); ! } ! //} ! /* ! if (desc->node()->is_block_proj() && _nodes.at(desc->node()->is_block_proj()->_idx)->block_index() != -1) { ! int index = _nodes.at(desc->node()->is_block_proj()->_idx)->block_index(); ! desc->set_block_index(index); ! blocks->adr_at(index)->add_node(desc); ! } */ } } ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc) { ! desc->clear_succs(); ! } } ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc) { ! int block_index = desc->block_index(); ! assert(block_index >= 0 && block_index < blocks->length(), "Block index must be in range"); ! assert(blocks->adr_at(block_index)->nodes()->contains(desc), "Node must be child of block"); ! } } - a->destruct_contents(); } ! void IdealGraphPrinter::build_blocks(Node *root) { ! ! Arena *a = new Arena(); ! Node_Stack stack(a, 100); ! ! VectorSet visited(a); ! stack.push(root, 0); ! GrowableArray<Block> blocks(a, 2, 0, Block(0)); - for (int i = 0; i < _nodes.length(); i++) { - if (_nodes.at(i)) _nodes.at(i)->set_block_index(-1); - } ! // Order nodes such that node index is equal to idx ! for (int i = 0; i < _nodes.length(); i++) { ! if (_nodes.at(i)) { ! NodeDescription *node = _nodes.at(i); ! int index = node->node()->_idx; ! if (index != i) { ! _nodes.at_grow(index); ! NodeDescription *tmp = _nodes.at(index); ! *(_nodes.adr_at(index)) = node; ! *(_nodes.adr_at(i)) = tmp; ! i--; } } } ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *node = _nodes.at(i); ! if (node) { ! assert(node->node()->_idx == (uint)i, ""); ! } ! } ! ! while(stack.is_nonempty()) { ! ! //Node *n = stack.node(); ! //int index = stack.index(); ! Node *proj = stack.node();//n->in(index); ! const Node *parent = proj->is_block_proj(); ! if (parent == NULL) { ! parent = proj; ! } ! ! if (!visited.test_set(parent->_idx)) { ! ! NodeDescription *end_desc = _nodes.at(parent->_idx); ! int block_index = blocks.length(); ! Block block(block_index); ! blocks.append(block); ! Block *b = blocks.adr_at(block_index); ! b->set_start(end_desc); ! // assert(end_desc->block_index() == -1, ""); ! end_desc->set_block_index(block_index); ! b->add_node(end_desc); ! ! // Skip any control-pinned middle'in stuff ! Node *p = proj; ! NodeDescription *start_desc = NULL; ! do { ! proj = p; // Update pointer to last Control ! if (p->in(0) == NULL) { ! start_desc = end_desc; ! break; ! } ! p = p->in(0); // Move control forward ! start_desc = _nodes.at(p->_idx); ! assert(start_desc, ""); ! ! if (start_desc != end_desc && start_desc->block_index() == -1) { ! assert(start_desc->block_index() == -1, ""); ! assert(block_index < blocks.length(), ""); ! start_desc->set_block_index(block_index); ! b->add_node(start_desc); ! } ! } while( !p->is_block_proj() && ! !p->is_block_start() ); ! ! for (uint i = 0; i < start_desc->node()->len(); i++) { ! ! Node *pred_node = start_desc->node()->in(i); ! ! ! if (pred_node && pred_node != start_desc->node()) { ! const Node *cur_parent = pred_node->is_block_proj(); ! if (cur_parent != NULL) { ! pred_node = (Node *)cur_parent; ! } ! ! NodeDescription *pred_node_desc = _nodes.at(pred_node->_idx); ! if (pred_node_desc->block_index() != -1) { ! blocks.adr_at(pred_node_desc->block_index())->add_succ(block_index); ! } ! } ! } ! ! for (DUIterator_Fast dmax, i = end_desc->node()->fast_outs(dmax); i < dmax; i++) { ! Node* cur_succ = end_desc->node()->fast_out(i); ! NodeDescription *cur_succ_desc = _nodes.at(cur_succ->_idx); ! ! DUIterator_Fast dmax2, i2 = cur_succ->fast_outs(dmax2); ! if (cur_succ->is_block_proj() && i2 < dmax2 && !cur_succ->is_Root()) { ! ! for (; i2<dmax2; i2++) { ! Node *cur_succ2 = cur_succ->fast_out(i2); ! if (cur_succ2) { ! cur_succ_desc = _nodes.at(cur_succ2->_idx); ! if (cur_succ_desc == NULL) { ! // dead node so skip it ! continue; ! } ! if (cur_succ2 != end_desc->node() && cur_succ_desc->block_index() != -1) { ! b->add_succ(cur_succ_desc->block_index()); ! } ! } ! } ! ! } else { ! ! if (cur_succ != end_desc->node() && cur_succ_desc && cur_succ_desc->block_index() != -1) { ! b->add_succ(cur_succ_desc->block_index()); ! } ! } ! } ! ! ! int num_preds = p->len(); ! int bottom = -1; ! if (p->is_Region() || p->is_Phi()) { ! bottom = 0; ! } ! ! int pushed = 0; ! for (int i=num_preds - 1; i > bottom; i--) { ! if (p->in(i) != NULL && p->in(i) != p) { ! stack.push(p->in(i), 0); ! pushed++; ! } ! } ! ! if (pushed == 0 && p->is_Root() && !_matcher) { ! // Special case when backedges to root are not yet built ! for (int i = 0; i < _nodes.length(); i++) { ! if (_nodes.at(i) && _nodes.at(i)->node()->is_SafePoint() && _nodes.at(i)->node()->outcnt() == 0) { ! stack.push(_nodes.at(i)->node(), 0); ! } ! } ! } ! ! } else { ! stack.pop(); ! } ! } ! ! build_dominators(&blocks); ! ! int **common_dominator = NEW_RESOURCE_ARRAY(int *, blocks.length()); ! for (int i = 0; i < blocks.length(); i++) { ! int *cur = NEW_RESOURCE_ARRAY(int, blocks.length()); ! common_dominator[i] = cur; ! ! for (int j=0; j<blocks.length(); j++) { ! cur[j] = 0; ! } ! } ! ! for (int i = 0; i < blocks.length(); i++) { ! blocks.adr_at(i)->add_child(blocks.adr_at(i)->index()); ! } ! build_common_dominator(common_dominator, 0, &blocks); ! ! schedule_latest(common_dominator, &blocks); ! ! start_element(CONTROL_FLOW_ELEMENT); ! ! for (int i = 0; i < blocks.length(); i++) { ! Block *block = blocks.adr_at(i); ! ! Properties props; ! props.add(new Property(BLOCK_NAME_PROPERTY, i)); ! props.add(new Property(BLOCK_DOMINATOR_PROPERTY, block->dominator())); ! start_element(BLOCK_ELEMENT, &props); ! ! if (block->succs()->length() > 0) { ! start_element(SUCCESSORS_ELEMENT); ! for (int j=0; j<block->succs()->length(); j++) { ! int cur_index = block->succs()->at(j); ! if (cur_index != 0 /* start_block has must not have inputs */) { ! Properties properties; ! properties.add(new Property(BLOCK_NAME_PROPERTY, cur_index)); ! simple_element(SUCCESSOR_ELEMENT, &properties); ! } } - end_element(SUCCESSORS_ELEMENT); } - - start_element(NODES_ELEMENT); - - for (int j=0; j<block->nodes()->length(); j++) { - NodeDescription *n = block->nodes()->at(j); - Properties properties; - properties.add(new Property(NODE_ID_PROPERTY, n->id())); - simple_element(NODE_ELEMENT, &properties); } - - end_element(NODES_ELEMENT); - - end_element(BLOCK_ELEMENT); } - - - end_element(CONTROL_FLOW_ELEMENT); - - a->destruct_contents(); } void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { print(compile, name, (Node *)compile->root(), level, clear_nodes); } // Print current ideal graph void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { - // if (finish && !in_method) return; if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return; ! assert(_current_method, "newMethod has to be called first!"); ! ! if (clear_nodes) { ! int x = 0; ! } ! ! _clear_nodes = clear_nodes; // Warning, unsafe cast? ! _chaitin = (PhaseChaitin *)compile->regalloc(); ! _matcher = compile->matcher(); ! ! ! // Update nodes ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc) { ! desc->set_state(Invalid); ! } ! } ! Node *n = node; ! walk(n); ! ! // Update edges ! for (int i = 0; i < _edges.length(); i++) { ! _edges.at(i)->set_state(Invalid); ! } ! ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc && desc->state() != Invalid) { ! ! int to = desc->id(); ! uint len = desc->node()->len(); ! for (uint j=0; j<len; j++) { ! Node *n = desc->node()->in(j); ! ! if (n) { ! ! ! intptr_t from = (intptr_t)n; ! ! // Assert from node is valid ! /* ! bool ok = false; ! for (int k=0; k<_nodes.length(); k++) { ! NodeDescription *desc = _nodes.at(k); ! if (desc && desc->id() == from) { ! assert(desc->state() != Invalid, ""); ! ok = true; ! } ! } ! assert(ok, "");*/ ! ! uint index = j; ! if (index >= desc->node()->req()) { ! index = desc->node()->req(); ! } ! ! print_edge(from, to, index); ! } ! } ! } ! } ! ! bool is_different = false; ! ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc && desc->state() != Valid) { ! is_different = true; ! break; ! } ! } ! ! if (!is_different) { ! for (int i = 0; i < _edges.length(); i++) { ! EdgeDescription *conn = _edges.at(i); ! if (conn && conn->state() != Valid) { ! is_different = true; ! break; ! } ! } ! } ! ! // No changes -> do not print graph ! if (!is_different) return; ! ! Properties properties; ! properties.add(new Property(GRAPH_NAME_PROPERTY, (const char *)name)); ! start_element(GRAPH_ELEMENT, &properties); ! ! start_element(NODES_ELEMENT); ! for (int i = 0; i < _nodes.length(); i++) { ! NodeDescription *desc = _nodes.at(i); ! if (desc) { ! desc->print(this); ! if (desc->state() == Invalid) { ! delete desc; ! _nodes.at_put(i, NULL); ! } else { ! desc->set_state(Valid); ! } ! } ! } ! end_element(NODES_ELEMENT); ! build_blocks(node); ! start_element(EDGES_ELEMENT); ! for (int i = 0; i < _edges.length(); i++) { ! EdgeDescription *conn = _edges.at(i); ! // Assert from and to nodes are valid ! /* ! if (!conn->state() == Invalid) { ! bool ok1 = false; ! bool ok2 = false; ! for (int j=0; j<_nodes.length(); j++) { ! NodeDescription *desc = _nodes.at(j); ! if (desc && desc->id() == conn->from()) { ! ok1 = true; ! } ! if (desc && desc->id() == conn->to()) { ! ok2 = true; ! } } ! assert(ok1, "from node not found!"); ! assert(ok2, "to node not found!"); ! }*/ ! ! conn->print(this); ! if (conn->state() == Invalid) { ! _edges.remove_at(i); ! delete conn; ! i--; ! } } ! end_element(EDGES_ELEMENT); ! ! end_element(GRAPH_ELEMENT); ! ! _output->flush(); ! } ! ! // Print edge ! void IdealGraphPrinter::print_edge(int from, int to, int index) { ! ! EdgeDescription *conn = new EdgeDescription(from, to, index); ! for (int i = 0; i < _edges.length(); i++) { ! if (_edges.at(i)->equals(conn)) { ! conn->set_state(Valid); ! delete _edges.at(i); ! _edges.at_put(i, conn); ! return; ! } } ! ! _edges.append(conn); } extern const char *NodeClassNames[]; - // Create node description - IdealGraphPrinter::NodeDescription *IdealGraphPrinter::create_node_description(Node* node) { - - #ifndef PRODUCT - node->_in_dump_cnt++; - NodeDescription *desc = new NodeDescription(node); - desc->properties()->add(new Property(NODE_NAME_PROPERTY, (const char *)node->Name())); - - const Type *t = node->bottom_type(); - desc->properties()->add(new Property("type", (const char *)Type::msg[t->base()])); - - desc->properties()->add(new Property("idx", node->_idx)); - #ifdef ASSERT - desc->properties()->add(new Property("debug_idx", node->_debug_idx)); - #endif - - - const jushort flags = node->flags(); - if (flags & Node::Flag_is_Copy) { - desc->properties()->add(new Property("is_copy", "true")); - } - if (flags & Node::Flag_is_Call) { - desc->properties()->add(new Property("is_call", "true")); - } - if (flags & Node::Flag_rematerialize) { - desc->properties()->add(new Property("rematerialize", "true")); - } - if (flags & Node::Flag_needs_anti_dependence_check) { - desc->properties()->add(new Property("needs_anti_dependence_check", "true")); - } - if (flags & Node::Flag_is_macro) { - desc->properties()->add(new Property("is_macro", "true")); - } - if (flags & Node::Flag_is_Con) { - desc->properties()->add(new Property("is_con", "true")); - } - if (flags & Node::Flag_is_cisc_alternate) { - desc->properties()->add(new Property("is_cisc_alternate", "true")); - } - if (flags & Node::Flag_is_Branch) { - desc->properties()->add(new Property("is_branch", "true")); - } - if (flags & Node::Flag_is_block_start) { - desc->properties()->add(new Property("is_block_start", "true")); - } - if (flags & Node::Flag_is_Goto) { - desc->properties()->add(new Property("is_goto", "true")); - } - if (flags & Node::Flag_is_dead_loop_safe) { - desc->properties()->add(new Property("is_dead_loop_safe", "true")); - } - if (flags & Node::Flag_may_be_short_branch) { - desc->properties()->add(new Property("may_be_short_branch", "true")); - } - if (flags & Node::Flag_is_safepoint_node) { - desc->properties()->add(new Property("is_safepoint_node", "true")); - } - if (flags & Node::Flag_is_pc_relative) { - desc->properties()->add(new Property("is_pc_relative", "true")); - } - - if (_matcher) { - if (_matcher->is_shared(desc->node())) { - desc->properties()->add(new Property("is_shared", "true")); - } else { - desc->properties()->add(new Property("is_shared", "false")); - } - - if (_matcher->is_dontcare(desc->node())) { - desc->properties()->add(new Property("is_dontcare", "true")); - } else { - desc->properties()->add(new Property("is_dontcare", "false")); - } - } - - if (node->is_Proj()) { - desc->properties()->add(new Property("con", (int)node->as_Proj()->_con)); - } - - if (node->is_Mach()) { - desc->properties()->add(new Property("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()])); - } - - - - - - outputStream *oldTty = tty; - buffer[0] = 0; - stringStream s2(buffer, sizeof(buffer) - 1); - - node->dump_spec(&s2); - assert(s2.size() < sizeof(buffer), "size in range"); - desc->properties()->add(new Property("dump_spec", buffer)); - - if (node->is_block_proj()) { - desc->properties()->add(new Property("is_block_proj", "true")); - } - - if (node->is_block_start()) { - desc->properties()->add(new Property("is_block_start", "true")); - } - - const char *short_name = "short_name"; - if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { - int index = node->as_Proj()->_con - TypeFunc::Parms; - if (index >= 10) { - desc->properties()->add(new Property(short_name, "PA")); - } else { - sprintf(buffer, "P%d", index); - desc->properties()->add(new Property(short_name, buffer)); - } - } else if (strcmp(node->Name(), "IfTrue") == 0) { - desc->properties()->add(new Property(short_name, "T")); - } else if (strcmp(node->Name(), "IfFalse") == 0) { - desc->properties()->add(new Property(short_name, "F")); - } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) { - - if (t->base() == Type::Int && t->is_int()->is_con()) { - const TypeInt *typeInt = t->is_int(); - assert(typeInt->is_con(), "must be constant"); - jint value = typeInt->get_con(); - - // max. 2 chars allowed - if (value >= -9 && value <= 99) { - sprintf(buffer, "%d", value); - desc->properties()->add(new Property(short_name, buffer)); - } - else - { - desc->properties()->add(new Property(short_name, "I")); - } - } else if (t == Type::TOP) { - desc->properties()->add(new Property(short_name, "^")); - } else if (t->base() == Type::Long && t->is_long()->is_con()) { - const TypeLong *typeLong = t->is_long(); - assert(typeLong->is_con(), "must be constant"); - jlong value = typeLong->get_con(); - - // max. 2 chars allowed - if (value >= -9 && value <= 99) { - sprintf(buffer, "%d", value); - desc->properties()->add(new Property(short_name, buffer)); - } - else - { - desc->properties()->add(new Property(short_name, "L")); - } - } else if (t->base() == Type::KlassPtr) { - const TypeKlassPtr *typeKlass = t->is_klassptr(); - desc->properties()->add(new Property(short_name, "CP")); - } else if (t->base() == Type::Control) { - desc->properties()->add(new Property(short_name, "C")); - } else if (t->base() == Type::Memory) { - desc->properties()->add(new Property(short_name, "M")); - } else if (t->base() == Type::Abio) { - desc->properties()->add(new Property(short_name, "IO")); - } else if (t->base() == Type::Return_Address) { - desc->properties()->add(new Property(short_name, "RA")); - } else if (t->base() == Type::AnyPtr) { - desc->properties()->add(new Property(short_name, "P")); - } else if (t->base() == Type::RawPtr) { - desc->properties()->add(new Property(short_name, "RP")); - } else if (t->base() == Type::AryPtr) { - desc->properties()->add(new Property(short_name, "AP")); - } - } - - if (node->is_SafePoint()) { - SafePointNode *safePointNode = node->as_SafePoint(); - if (safePointNode->jvms()) { - stringStream bciStream; - bciStream.print("%d ", safePointNode->jvms()->bci()); - JVMState *caller = safePointNode->jvms()->caller(); - while(caller) { - bciStream.print("%d ", caller->bci()); - - caller = caller->caller(); - } - desc->properties()->add(new Property("bci", bciStream.as_string())); - } - } - - if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { - buffer[0] = 0; - _chaitin->dump_register(node, buffer); - desc->properties()->add(new Property("reg", buffer)); - desc->properties()->add(new Property("lrg", _chaitin->n2lidx(node))); - } - - - node->_in_dump_cnt--; - return desc; - #else - return NULL; - #endif - } - - void IdealGraphPrinter::pre_node(Node* node, void *env) { - - IdealGraphPrinter *printer = (IdealGraphPrinter *)env; - - NodeDescription *newDesc = printer->create_node_description(node); - - if (printer->_clear_nodes) { - - printer->_nodes.append(newDesc); - } else { - - NodeDescription *desc = printer->_nodes.at_grow(node->_idx, NULL); - - if (desc && desc->equals(newDesc)) { - //desc->set_state(Valid); - //desc->set_node(node); - delete desc; - printer->_nodes.at_put(node->_idx, NULL); - newDesc->set_state(Valid); - //printer->_nodes.at_put(node->_idx, newDesc); - } else { - - if (desc && desc->id() == newDesc->id()) { - delete desc; - printer->_nodes.at_put(node->_idx, NULL); - newDesc->set_state(New); - - } - - //if (desc) { - // delete desc; - //} - - //printer->_nodes.at_put(node->_idx, newDesc); - } - - printer->_nodes.append(newDesc); - } - } - - void IdealGraphPrinter::post_node(Node* node, void *env) { - } - outputStream *IdealGraphPrinter::output() { ! return _output; ! } ! ! IdealGraphPrinter::Description::Description() { ! _state = New; ! } ! ! void IdealGraphPrinter::Description::print(IdealGraphPrinter *printer) { ! if (_state == Invalid) { ! print_removed(printer); ! } else if (_state == New) { ! print_changed(printer); ! } ! } ! ! void IdealGraphPrinter::Description::set_state(State s) { ! _state = s; ! } ! ! IdealGraphPrinter::State IdealGraphPrinter::Description::state() { ! return _state; ! } ! ! void IdealGraphPrinter::Block::set_proj(NodeDescription *n) { ! _proj = n; ! } ! ! void IdealGraphPrinter::Block::set_start(NodeDescription *n) { ! _start = n; ! } ! ! int IdealGraphPrinter::Block::semi() { ! return _semi; ! } ! ! int IdealGraphPrinter::Block::parent() { ! return _parent; ! } ! ! GrowableArray<int>* IdealGraphPrinter::Block::bucket() { ! return &_bucket; ! } ! ! GrowableArray<int>* IdealGraphPrinter::Block::children() { ! return &_children; ! } ! ! void IdealGraphPrinter::Block::add_child(int i) { ! _children.append(i); ! } ! ! GrowableArray<int>* IdealGraphPrinter::Block::dominates() { ! return &_dominates; ! } ! ! void IdealGraphPrinter::Block::add_dominates(int i) { ! _dominates.append(i); ! } ! ! void IdealGraphPrinter::Block::add_to_bucket(int i) { ! _bucket.append(i); ! } ! ! void IdealGraphPrinter::Block::clear_bucket() { ! _bucket.clear(); ! } ! ! void IdealGraphPrinter::Block::set_dominator(int i) { ! _dominator = i; ! } ! ! void IdealGraphPrinter::Block::set_label(int i) { ! _label = i; ! } ! ! int IdealGraphPrinter::Block::label() { ! return _label; ! } ! ! int IdealGraphPrinter::Block::ancestor() { ! return _ancestor; ! } ! ! void IdealGraphPrinter::Block::set_ancestor(int i) { ! _ancestor = i; ! } ! ! int IdealGraphPrinter::Block::dominator() { ! return _dominator; ! } ! ! int IdealGraphPrinter::Block::index() { ! return _index; ! } ! ! void IdealGraphPrinter::Block::set_parent(int i) { ! _parent = i; ! } ! ! GrowableArray<int>* IdealGraphPrinter::Block::pred() { ! return &_pred; ! } ! ! void IdealGraphPrinter::Block::set_semi(int i) { ! _semi = i; ! } ! ! IdealGraphPrinter::Block::Block() { ! } ! ! IdealGraphPrinter::Block::Block(int index) { ! _index = index; ! _label = index; ! _semi = -1; ! _ancestor = -1; ! _dominator = -1; ! } ! ! void IdealGraphPrinter::Block::add_pred(int i) { ! _pred.append(i); ! } ! ! IdealGraphPrinter::NodeDescription *IdealGraphPrinter::Block::proj() { ! return _proj; ! } ! ! IdealGraphPrinter::NodeDescription *IdealGraphPrinter::Block::start() { ! return _start; ! } ! ! GrowableArray<int>* IdealGraphPrinter::Block::succs() { ! return &_succs; ! } ! ! void IdealGraphPrinter::Block::add_succ(int index) { ! ! if (this->_index == 16 && index == 15) { ! int x = 0; ! } ! ! if (!_succs.contains(index)) { ! _succs.append(index); ! } ! } ! ! ! void IdealGraphPrinter::Block::add_node(NodeDescription *n) { ! if (!_nodes.contains(n)) { ! _nodes.append(n); ! } ! } ! ! GrowableArray<IdealGraphPrinter::NodeDescription *>* IdealGraphPrinter::Block::nodes() { ! return &_nodes; ! } ! ! int IdealGraphPrinter::NodeDescription::count = 0; ! ! IdealGraphPrinter::NodeDescription::NodeDescription(Node* node) : _node(node) { ! _id = (intptr_t)(node); ! _block_index = -1; ! } ! ! IdealGraphPrinter::NodeDescription::~NodeDescription() { ! _properties.clean(); ! } ! ! // void IdealGraphPrinter::NodeDescription::set_node(Node* node) { ! // //this->_node = node; ! // } ! ! int IdealGraphPrinter::NodeDescription::block_index() { ! return _block_index; ! } ! ! ! GrowableArray<IdealGraphPrinter::NodeDescription *>* IdealGraphPrinter::NodeDescription::succs() { ! return &_succs; ! } ! ! void IdealGraphPrinter::NodeDescription::clear_succs() { ! _succs.clear(); ! } ! ! void IdealGraphPrinter::NodeDescription::init_succs() { ! _succs = GrowableArray<NodeDescription *>(); ! } ! ! void IdealGraphPrinter::NodeDescription::add_succ(NodeDescription *desc) { ! _succs.append(desc); ! } ! ! void IdealGraphPrinter::NodeDescription::set_block_index(int i) { ! _block_index = i; ! } ! ! bool IdealGraphPrinter::NodeDescription::equals(NodeDescription *desc) { ! if (desc == NULL) return false; ! if (desc->id() != id()) return false; ! return properties()->equals(desc->properties()); ! } ! ! Node* IdealGraphPrinter::NodeDescription::node() { ! return _node; ! } ! ! IdealGraphPrinter::Properties* IdealGraphPrinter::NodeDescription::properties() { ! return &_properties; ! } ! ! uint IdealGraphPrinter::NodeDescription::id() { ! return _id; ! } ! ! void IdealGraphPrinter::NodeDescription::print_changed(IdealGraphPrinter *printer) { ! ! ! Properties properties; ! properties.add(new Property(NODE_ID_PROPERTY, id())); ! printer->start_element(NODE_ELEMENT, &properties); ! ! this->properties()->print(printer); ! ! ! printer->end_element(NODE_ELEMENT); ! } ! ! void IdealGraphPrinter::NodeDescription::print_removed(IdealGraphPrinter *printer) { ! ! Properties properties; ! properties.add(new Property(NODE_ID_PROPERTY, id())); ! printer->simple_element(REMOVE_NODE_ELEMENT, &properties); ! } ! ! IdealGraphPrinter::EdgeDescription::EdgeDescription(int from, int to, int index) { ! this->_from = from; ! this->_to = to; ! this->_index = index; ! } ! ! IdealGraphPrinter::EdgeDescription::~EdgeDescription() { ! } ! ! int IdealGraphPrinter::EdgeDescription::from() { ! return _from; ! } ! ! int IdealGraphPrinter::EdgeDescription::to() { ! return _to; ! } ! ! void IdealGraphPrinter::EdgeDescription::print_changed(IdealGraphPrinter *printer) { ! ! Properties properties; ! properties.add(new Property(INDEX_PROPERTY, _index)); ! properties.add(new Property(FROM_PROPERTY, _from)); ! properties.add(new Property(TO_PROPERTY, _to)); ! printer->simple_element(EDGE_ELEMENT, &properties); ! } ! ! void IdealGraphPrinter::EdgeDescription::print_removed(IdealGraphPrinter *printer) { ! ! Properties properties; ! properties.add(new Property(INDEX_PROPERTY, _index)); ! properties.add(new Property(FROM_PROPERTY, _from)); ! properties.add(new Property(TO_PROPERTY, _to)); ! printer->simple_element(REMOVE_EDGE_ELEMENT, &properties); ! } ! ! bool IdealGraphPrinter::EdgeDescription::equals(IdealGraphPrinter::EdgeDescription *desc) { ! if (desc == NULL) return false; ! return (_from == desc->_from && _to == desc->_to && _index == desc->_index); ! } ! ! IdealGraphPrinter::Properties::Properties() : list(new (ResourceObj::C_HEAP) GrowableArray<Property *>(2, 0, NULL, true)) { ! } ! ! IdealGraphPrinter::Properties::~Properties() { ! clean(); ! delete list; ! } ! ! void IdealGraphPrinter::Properties::add(Property *p) { ! assert(p != NULL, "Property not NULL"); ! list->append(p); ! } ! ! void IdealGraphPrinter::Properties::print(IdealGraphPrinter *printer) { ! printer->start_element(PROPERTIES_ELEMENT); ! ! for (int i = 0; i < list->length(); i++) { ! list->at(i)->print(printer); ! } ! ! printer->end_element(PROPERTIES_ELEMENT); ! } ! ! void IdealGraphPrinter::Properties::clean() { ! for (int i = 0; i < list->length(); i++) { ! delete list->at(i); ! list->at_put(i, NULL); ! } ! list->clear(); ! assert(list->length() == 0, "List cleared"); ! } ! ! void IdealGraphPrinter::Properties::remove(const char *name) { ! for (int i = 0; i < list->length(); i++) { ! if (strcmp(list->at(i)->name(), name) == 0) { ! delete list->at(i); ! list->remove_at(i); ! i--; ! } ! } ! } ! ! void IdealGraphPrinter::Properties::print_as_attributes(IdealGraphPrinter *printer) { ! ! for (int i = 0; i < list->length(); i++) { ! assert(list->at(i) != NULL, "Property not null!"); ! printer->output()->print(" "); ! list->at(i)->print_as_attribute(printer); ! } ! } ! ! bool IdealGraphPrinter::Properties::equals(Properties* p) { ! if (p->list->length() != this->list->length()) return false; ! ! for (int i = 0; i < list->length(); i++) { ! assert(list->at(i) != NULL, "Property not null!"); ! if (!list->at(i)->equals(p->list->at(i))) return false; ! } ! ! return true; ! } ! ! IdealGraphPrinter::Property::Property() { ! _name = NULL; ! _value = NULL; ! } ! ! const char *IdealGraphPrinter::Property::name() { ! return _name; ! } ! ! IdealGraphPrinter::Property::Property(const Property* p) { ! ! this->_name = NULL; ! this->_value = NULL; ! ! if (p->_name != NULL) { ! _name = dup(p->_name); ! } ! ! if (p->_value) { ! _value = dup(p->_value); ! } ! } ! ! IdealGraphPrinter::Property::~Property() { ! ! clean(); ! } ! ! IdealGraphPrinter::Property::Property(const char *name, const char *value) { ! ! assert(name, "Name must not be null!"); ! assert(value, "Value must not be null!"); ! ! _name = dup(name); ! _value = dup(value); ! } ! ! IdealGraphPrinter::Property::Property(const char *name, int intValue) { ! _name = dup(name); ! ! stringStream stream; ! stream.print("%d", intValue); ! _value = dup(stream.as_string()); ! } ! ! void IdealGraphPrinter::Property::clean() { ! if (_name) { ! delete _name; ! _name = NULL; ! } ! ! if (_value) { ! delete _value; ! _value = NULL; ! } ! } ! ! ! bool IdealGraphPrinter::Property::is_null() { ! return _name == NULL; ! } ! ! void IdealGraphPrinter::Property::print(IdealGraphPrinter *printer) { ! ! assert(!is_null(), "null properties cannot be printed!"); ! Properties properties; ! properties.add(new Property(PROPERTY_NAME_PROPERTY, _name)); ! printer->start_element(PROPERTY_ELEMENT, &properties, false, false); ! printer->print_xml(_value); ! printer->end_element(PROPERTY_ELEMENT, false, true); ! } ! ! void IdealGraphPrinter::Property::print_as_attribute(IdealGraphPrinter *printer) { ! ! printer->output()->print(_name); ! printer->output()->print("=\""); ! printer->print_xml(_value); ! printer->output()->print("\""); ! } ! ! ! bool IdealGraphPrinter::Property::equals(Property* p) { ! ! if (is_null() && p->is_null()) return true; ! if (is_null()) return false; ! if (p->is_null()) return false; ! ! int cmp1 = strcmp(p->_name, _name); ! if (cmp1 != 0) return false; ! ! int cmp2 = strcmp(p->_value, _value); ! if (cmp2 != 0) return false; ! ! return true; ! } ! ! void IdealGraphPrinter::print_xml(const char *value) { ! size_t len = strlen(value); ! ! char buf[2]; ! buf[1] = 0; ! for (size_t i = 0; i < len; i++) { ! char c = value[i]; ! ! switch(c) { ! case '<': ! output()->print("&lt;"); ! break; ! ! case '>': ! output()->print("&gt;"); ! break; ! ! default: ! buf[0] = c; ! output()->print(buf); ! break; ! } ! } } #endif --- 306,706 ---- ciMethod *method = compile->method(); assert(_output, "output stream must exist!"); assert(method, "null methods are not allowed!"); assert(!_current_method, "current method must be null!"); ! head(GROUP_ELEMENT); ! head(PROPERTIES_ELEMENT); // Print properties // Add method name stringStream strStream; method->print_name(&strStream); ! print_prop(METHOD_NAME_PROPERTY, strStream.as_string()); if (method->flags().is_public()) { ! print_prop(METHOD_IS_PUBLIC_PROPERTY, TRUE_VALUE); } if (method->flags().is_static()) { ! print_prop(METHOD_IS_STATIC_PROPERTY, TRUE_VALUE); } ! tail(PROPERTIES_ELEMENT); if (_stream) { char answer = 0; ! _xml->flush(); int result = _stream->read(&answer, 1); _should_send_method = (answer == 'y'); } this->_current_method = method; ! _xml->flush(); } // Has to be called whenever a method has finished compilation void IdealGraphPrinter::end_method() { nmethod* method = (nmethod*)this->_current_method->code(); ! tail(GROUP_ELEMENT); _current_method = NULL; ! _xml->flush(); } // Print indent void IdealGraphPrinter::print_indent() { + tty->print_cr("printing ident %d", _depth); for (int i = 0; i < _depth; i++) { ! _xml->print(INDENT); } } bool IdealGraphPrinter::traverse_outs() { return _traverse_outs; } void IdealGraphPrinter::set_traverse_outs(bool b) { _traverse_outs = b; } ! intptr_t IdealGraphPrinter::get_node_id(Node *n) { ! return (intptr_t)(n); ! } ! void IdealGraphPrinter::visit_node(Node *n, void *param) { ! if(param) { + // Output edge + intptr_t dest_id = get_node_id(n); for ( uint i = 0; i < n->len(); i++ ) { if ( n->in(i) ) { ! Node *source = n->in(i); ! begin_elem(EDGE_ELEMENT); ! intptr_t source_id = get_node_id(source); ! print_attr(FROM_PROPERTY, source_id); ! print_attr(TO_PROPERTY, dest_id); ! print_attr(INDEX_PROPERTY, i); ! end_elem(); } } } else { ! // Output node ! begin_head(NODE_ELEMENT); ! print_attr(NODE_ID_PROPERTY, get_node_id(n)); ! end_head(); ! head(PROPERTIES_ELEMENT); ! Node *node = n; ! #ifndef PRODUCT ! node->_in_dump_cnt++; ! print_prop(NODE_NAME_PROPERTY, (const char *)node->Name()); ! const Type *t = node->bottom_type(); ! print_prop("type", (const char *)Type::msg[t->base()]); ! print_prop("idx", node->_idx); ! #ifdef ASSERT ! print_prop("debug_idx", node->_debug_idx); ! #endif ! if(C->cfg() != NULL) { ! Block *block = C->cfg()->_bbs[node->_idx]; ! if(block == NULL) { ! print_prop("block", C->cfg()->_blocks[0]->_pre_order); ! } else { ! print_prop("block", block->_pre_order); } } ! const jushort flags = node->flags(); ! if (flags & Node::Flag_is_Copy) { ! print_prop("is_copy", "true"); } ! if (flags & Node::Flag_is_Call) { ! print_prop("is_call", "true"); } ! if (flags & Node::Flag_rematerialize) { ! print_prop("rematerialize", "true"); } ! if (flags & Node::Flag_needs_anti_dependence_check) { ! print_prop("needs_anti_dependence_check", "true"); } ! if (flags & Node::Flag_is_macro) { ! print_prop("is_macro", "true"); } + if (flags & Node::Flag_is_Con) { + print_prop("is_con", "true"); } ! if (flags & Node::Flag_is_cisc_alternate) { ! print_prop("is_cisc_alternate", "true"); } + if (flags & Node::Flag_is_Branch) { + print_prop("is_branch", "true"); } ! if (flags & Node::Flag_is_block_start) { ! print_prop("is_block_start", "true"); } + if (flags & Node::Flag_is_Goto) { + print_prop("is_goto", "true"); } ! if (flags & Node::Flag_is_dead_loop_safe) { ! print_prop("is_dead_loop_safe", "true"); } + if (flags & Node::Flag_may_be_short_branch) { + print_prop("may_be_short_branch", "true"); } + if (flags & Node::Flag_is_safepoint_node) { + print_prop("is_safepoint_node", "true"); } ! if (flags & Node::Flag_is_pc_relative) { ! print_prop("is_pc_relative", "true"); } ! if (C->matcher() != NULL) { ! if (C->matcher()->is_shared(node)) { ! print_prop("is_shared", "true"); ! } else { ! print_prop("is_shared", "false"); } + if (C->matcher()->is_dontcare(node)) { + print_prop("is_dontcare", "true"); + } else { + print_prop("is_dontcare", "false"); } ! #ifdef ASSERT ! Node* old = C->matcher()->find_old_node(node); ! if (old != NULL) { ! print_prop("old_node_idx", old->_idx); } + #endif } ! if (node->is_Proj()) { ! print_prop("con", (int)node->as_Proj()->_con); } ! if (node->is_Mach()) { ! print_prop("idealOpcode", (const char *)NodeClassNames[node->as_Mach()->ideal_Opcode()]); } ! buffer[0] = 0; ! stringStream s2(buffer, sizeof(buffer) - 1); ! node->dump_spec(&s2); ! if (t != NULL && (t->isa_instptr() || t->isa_klassptr())) { ! const TypeInstPtr *toop = t->isa_instptr(); ! const TypeKlassPtr *tkls = t->isa_klassptr(); ! ciKlass* klass = toop ? toop->klass() : (tkls ? tkls->klass() : NULL ); ! if( klass && klass->is_loaded() && klass->is_interface() ) { ! s2.print(" Interface:"); ! } else if( toop ) { ! s2.print(" Oop:"); ! } else if( tkls ) { ! s2.print(" Klass:"); ! } ! t->dump_on(&s2); ! } else if( t == Type::MEMORY ) { ! s2.print(" Memory:"); ! MemNode::dump_adr_type(node, node->adr_type(), &s2); ! } ! assert(s2.size() < sizeof(buffer), "size in range"); ! print_prop("dump_spec", buffer); ! if (node->is_block_proj()) { ! print_prop("is_block_proj", "true"); ! } ! if (node->is_block_start()) { ! print_prop("is_block_start", "true"); ! } ! const char *short_name = "short_name"; ! if (strcmp(node->Name(), "Parm") == 0 && node->as_Proj()->_con >= TypeFunc::Parms) { ! int index = node->as_Proj()->_con - TypeFunc::Parms; ! if (index >= 10) { ! print_prop(short_name, "PA"); ! } else { ! sprintf(buffer, "P%d", index); ! print_prop(short_name, buffer); ! } ! } else if (strcmp(node->Name(), "IfTrue") == 0) { ! print_prop(short_name, "T"); ! } else if (strcmp(node->Name(), "IfFalse") == 0) { ! print_prop(short_name, "F"); ! } else if ((node->is_Con() && node->is_Type()) || node->is_Proj()) { ! if (t->base() == Type::Int && t->is_int()->is_con()) { ! const TypeInt *typeInt = t->is_int(); ! assert(typeInt->is_con(), "must be constant"); ! jint value = typeInt->get_con(); ! // max. 2 chars allowed ! if (value >= -9 && value <= 99) { ! sprintf(buffer, "%d", value); ! print_prop(short_name, buffer); } else { ! print_prop(short_name, "I"); } + } else if (t == Type::TOP) { + print_prop(short_name, "^"); + } else if (t->base() == Type::Long && t->is_long()->is_con()) { + const TypeLong *typeLong = t->is_long(); + assert(typeLong->is_con(), "must be constant"); + jlong value = typeLong->get_con(); + // max. 2 chars allowed + if (value >= -9 && value <= 99) { + sprintf(buffer, "%d", value); + print_prop(short_name, buffer); } else { ! print_prop(short_name, "L"); } + } else if (t->base() == Type::KlassPtr) { + const TypeKlassPtr *typeKlass = t->is_klassptr(); + print_prop(short_name, "CP"); + } else if (t->base() == Type::Control) { + print_prop(short_name, "C"); + } else if (t->base() == Type::Memory) { + print_prop(short_name, "M"); + } else if (t->base() == Type::Abio) { + print_prop(short_name, "IO"); + } else if (t->base() == Type::Return_Address) { + print_prop(short_name, "RA"); + } else if (t->base() == Type::AnyPtr) { + print_prop(short_name, "P"); + } else if (t->base() == Type::RawPtr) { + print_prop(short_name, "RP"); + } else if (t->base() == Type::AryPtr) { + print_prop(short_name, "AP"); } } ! JVMState* caller = NULL; ! if (node->is_SafePoint()) { ! caller = node->as_SafePoint()->jvms(); } else { ! Node_Notes* notes = C->node_notes_at(node->_idx); ! if (notes != NULL) { ! caller = notes->jvms(); } } ! if (caller != NULL) { ! stringStream bciStream; ! while(caller) { ! bciStream.print("%d ", caller->bci()); ! caller = caller->caller(); } + print_prop("bci", bciStream.as_string()); } ! if (_chaitin && _chaitin != (PhaseChaitin *)0xdeadbeef) { ! buffer[0] = 0; ! _chaitin->dump_register(node, buffer); ! print_prop("reg", buffer); ! print_prop("lrg", _chaitin->n2lidx(node)); } ! node->_in_dump_cnt--; ! #endif ! tail(PROPERTIES_ELEMENT); ! tail(NODE_ELEMENT); } } ! void IdealGraphPrinter::walk_nodes(Node *start, void *param) { + VectorSet visited(Thread::current()->resource_area()); + GrowableArray<Node *> nodeStack(Thread::current()->resource_area(), 0, 0, NULL); + nodeStack.push(start); + visited.test_set(start->_idx); + while(nodeStack.length() > 0) { ! Node *n = nodeStack.pop(); ! visit_node(n, param); ! if (_traverse_outs) { ! for (DUIterator i = n->outs(); n->has_out(i); i++) { ! Node* p = n->out(i); ! if (!visited.test_set(p->_idx)) { ! nodeStack.push(p); } } } ! for ( uint i = 0; i < n->len(); i++ ) { ! if ( n->in(i) ) { ! if (!visited.test_set(n->in(i)->_idx)) { ! nodeStack.push(n->in(i)); } } } } } void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) { print(compile, name, (Node *)compile->root(), level, clear_nodes); } // Print current ideal graph void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) { if (!_current_method || !_should_send_method || level > PrintIdealGraphLevel) return; ! this->C = compile; // Warning, unsafe cast? ! _chaitin = (PhaseChaitin *)C->regalloc(); ! begin_head(GRAPH_ELEMENT); ! print_attr(GRAPH_NAME_PROPERTY, (const char *)name); ! end_head(); ! head(NODES_ELEMENT); ! walk_nodes(node, NULL); ! tail(NODES_ELEMENT); ! head(EDGES_ELEMENT); ! walk_nodes(node, (void *)1); ! tail(EDGES_ELEMENT); ! if (C->cfg() != NULL) { ! head(CONTROL_FLOW_ELEMENT); ! for (uint i = 0; i < C->cfg()->_blocks.size(); i++) { ! Block *b = C->cfg()->_blocks[i]; ! begin_head(BLOCK_ELEMENT); ! print_attr(BLOCK_NAME_PROPERTY, b->_pre_order); ! end_head(); ! head(SUCCESSORS_ELEMENT); ! for (uint s = 0; s < C->cfg()->_blocks[i]->_num_succs; s++) { ! begin_elem(SUCCESSOR_ELEMENT); ! print_attr(BLOCK_NAME_PROPERTY, b->_succs[s]->_pre_order); ! end_elem(); } + tail(SUCCESSORS_ELEMENT); ! tail(BLOCK_ELEMENT); } ! tail(CONTROL_FLOW_ELEMENT); } ! tail(GRAPH_ELEMENT); ! output()->flush(); } extern const char *NodeClassNames[]; outputStream *IdealGraphPrinter::output() { ! return _xml; } #endif