< prev index next >

src/share/vm/opto/node.cpp

Print this page
rev 8739 : 8004073: Implement C2 Ideal node specific dump() method
Summary: add Node::dump_rel() to dump a node and its related nodes (the notion of "related" depends on the node at hand); add Node::dump_comp() to dump a node in compact representation; add Node::dump_rel_comp() to dump a node and its related nodes in compact representation; add the required machinery; extend some C2 IR nodes with compact and related dumping
Reviewed-by:


1472 #endif
1473   return tp;
1474 }
1475 
1476 // Get a double constant from a ConstNode.
1477 // Returns the constant if it is a double ConstNode
1478 jdouble Node::getd() const {
1479   assert( Opcode() == Op_ConD, "" );
1480   return ((ConDNode*)this)->type()->is_double_constant()->getd();
1481 }
1482 
1483 // Get a float constant from a ConstNode.
1484 // Returns the constant if it is a float ConstNode
1485 jfloat Node::getf() const {
1486   assert( Opcode() == Op_ConF, "" );
1487   return ((ConFNode*)this)->type()->is_float_constant()->getf();
1488 }
1489 
1490 #ifndef PRODUCT
1491 
1492 //----------------------------NotANode----------------------------------------
1493 // Used in debugging code to avoid walking across dead or uninitialized edges.
1494 static inline bool NotANode(const Node* n) {
1495   if (n == NULL)                   return true;
1496   if (((intptr_t)n & 1) != 0)      return true;  // uninitialized, etc.
1497   if (*(address*)n == badAddress)  return true;  // kill by Node::destruct
1498   return false;
1499 }
1500 
1501 
1502 //------------------------------find------------------------------------------
1503 // Find a neighbor of this Node with the given _idx
1504 // If idx is negative, find its absolute value, following both _in and _out.
1505 static void find_recur(Compile* C,  Node* &result, Node *n, int idx, bool only_ctrl,
1506                         VectorSet* old_space, VectorSet* new_space ) {
1507   int node_idx = (idx >= 0) ? idx : -idx;
1508   if (NotANode(n))  return;  // Gracefully handle NULL, -1, 0xabababab, etc.
1509   // Contained in new_space or old_space?   Check old_arena first since it's mostly empty.
1510   VectorSet *v = C->old_arena()->contains(n) ? old_space : new_space;
1511   if( v->test(n->_idx) ) return;
1512   if( (int)n->_idx == node_idx
1513       debug_only(|| n->debug_idx() == node_idx) ) {
1514     if (result != NULL)
1515       tty->print("find: " INTPTR_FORMAT " and " INTPTR_FORMAT " both have idx==%d\n",
1516                  (uintptr_t)result, (uintptr_t)n, node_idx);
1517     result = n;
1518   }
1519   v->set(n->_idx);
1520   for( uint i=0; i<n->len(); i++ ) {
1521     if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue;


1619 void Node::set_debug_orig(Node* orig) {
1620   _debug_orig = orig;
1621   if (BreakAtNode == 0)  return;
1622   if (NotANode(orig))  orig = NULL;
1623   int trip = 10;
1624   while (orig != NULL) {
1625     if (orig->debug_idx() == BreakAtNode || (int)orig->_idx == BreakAtNode) {
1626       tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d orig._idx=%d orig._debug_idx=%d",
1627                     this->_idx, this->debug_idx(), orig->_idx, orig->debug_idx());
1628       BREAKPOINT;
1629     }
1630     orig = orig->debug_orig();
1631     if (NotANode(orig))  orig = NULL;
1632     if (trip-- <= 0)  break;
1633   }
1634 }
1635 #endif //ASSERT
1636 
1637 //------------------------------dump------------------------------------------
1638 // Dump a Node
1639 void Node::dump(const char* suffix, outputStream *st) const {
1640   Compile* C = Compile::current();
1641   bool is_new = C->node_arena()->contains(this);
1642   C->_in_dump_cnt++;
1643   st->print("%c%d\t%s\t=== ", is_new ? ' ' : 'o', _idx, Name());
1644 
1645   // Dump the required and precedence inputs
1646   dump_req(st);
1647   dump_prec(st);
1648   // Dump the outputs
1649   dump_out(st);
1650 
1651   if (is_disconnected(this)) {
1652 #ifdef ASSERT
1653     st->print("  [%d]",debug_idx());
1654     dump_orig(debug_orig(), st);
1655 #endif
1656     st->cr();
1657     C->_in_dump_cnt--;
1658     return;                     // don't process dead nodes
1659   }
1660 
1661   if (C->clone_map().value(_idx) != 0) {
1662     C->clone_map().dump(_idx);
1663   }


1743 }
1744 
1745 //------------------------------dump_out--------------------------------------
1746 void Node::dump_out(outputStream *st) const {
1747   // Delimit the output edges
1748   st->print(" [[");
1749   // Dump the output edges
1750   for (uint i = 0; i < _outcnt; i++) {    // For all outputs
1751     Node* u = _out[i];
1752     if (u == NULL) {
1753       st->print("_ ");
1754     } else if (NotANode(u)) {
1755       st->print("NotANode ");
1756     } else {
1757       st->print("%c%d ", Compile::current()->node_arena()->contains(u) ? ' ' : 'o', u->_idx);
1758     }
1759   }
1760   st->print("]] ");
1761 }
1762 
1763 //------------------------------dump_nodes-------------------------------------
1764 static void dump_nodes(const Node* start, int d, bool only_ctrl) {
1765   Node* s = (Node*)start; // remove const
1766   if (NotANode(s)) return;
1767 
1768   uint depth = (uint)ABS(d);
1769   int direction = d;
1770   Compile* C = Compile::current();
1771   GrowableArray <Node *> nstack(C->unique());
1772 
1773   nstack.append(s);





1774   int begin = 0;
1775   int end = 0;
1776   for(uint i = 0; i < depth; i++) {
1777     end = nstack.length();
1778     for(int j = begin; j < end; j++) {
1779       Node* tp  = nstack.at(j);
1780       uint limit = direction > 0 ? tp->len() : tp->outcnt();
1781       for(uint k = 0; k < limit; k++) {
1782         Node* n = direction > 0 ? tp->in(k) : tp->raw_out(k);
1783 
1784         if (NotANode(n))  continue;
1785         // do not recurse through top or the root (would reach unrelated stuff)
1786         if (n->is_Root() || n->is_top())  continue;
1787         if (only_ctrl && !n->is_CFG()) continue;

1788 
1789         bool on_stack = nstack.contains(n);
1790         if (!on_stack) {
1791           nstack.append(n);
1792         }
1793       }
1794     }
1795     begin = end;
1796   }
1797   end = nstack.length();
1798   if (direction > 0) {












1799     for(int j = end-1; j >= 0; j--) {
1800       nstack.at(j)->dump();
1801     }
1802   } else {
1803     for(int j = 0; j < end; j++) {
1804       nstack.at(j)->dump();
1805     }
1806   }
1807 }
1808 
1809 //------------------------------dump-------------------------------------------
1810 void Node::dump(int d) const {
1811   dump_nodes(this, d, false);
1812 }
1813 
1814 //------------------------------dump_ctrl--------------------------------------
1815 // Dump a Node's control history to depth
1816 void Node::dump_ctrl(int d) const {
1817   dump_nodes(this, d, true);
1818 }
1819 












































































































































































































1820 // VERIFICATION CODE
1821 // For each input edge to a node (ie - for each Use-Def edge), verify that
1822 // there is a corresponding Def-Use edge.
1823 //------------------------------verify_edges-----------------------------------
1824 void Node::verify_edges(Unique_Node_List &visited) {
1825   uint i, j, idx;
1826   int  cnt;
1827   Node *n;
1828 
1829   // Recursive termination test
1830   if (visited.member(this))  return;
1831   visited.push(this);
1832 
1833   // Walk over all input edges, checking for correspondence
1834   for( i = 0; i < len(); i++ ) {
1835     n = in(i);
1836     if (n != NULL && !n->is_top()) {
1837       // Count instances of (Node *)this
1838       cnt = 0;
1839       for (idx = 0; idx < n->_outcnt; idx++ ) {


2156 
2157 // Node_Stack is used to map nodes.
2158 Node* Node_Stack::find(uint idx) const {
2159   uint sz = size();
2160   for (uint i=0; i < sz; i++) {
2161     if (idx == index_at(i) )
2162       return node_at(i);
2163   }
2164   return NULL;
2165 }
2166 
2167 //=============================================================================
2168 uint TypeNode::size_of() const { return sizeof(*this); }
2169 #ifndef PRODUCT
2170 void TypeNode::dump_spec(outputStream *st) const {
2171   if( !Verbose && !WizardMode ) {
2172     // standard dump does this in Verbose and WizardMode
2173     st->print(" #"); _type->dump_on(st);
2174   }
2175 }





2176 #endif
2177 uint TypeNode::hash() const {
2178   return Node::hash() + _type->hash();
2179 }
2180 uint TypeNode::cmp( const Node &n ) const
2181 { return !Type::cmp( _type, ((TypeNode&)n)._type ); }
2182 const Type *TypeNode::bottom_type() const { return _type; }
2183 const Type *TypeNode::Value( PhaseTransform * ) const { return _type; }
2184 
2185 //------------------------------ideal_reg--------------------------------------
2186 uint TypeNode::ideal_reg() const {
2187   return _type->ideal_reg();
2188 }


1472 #endif
1473   return tp;
1474 }
1475 
1476 // Get a double constant from a ConstNode.
1477 // Returns the constant if it is a double ConstNode
1478 jdouble Node::getd() const {
1479   assert( Opcode() == Op_ConD, "" );
1480   return ((ConDNode*)this)->type()->is_double_constant()->getd();
1481 }
1482 
1483 // Get a float constant from a ConstNode.
1484 // Returns the constant if it is a float ConstNode
1485 jfloat Node::getf() const {
1486   assert( Opcode() == Op_ConF, "" );
1487   return ((ConFNode*)this)->type()->is_float_constant()->getf();
1488 }
1489 
1490 #ifndef PRODUCT
1491 










1492 //------------------------------find------------------------------------------
1493 // Find a neighbor of this Node with the given _idx
1494 // If idx is negative, find its absolute value, following both _in and _out.
1495 static void find_recur(Compile* C,  Node* &result, Node *n, int idx, bool only_ctrl,
1496                         VectorSet* old_space, VectorSet* new_space ) {
1497   int node_idx = (idx >= 0) ? idx : -idx;
1498   if (NotANode(n))  return;  // Gracefully handle NULL, -1, 0xabababab, etc.
1499   // Contained in new_space or old_space?   Check old_arena first since it's mostly empty.
1500   VectorSet *v = C->old_arena()->contains(n) ? old_space : new_space;
1501   if( v->test(n->_idx) ) return;
1502   if( (int)n->_idx == node_idx
1503       debug_only(|| n->debug_idx() == node_idx) ) {
1504     if (result != NULL)
1505       tty->print("find: " INTPTR_FORMAT " and " INTPTR_FORMAT " both have idx==%d\n",
1506                  (uintptr_t)result, (uintptr_t)n, node_idx);
1507     result = n;
1508   }
1509   v->set(n->_idx);
1510   for( uint i=0; i<n->len(); i++ ) {
1511     if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue;


1609 void Node::set_debug_orig(Node* orig) {
1610   _debug_orig = orig;
1611   if (BreakAtNode == 0)  return;
1612   if (NotANode(orig))  orig = NULL;
1613   int trip = 10;
1614   while (orig != NULL) {
1615     if (orig->debug_idx() == BreakAtNode || (int)orig->_idx == BreakAtNode) {
1616       tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d orig._idx=%d orig._debug_idx=%d",
1617                     this->_idx, this->debug_idx(), orig->_idx, orig->debug_idx());
1618       BREAKPOINT;
1619     }
1620     orig = orig->debug_orig();
1621     if (NotANode(orig))  orig = NULL;
1622     if (trip-- <= 0)  break;
1623   }
1624 }
1625 #endif //ASSERT
1626 
1627 //------------------------------dump------------------------------------------
1628 // Dump a Node
1629 void Node::dump(const char* suffix, bool mark, outputStream *st) const {
1630   Compile* C = Compile::current();
1631   bool is_new = C->node_arena()->contains(this);
1632   C->_in_dump_cnt++;
1633   st->print("%c%d%s\t%s\t=== ", is_new ? ' ' : 'o', _idx, mark ? " >" : "", Name());
1634 
1635   // Dump the required and precedence inputs
1636   dump_req(st);
1637   dump_prec(st);
1638   // Dump the outputs
1639   dump_out(st);
1640 
1641   if (is_disconnected(this)) {
1642 #ifdef ASSERT
1643     st->print("  [%d]",debug_idx());
1644     dump_orig(debug_orig(), st);
1645 #endif
1646     st->cr();
1647     C->_in_dump_cnt--;
1648     return;                     // don't process dead nodes
1649   }
1650 
1651   if (C->clone_map().value(_idx) != 0) {
1652     C->clone_map().dump(_idx);
1653   }


1733 }
1734 
1735 //------------------------------dump_out--------------------------------------
1736 void Node::dump_out(outputStream *st) const {
1737   // Delimit the output edges
1738   st->print(" [[");
1739   // Dump the output edges
1740   for (uint i = 0; i < _outcnt; i++) {    // For all outputs
1741     Node* u = _out[i];
1742     if (u == NULL) {
1743       st->print("_ ");
1744     } else if (NotANode(u)) {
1745       st->print("NotANode ");
1746     } else {
1747       st->print("%c%d ", Compile::current()->node_arena()->contains(u) ? ' ' : 'o', u->_idx);
1748     }
1749   }
1750   st->print("]] ");
1751 }
1752 
1753 //----------------------------collect_nodes_i----------------------------------
1754 // Collects nodes from an Ideal graph, starting from a given start node and
1755 // moving in a given direction until a certain depth (distance from the start
1756 // node) is reached. Duplicates are ignored.
1757 // Arguments:
1758 //   nstack:        the nodes are collected into this array.
1759 //   start:         the node at which to start collecting.
1760 //   direction:     if this is a positive number, collect input nodes; if it is
1761 //                  a negative number, collect output nodes.
1762 //   depth:         collect nodes up to this distance from the start node.
1763 //   include_start: whether to include the start node in the result collection.
1764 //   only_ctrl:     whether to regard control edges only during traversal.
1765 //   only_data:     whether to regard data edges only during traversal.
1766 static void collect_nodes_i(GrowableArray<Node*> *nstack, const Node* start, int direction, uint depth, bool include_start, bool only_ctrl, bool only_data) {
1767   Node* s = (Node*) start; // remove const
1768   nstack->append(s);
1769   int begin = 0;
1770   int end = 0;
1771   for(uint i = 0; i < depth; i++) {
1772     end = nstack->length();
1773     for(int j = begin; j < end; j++) {
1774       Node* tp  = nstack->at(j);
1775       uint limit = direction > 0 ? tp->len() : tp->outcnt();
1776       for(uint k = 0; k < limit; k++) {
1777         Node* n = direction > 0 ? tp->in(k) : tp->raw_out(k);
1778 
1779         if (NotANode(n))  continue;
1780         // do not recurse through top or the root (would reach unrelated stuff)
1781         if (n->is_Root() || n->is_top()) continue;
1782         if (only_ctrl && !n->is_CFG()) continue;
1783         if (only_data && n->is_CFG()) continue;
1784 
1785         bool on_stack = nstack->contains(n);
1786         if (!on_stack) {
1787           nstack->append(n);
1788         }
1789       }
1790     }
1791     begin = end;
1792   }
1793   if (!include_start) {
1794     nstack->remove(s);
1795   }
1796 }
1797 
1798 //------------------------------dump_nodes-------------------------------------
1799 static void dump_nodes(const Node* start, int d, bool only_ctrl) {
1800   if (NotANode(start)) return;
1801 
1802   GrowableArray <Node *> nstack(Compile::current()->unique());
1803   collect_nodes_i(&nstack, start, d, (uint) ABS(d), true, only_ctrl, false);
1804 
1805   int end = nstack.length();
1806   if (d > 0) {
1807     for(int j = end-1; j >= 0; j--) {
1808       nstack.at(j)->dump();
1809     }
1810   } else {
1811     for(int j = 0; j < end; j++) {
1812       nstack.at(j)->dump();
1813     }
1814   }
1815 }
1816 
1817 //------------------------------dump-------------------------------------------
1818 void Node::dump(int d) const {
1819   dump_nodes(this, d, false);
1820 }
1821 
1822 //------------------------------dump_ctrl--------------------------------------
1823 // Dump a Node's control history to depth
1824 void Node::dump_ctrl(int d) const {
1825   dump_nodes(this, d, true);
1826 }
1827 
1828 //------------------------------dump_comp--------------------------------------
1829 void Node::dump_comp() const {
1830   this->dump_comp("\n");
1831 }
1832 
1833 //------------------------------dump_comp--------------------------------------
1834 // Dump a Node in compact representation, i.e., just print its name and index.
1835 // Nodes can specify additional specifics to print in compact representation by
1836 // implementing dump_compact_spec.
1837 void Node::dump_comp(const char* suffix, outputStream *st) const {
1838   Compile* C = Compile::current();
1839   C->_in_dump_cnt++;
1840   st->print("%s(%d)", Name(), _idx);
1841   this->dump_comp_spec(st);
1842   if (suffix) {
1843     st->print("%s", suffix);
1844   }
1845   C->_in_dump_cnt--;
1846 }
1847 
1848 //------------------------------dump_rel---------------------------------------
1849 // Dump a Node's related nodes - the notion of "related" depends on the Node at
1850 // hand and is determined by the implementation of the virtual method rel.
1851 void Node::dump_rel() const {
1852   Compile* C = Compile::current();
1853   GrowableArray <Node *> in_rel(C->unique());
1854   GrowableArray <Node *> out_rel(C->unique());
1855   this->rel(&in_rel, &out_rel, false);
1856   for (int i = in_rel.length() - 1; i >= 0; i--) {
1857     in_rel.at(i)->dump();
1858   }
1859   this->dump("\n", true);
1860   for (int i = 0; i < out_rel.length(); i++) {
1861     out_rel.at(i)->dump();
1862   }
1863 }
1864 
1865 //------------------------------dump_rel---------------------------------------
1866 // Dump a Node's related nodes up to a given depth (distance from the start
1867 // node).
1868 // Arguments:
1869 //   d_in:  depth for input nodes.
1870 //   d_out: depth for output nodes (note: this also is a positive number).
1871 void Node::dump_rel(uint d_in, uint d_out) const {
1872   Compile* C = Compile::current();
1873   GrowableArray <Node *> in_rel(C->unique());
1874   GrowableArray <Node *> out_rel(C->unique());
1875 
1876   // call collect_nodes_i directly
1877   collect_nodes_i(&in_rel, this, 1, d_in, false, false, false);
1878   collect_nodes_i(&out_rel, this, -1, d_out, false, false, false);
1879 
1880   for (int i = in_rel.length() - 1; i >= 0; i--) {
1881     in_rel.at(i)->dump();
1882   }
1883   this->dump("\n", true);
1884   for (int i = 0; i < out_rel.length(); i++) {
1885     out_rel.at(i)->dump();
1886   }
1887 }
1888 
1889 //---------------------------dump_rel_comp-------------------------------------
1890 // Dump a Node's related nodes in compact representation. The notion of
1891 // "related" depends on the Node at hand and is determined by the implementation
1892 // of the virtual method rel.
1893 void Node::dump_rel_comp() const {
1894   Compile* C = Compile::current();
1895   GrowableArray <Node *> in_rel(C->unique());
1896   GrowableArray <Node *> out_rel(C->unique());
1897   this->rel(&in_rel, &out_rel, true);
1898   int n_in = in_rel.length();
1899   int n_out = out_rel.length();
1900 
1901   this->dump_comp(n_in == 0 ? "\n" : "  ");
1902   for (int i = 0; i < n_in; i++) {
1903     in_rel.at(i)->dump_comp(i == n_in - 1 ? "\n" : "  ");
1904   }
1905   for (int i = 0; i < n_out; i++) {
1906     out_rel.at(i)->dump_comp(i == n_out - 1 ? "\n" : "  ");
1907   }
1908 }
1909 
1910 //--------------------------------rel------------------------------------------
1911 // Collect a Node's related nodes. The default behaviour just collects the
1912 // inputs and outputs at depth 1, including both control and data flow edges,
1913 // regardless of whether the presentation is compact or not.
1914 void Node::rel(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const {
1915   collect_nodes_i(in_rel, this, 1, 1, false, false, false);
1916   collect_nodes_i(out_rel, this, -1, 1, false, false, false);
1917 }
1918 
1919 //---------------------------collect_nodes-------------------------------------
1920 // An entry point to the low-level node collection facility, to start from a
1921 // given node in the graph. The start node is by default not included in the
1922 // result.
1923 // Arguments:
1924 //   ns:   collect the nodes into this data structure.
1925 //   d:    the depth (distance from start node) to which nodes should be
1926 //         collected. A value >0 indicates input nodes, a value <0, output
1927 //         nodes.
1928 //   ctrl: include only control nodes.
1929 //   data: include only data nodes.
1930 void Node::collect_nodes(GrowableArray<Node*> *ns, int d, bool ctrl, bool data) const {
1931   if (ctrl && data) {
1932     // ignore nonsensical combination
1933     return;
1934   }
1935   collect_nodes_i(ns, this, d, (uint) ABS(d), false, ctrl, data);
1936 }
1937 
1938 //--------------------------collect_nodes_in-----------------------------------
1939 static void collect_nodes_in(Node* start, GrowableArray<Node*> *ns, bool primary_is_data, bool collect_secondary) {
1940   // The maximum depth is determined using a BFS that visits all primary (data
1941   // or control) inputs and increments the depth at each level.
1942   uint d_in = 0;
1943   GrowableArray<Node*> nodes(Compile::current()->unique());
1944   nodes.push(start);
1945   int nodes_at_current_level = 1;
1946   int n_idx = 0;
1947   while (nodes_at_current_level > 0) {
1948     // Add all primary inputs reachable from the current level to the list, and
1949     // increase the depth if there were any.
1950     int nodes_at_next_level = 0;
1951     bool nodes_added = false;
1952     while (nodes_at_current_level > 0) {
1953       nodes_at_current_level--;
1954       Node* current = nodes.at(n_idx++);
1955       for (uint i = 0; i < current->len(); i++) {
1956         Node* n = current->in(i);
1957         if (NotANode(n)) {
1958           continue;
1959         }
1960         if ((primary_is_data && n->is_CFG()) || (!primary_is_data && !n->is_CFG())) {
1961           continue;
1962         }
1963         if (!nodes.contains(n)) {
1964           nodes.push(n);
1965           nodes_added = true;
1966           nodes_at_next_level++;
1967         }
1968       }
1969     }
1970     if (nodes_added) {
1971       d_in++;
1972     }
1973     nodes_at_current_level = nodes_at_next_level;
1974   }
1975   start->collect_nodes(ns, d_in, !primary_is_data, primary_is_data);
1976   if (collect_secondary) {
1977     // Now, iterate over the secondary nodes in ns and add the respective
1978     // boundary reachable from them.
1979     GrowableArray<Node*> sns(Compile::current()->unique());
1980     for (GrowableArrayIterator<Node*> it = ns->begin(); it != ns->end(); ++it) {
1981       Node* n = *it;
1982       n->collect_nodes(&sns, 1, primary_is_data, !primary_is_data);
1983       for (GrowableArrayIterator<Node*> d = sns.begin(); d != sns.end(); ++d) {
1984         ns->append_if_missing(*d);
1985       }
1986       sns.clear();
1987     }
1988   }
1989 }
1990 
1991 //---------------------collect_nodes_in_all_data-------------------------------
1992 // Collect the entire data input graph. Include the control boundary if
1993 // requested.
1994 // Arguments:
1995 //   ns:   collect the nodes into this data structure.
1996 //   ctrl: if true, include the control boundary.
1997 void Node::collect_nodes_in_all_data(GrowableArray<Node*> *ns, bool ctrl) const {
1998   collect_nodes_in((Node*) this, ns, true, ctrl);
1999 }
2000 
2001 //--------------------------collect_nodes_in_all_ctrl--------------------------
2002 // Collect the entire control input graph. Include the data boundary if
2003 // requested.
2004 //   ns:   collect the nodes into this data structure.
2005 //   data: if true, include the control boundary.
2006 void Node::collect_nodes_in_all_ctrl(GrowableArray<Node*> *ns, bool data) const {
2007   collect_nodes_in((Node*) this, ns, false, data);
2008 }
2009 
2010 //------------------collect_nodes_out_all_ctrl_boundary------------------------
2011 // Collect the entire output graph until hitting control node boundaries, and
2012 // include those.
2013 void Node::collect_nodes_out_all_ctrl_boundary(GrowableArray<Node*> *ns) const {
2014   // Perform a BFS and stop at control nodes.
2015   GrowableArray<Node*> nodes(Compile::current()->unique());
2016   nodes.push((Node*) this);
2017   while (nodes.length() > 0) {
2018     Node* current = nodes.pop();
2019     if (NotANode(current)) {
2020       continue;
2021     }
2022     ns->append_if_missing(current);
2023     if (!current->is_CFG()) {
2024       for (DUIterator i = current->outs(); current->has_out(i); i++) {
2025         nodes.push(current->out(i));
2026       }
2027     }
2028   }
2029   ns->remove((Node*) this);
2030 }
2031 
2032 // VERIFICATION CODE
2033 // For each input edge to a node (ie - for each Use-Def edge), verify that
2034 // there is a corresponding Def-Use edge.
2035 //------------------------------verify_edges-----------------------------------
2036 void Node::verify_edges(Unique_Node_List &visited) {
2037   uint i, j, idx;
2038   int  cnt;
2039   Node *n;
2040 
2041   // Recursive termination test
2042   if (visited.member(this))  return;
2043   visited.push(this);
2044 
2045   // Walk over all input edges, checking for correspondence
2046   for( i = 0; i < len(); i++ ) {
2047     n = in(i);
2048     if (n != NULL && !n->is_top()) {
2049       // Count instances of (Node *)this
2050       cnt = 0;
2051       for (idx = 0; idx < n->_outcnt; idx++ ) {


2368 
2369 // Node_Stack is used to map nodes.
2370 Node* Node_Stack::find(uint idx) const {
2371   uint sz = size();
2372   for (uint i=0; i < sz; i++) {
2373     if (idx == index_at(i) )
2374       return node_at(i);
2375   }
2376   return NULL;
2377 }
2378 
2379 //=============================================================================
2380 uint TypeNode::size_of() const { return sizeof(*this); }
2381 #ifndef PRODUCT
2382 void TypeNode::dump_spec(outputStream *st) const {
2383   if( !Verbose && !WizardMode ) {
2384     // standard dump does this in Verbose and WizardMode
2385     st->print(" #"); _type->dump_on(st);
2386   }
2387 }
2388 
2389 void TypeNode::dump_comp_spec(outputStream *st) const {
2390   st->print("#");
2391   _type->dump_on(st);
2392 }
2393 #endif
2394 uint TypeNode::hash() const {
2395   return Node::hash() + _type->hash();
2396 }
2397 uint TypeNode::cmp( const Node &n ) const
2398 { return !Type::cmp( _type, ((TypeNode&)n)._type ); }
2399 const Type *TypeNode::bottom_type() const { return _type; }
2400 const Type *TypeNode::Value( PhaseTransform * ) const { return _type; }
2401 
2402 //------------------------------ideal_reg--------------------------------------
2403 uint TypeNode::ideal_reg() const {
2404   return _type->ideal_reg();
2405 }
< prev index next >