node.cpp revision 4321
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "libadt/vectset.hpp"
#include "memory/allocation.inline.hpp"
#include "opto/cfgnode.hpp"
#include "opto/connode.hpp"
#include "opto/machnode.hpp"
#include "opto/matcher.hpp"
#include "opto/opcodes.hpp"
#include "opto/regmask.hpp"
class RegMask;
// #include "phase.hpp"
class PhaseTransform;
class PhaseGVN;
// Arena we are currently building Nodes in
#ifndef PRODUCT
extern int nodes_created;
#endif
#ifdef ASSERT
//-------------------------- construct_node------------------------------------
// Set a breakpoint here to identify where a particular node index is built.
void Node::verify_construction() {
_debug_orig = NULL;
if (new_debug_idx > 0) {
// Arrange that the lowest five decimal digits of _debug_idx
// will repeat those of _idx. In case this is somehow pathological,
// we continue to assign negative numbers (!) consecutively.
const int mod = 100000;
new_debug_idx += bump;
}
}
_del_tick = 0;
#endif
_hash_lock = 0;
}
// #ifdef ASSERT ...
}
}
void DUIterator_Common::verify_resync() {
// Ensure that the loop body has just deleted the last guy produced.
// Ensure that at least one copy of the last-seen edge was deleted.
// Note: It is OK to delete multiple copies of the last-seen edge.
// Unfortunately, we have no way to verify that all the deletions delete
// that same edge. On this point we must use the Honor System.
// We liked this deletion, so accept the resulting outcnt and tick.
}
if (this == &that) return; // ignore assignment to self
if (!_vdui) {
// We need to initialize everything, overwriting garbage values.
}
// Note: It is legal (though odd) for an iterator over some node x
// to be reassigned to iterate over another node y. Some doubly-nested
// progress loops depend on being able to do this.
// Re-initialize everything, except _last.
}
_refresh_tick = 0; // No refreshes have happened, as yet.
}
}
void DUIterator::verify_increment() {
if (_refresh_tick & 1) {
// We have refreshed the index during this loop.
// Fix up _idx to meet asserts.
}
}
void DUIterator::verify_resync() {
// Note: We do not assert on _outcnt, because insertions are OK here.
// Make sure we are still in sync, possibly with no more out-edges:
}
if (this == &that) return; // self assignment is always a no-op
if (!_vdui) {
// We need to initialize everything, overwriting garbage values.
} else {
if (_refresh_tick & 1) {
_refresh_tick++; // Clear the "was refreshed" flag.
}
}
}
void DUIterator::refresh() {
}
void DUIterator::verify_finish() {
// If the loop has killed the node, do not require it to re-run.
// If this assert triggers, it means that a loop used refresh_out_pos
// to re-synch an iteration index, but the loop did not correctly
// re-run itself, using a "while (progress)" construct.
// This iterator enforces the rule that you must keep trying the loop
// until it "runs clean" without any need for refreshing.
}
// This last check is carefully designed to work for NO_OUT_ARRAY.
}
void DUIterator_Fast::verify_limit() {
}
void DUIterator_Fast::verify_resync() {
// Note that the limit imax, not the pointer i, gets updated with the
// exact count of deletions. (For the pointer it's always "--i".)
assert(node->_outcnt+node->_del_tick == _outcnt+_del_tick, "no insertions allowed with deletion(s)");
// This is a limit pointer, with a name like "imax".
// Fudge the _last field so that the common assert will be happy.
} else {
// A normal internal pointer.
// Make sure we are still in sync, possibly with no more out-edges:
}
}
assert((int)n > 0, "use imax -= n only with a positive count");
// This must be a limit pointer, with a name like "imax".
// The reported number of deletions must match what the node saw.
// Fudge the _last field so that the common assert will be happy.
}
}
// at_end_ok means the _outp is allowed to underflow by 1
}
void DUIterator_Last::verify_limit() {
// Do not require the limit address to be resynched.
//verify(node, true);
}
// Make sure we are still in sync, possibly with no more out-edges:
}
#endif //OPTO_DU_ITERATOR_ASSERT
#endif //ASSERT
// This constant used to initialize _out may be any non-null value.
// The value NULL is reserved for the top node only.
// This funny expression handshakes with Node::operator new
// to pull Compile::current out of the new node's _out field,
// and then calls a subroutine which manages most field
// initializations. The only one which is tricky is the
// _idx field, which is const, and so must be initialized
// by a return value, not an assignment.
//
// (Aren't you thankful that Java finals don't require so many tricks?)
#ifdef _MSC_VER // the IDX_INIT hack falls foul of warning C4355
#endif
// Out-of-line code from node constructors.
// Executed only when extra debug info. is being passed around.
}
// Shared initialization code.
int idx = C->next_unique();
// Allocate memory for the necessary number of edges.
if (req > 0) {
// Allocate space for _in array to have double alignment.
#ifdef ASSERT
#endif
}
// If there are default notes floating around, capture them:
// Note: At this point, C is dead,
// and we begin to initialize the new Node.
_flags = 0;
_out = NO_OUT_ARRAY;
return idx;
}
//------------------------------Node-------------------------------------------
// Create a Node, with a given number of required edges.
{
if (req == 0) {
} else {
}
}
}
//------------------------------Node-------------------------------------------
{
// Assert we allocated space for input array already
}
//------------------------------Node-------------------------------------------
{
// Assert we allocated space for input array already
}
//------------------------------Node-------------------------------------------
{
// Assert we allocated space for input array already
}
//------------------------------Node-------------------------------------------
{
// Assert we allocated space for input array already
}
//------------------------------Node-------------------------------------------
{
// Assert we allocated space for input array already
}
//------------------------------Node-------------------------------------------
{
// Assert we allocated space for input array already
}
//------------------------------Node-------------------------------------------
{
// Assert we allocated space for input array already
}
//------------------------------clone------------------------------------------
// Clone a Node.
// Set the new input pointer array
// Cannot share the old output pointer array, so kill it
n->_out = NO_OUT_ARRAY;
// And reset the counters to 0
n->_outcnt = 0;
n->_outmax = 0;
// Unlock this guy, since he is not in any hash table.
debug_only(n->_hash_lock = 0);
// Walk the old node's input list to duplicate its edges
uint i;
for( i = 0; i < len(); i++ ) {
n->_in[i] = x;
}
if (is_macro())
compile->add_macro_node(n);
if (is_expensive())
debug_only( n->verify_construction() );
// Do not patch over the debug_idx of a clone, because it makes it
// impossible to break on the clone's moment of creation.
//debug_only( n->set_debug_idx( debug_idx() ) );
// MachNode clone
// Get address of _opnd_array.
// It should be the same offset since it is the clone of this node.
pointer_delta((const void*)from,
}
}
// cloning CallNode may need to clone JVMState
if (n->is_Call()) {
call->clone_jvms();
}
return n; // Return the clone
}
//---------------------------setup_is_top--------------------------------------
// Call this when changing the top node, to reassert the invariants
// required by Node::is_top. See Compile::set_cached_top_node.
void Node::setup_is_top() {
// This node has just become top. Kill its out array.
} else {
}
}
//------------------------------~Node------------------------------------------
// Fancy destructor; eagerly attempt to reclaim Node numberings and storage
extern int reclaim_idx ;
extern int reclaim_in ;
extern int reclaim_node;
// Eagerly reclaim unique Node numberings
#ifdef ASSERT
reclaim_idx++;
#endif
}
// Clear debug info:
// Walk the input array, freeing the corresponding output edges
uint i;
for( i = 0; i < _max; i++ ) {
//assert(def->out(def->outcnt()-1) == (Node *)this,"bad def-use hacking in reclaim");
}
// See if the input array was allocated just prior to the object
int out_edge_size = _outmax*sizeof(void*);
// Free the output edge array
if (out_edge_size > 0) {
#ifdef ASSERT
#endif
}
// Free the input edge array and the node itself
if( edge_end == (char*)this ) {
#ifdef ASSERT
reclaim_in += edge_size;
}
#else
// It was; free the input array and object all in one hit
#endif
} else {
// Free just the input array
#ifdef ASSERT
reclaim_in += edge_size;
#endif
// Free just the object
#ifdef ASSERT
#else
#endif
}
if (is_macro()) {
compile->remove_macro_node(this);
}
if (is_expensive()) {
compile->remove_expensive_node(this);
}
#ifdef ASSERT
// We will not actually delete the storage, but we'll make the node unusable.
#endif
}
//------------------------------grow-------------------------------------------
// Grow the input array, making space for more edges
if( new_max == 0 ) {
_max = 4;
return;
}
// Trimming to limit allows a uint8 to handle up to 255 edges.
// Previously I was using only powers-of-2 which peaked at 128 edges.
//if( new_max >= limit ) new_max = limit-1;
// This assertion makes sure that Node::_max is wide enough to
// represent the numerical value of new_max.
}
//-----------------------------out_grow----------------------------------------
// Grow the input array, making space for more edges
if( new_max == 0 ) {
_outmax = 4;
return;
}
// Trimming to limit allows a uint8 to handle up to 255 edges.
// Previously I was using only powers-of-2 which peaked at 128 edges.
//if( new_max >= limit ) new_max = limit-1;
//Copy::zero_to_bytes(&_out[_outmax], (new_max-_outmax)*sizeof(Node*)); // NULL all new space
// This assertion makes sure that Node::_max is wide enough to
// represent the numerical value of new_max.
}
#ifdef ASSERT
//------------------------------is_dead----------------------------------------
// Mach and pinch point nodes may look like dead.
return false;
return false;
dump();
return true;
}
#endif
//------------------------------is_unreachable---------------------------------
}
//------------------------------add_req----------------------------------------
// Add a new required input at the end
// Look to see if I can move precedence down one without reallocating
// Find a precedence edge to move
uint i;
break; // There must be one, since we grew the array
}
}
//---------------------------add_req_batch-------------------------------------
// Add a new required input at the end
// check various edge cases
if ((int)m <= 1) {
assert((int)m >= 0, "oob");
if (m != 0) add_req(n);
return;
}
// Look to see if I can move precedence down one without reallocating
// Find a precedence edge to move
uint i;
break; // There must be one, since we grew the array
// Slide all the precs over by m positions (assume #prec << m).
Copy::conjoint_words_to_higher((HeapWord*)&_in[_cnt], (HeapWord*)&_in[_cnt+m], ((i-_cnt)*sizeof(Node*)));
}
// Stuff over the old prec edges
for(uint i=0; i<m; i++ ) {
}
// Insert multiple out edges on the node.
for(uint i=0; i<m; i++ ) {
}
}
}
//------------------------------del_req----------------------------------------
// Delete the required edge and compact the edge array
"remove node from hash table before modifying it");
// First remove corresponding def-use edge
}
//------------------------------ins_req----------------------------------------
// Insert a new required input at the end
// Slide over
Copy::conjoint_words_to_higher((HeapWord*)&_in[idx], (HeapWord*)&_in[idx+1], ((_cnt-idx-1)*sizeof(Node*)));
}
}
//-----------------------------find_edge---------------------------------------
if (_in[i] == n) return i;
}
return -1;
}
//----------------------------replace_edge-------------------------------------
if (i < req())
else
nrep++;
}
}
return nrep;
}
//-------------------------disconnect_inputs-----------------------------------
// NULL out all inputs to eliminate incoming Def-Use edges.
// Return the number of edges between 'n' and 'this'
int edges_to_n = 0;
if( in(i) == 0 ) continue;
if( in(i) == n ) ++edges_to_n;
}
// Remove precedence edges if any exist
// Note: Safepoints may have precedence edges, even during parsing
if( in(i) == 0 ) continue;
if( in(i) == n ) ++edges_to_n;
}
}
// Node::destruct requires all out edges be deleted first
// debug_only(destruct();) // no reuse benefit expected
if (edges_to_n == 0) {
C->record_dead_node(_idx);
}
return edges_to_n;
}
//-----------------------------uncast---------------------------------------
// %%% Temporary, until we sort out CheckCastPP vs. CastPP.
// Strip away casting. (It is depth-limited.)
// Should be inline:
//return is_ConstraintCast() ? uncast_helper(this) : (Node*) this;
if (is_ConstraintCast() || is_CheckCastPP())
return uncast_helper(this);
else
return (Node*) this;
}
//---------------------------uncast_helper-------------------------------------
#ifdef ASSERT
uint depth_count = 0;
#endif
while (true) {
#ifdef ASSERT
if (depth_count >= K) {
if (p != orig_p)
p->dump(1);
}
#endif
break;
} else if (p->is_ConstraintCast()) {
p = p->in(1);
} else if (p->is_CheckCastPP()) {
p = p->in(1);
} else {
break;
}
}
return (Node*) p;
}
//------------------------------add_prec---------------------------------------
// Add a new precedence input. Precedence inputs are unordered, with
// duplicates removed and NULLs packed down at the end.
// Check for NULL at end
// Find a precedence edge to move
_in[i] = n; // Stuff prec edge over NULL
}
//------------------------------rm_prec----------------------------------------
// Remove a precedence input. Precedence inputs are unordered, with
// duplicates removed and NULLs packed down at the end.
// Find end of precedence list to pack NULLs
uint i;
for( i=j; i<_max; i++ )
if( !_in[i] ) // Find the NULL at end of prec edge list
break;
}
//------------------------------size_of----------------------------------------
//------------------------------ideal_reg--------------------------------------
//------------------------------jvms-------------------------------------------
#ifdef ASSERT
//------------------------------jvms-------------------------------------------
if (jvms == using_jvms) return true;
}
return false;
}
//------------------------------init_NodeProperty------------------------------
void Node::init_NodeProperty() {
}
#endif
//------------------------------format-----------------------------------------
// Print as assembly
//------------------------------emit-------------------------------------------
// Emit bytes starting at parameter 'ptr'.
//------------------------------size-------------------------------------------
// Size of instruction in bytes
//------------------------------CFG Construction-------------------------------
// Goto and Return.
// Minimum guaranteed type
//------------------------------raise_bottom_type------------------------------
// Get the worst-case Type output for this Node.
if (is_Type()) {
if (VerifyAliases) {
}
} else if (is_Load()) {
if (VerifyAliases) {
}
}
}
//------------------------------Identity---------------------------------------
// Return a node that the given node is equivalent to.
return this; // Default to no identities
}
//------------------------------Value------------------------------------------
// Compute a new Type for a node using the Type of the inputs.
return bottom_type(); // Default to worst-case Type
}
//------------------------------Ideal------------------------------------------
//
// 'Idealize' the graph rooted at this Node.
//
// In order to be efficient and flexible there are some subtle invariants
// these Ideal calls need to hold. Running with '+VerifyIterativeGVN' checks
// these invariants, although its too slow to have on by default. If you are
// hacking an Ideal call, be sure to test with +VerifyIterativeGVN!
//
// The Ideal call almost arbitrarily reshape the graph rooted at the 'this'
// pointer. If ANY change is made, it must return the root of the reshaped
// graph - even if the root is the same Node. Example: swapping the inputs
// to an AddINode gives the same answer and same root, but you still have to
// return the 'this' pointer instead of NULL.
//
// You cannot return an OLD Node, except for the 'this' pointer. Use the
// Identity call to return an old Node; basically if Identity can find
// another Node have the Ideal call make no change and return NULL.
// Example: AddINode::Ideal must check for add of zero; in this case it
// returns NULL instead of doing any graph reshaping.
//
// You cannot modify any old Nodes except for the 'this' pointer. Due to
// sharing there may be other users of the old Nodes relying on their current
// semantics. Modifying them will break the other users.
// Example: when reshape "(X+3)+4" into "X+7" you must leave the Node for
// "X+3" unchanged in case it is shared.
//
// If you modify the 'this' pointer's inputs, you should use
// 'set_req'. If you are making a new Node (either as the new root or
// some new internal piece) you may use 'init_req' to set the initial
// value. You can make a new Node with either 'new' or 'clone'. In
// either case, def-use info is correctly maintained.
//
// Example: reshape "(X+3)+4" into "X+7":
// set_req(1, in(1)->in(1));
// set_req(2, phase->intcon(7));
// return this;
// Example: reshape "X*4" into "X<<2"
// return new (C) LShiftINode(in(1), phase->intcon(2));
//
// You must call 'phase->transform(X)' on any new Nodes X you make, except
// for the returned root node. Example: reshape "X*31" with "(X<<5)-X".
// Node *shift=phase->transform(new(C)LShiftINode(in(1),phase->intcon(5)));
// return new (C) AddINode(shift, in(1));
//
// When making a Node for a constant use 'phase->makecon' or 'phase->intcon'.
// These forms are faster than 'phase->transform(new (C) ConNode())' and Do
// The Right Thing with def-use info.
//
// You cannot bury the 'this' Node inside of a graph reshape. If the reshaped
// graph uses the 'this' Node it must be the root. If you want a Node with
// the same Opcode as the 'this' pointer use 'clone'.
//
return NULL; // Default to being Ideal already
}
// Some nodes have specific Ideal subgraph transformations only if they are
// unique users of specific nodes. Such nodes should be put on IGVN worklist
// for the transformations to happen.
bool Node::has_special_unique_user() const {
Node* n = unique_out();
if( this->is_Store() ) {
// Condition for back-to-back stores folding.
// Condition for convL2I(addL(x,y)) ==> addI(convL2I(x),convL2I(y))
// Condition for subI(x,subI(y,z)) ==> subI(addI(x,z),y)
}
return false;
};
//--------------------------find_exact_control---------------------------------
// Skip Proj and CatchProj nodes chains. Check for Null and Top.
}
return ctrl;
}
//--------------------------dominates------------------------------------------
// Helper function for MemNode::all_controls_dominate().
// Check if 'this' control node dominates or equal to 'sub' control node.
// We already know that if any path back to Root or Start reaches 'this',
// then all paths so, so this is a simple search for one example,
// not an exhaustive search for a counterexample.
// detect dead cycle without regions
bool met_dom = false;
// Walk 'sub' backward up the chain to 'dom', watching for regions.
// After seeing 'dom', continue up to Root or Start.
// If we hit a region (backward split point), it may be a loop head.
// Keep going through one of the region's inputs. If we reach the
// same region again, go through a different input. Eventually we
// will either exit through the loop head, or give up.
// (If we get confused, break out and return a conservative 'false'.)
// No Region nodes except loops were visited before and the EntryControl
// path was taken for loops: it did not walk in a cycle.
return true;
} else if (met_dom) {
break; // already met before: walk in a cycle
} else {
// Region nodes were visited. Continue walk up to Start or Root
// to make sure that it did not walk in a cycle.
met_dom = true; // first time meet
}
}
// Success if we met 'dom' along a path to Start or Root.
// We assume there are no alternative paths that avoid 'dom'.
// (This assumption is up to the caller to ensure!)
return met_dom;
}
// Normalize simple pass-through regions and projections:
// If sub == up, we found a self-loop. Try to push past it.
// Take loop entry path on the way up to 'dom'.
// Always take in(1) path on the way up to 'dom' for clone regions
// (with only one input) or regions which merge > 2 paths
// Try both paths for Regions with 2 input paths (it may be a loop head).
// It could give conservative 'false' answer without information
// which region's input is the entry path.
bool region_was_visited_before = false;
// Was this Region node visited before?
// If so, we have reached it because we accidentally took a
// loop-back edge from 'sub' back into the body of the loop,
// and worked our way up again to the loop header 'sub'.
// So, take the first unexplored path on the way up to 'dom'.
if (visited_twice_already) {
// Visited 2 paths, but still stuck in loop body. Give up.
return false;
}
// The Region node was visited before only once.
// (We will repush with the low bit set, below.)
// We will find a new edge and re-insert.
region_was_visited_before = true;
break;
}
}
// Find an incoming edge which has not been seen yet; walk through it.
if (skip == 0) {
break;
}
--skip; // skip this nontrivial input
}
}
// Set 0 bit to indicate that both paths were taken.
}
break; // some kind of tight cycle
}
// returned back after visiting 'dom'
break; // some kind of cycle
}
if (--iterations_without_region_limit < 0) {
break; // dead cycle
}
}
// Did not meet Root or Start node in pred. chain.
// Conservative answer for dead code.
return false;
}
//------------------------------remove_dead_region-----------------------------
// This control node is dead. Follow the subgraph below it making everything
// using it dead as well. This will happen normally via the usual IterGVN
// worklist but this call is more efficient. Do not update use-def info
// inside the dead region, just at the borders.
// Con's are a popular node to re-hit in the hash table again.
// Can't put ResourceMark here since igvn->_worklist uses the same arena
// Keep dead node on stack until all uses are processed.
// For all Users of the Dead... ;-)
} else { // Else found a not-dead user
}
}
}
// Refresh the iterator, since any number of kills might have happened.
}
} else { // (dead->outcnt() == 0)
// Done with outputs.
}
if (dead->is_expensive()) {
}
// Kill all inputs to the dead guy
if (n->outcnt() == 0) { // Input also goes dead?
if (!n->is_Con())
} else if (n->outcnt() == 1 &&
n->has_special_unique_user()) {
igvn->add_users_to_worklist( n );
// Push store's uses on worklist to enable folding optimization for
// The restriction (outcnt() <= 2) is the same as in set_req_X()
// and remove_globally_dead_node().
igvn->add_users_to_worklist( n );
}
}
}
} // (dead->outcnt() == 0)
} // while (nstack.size() > 0) for outputs
return;
}
//------------------------------remove_dead_region-----------------------------
if( !n ) return false;
// Lost control into this guy? I.e., it became unreachable?
// Aggressively kill all unreachable code.
if (can_reshape && n->is_top()) {
return false; // Node is dead.
}
Node *m = n->nonnull_req();
set_req(0, m);
return true;
}
return false;
}
//------------------------------Ideal_DU_postCCP-------------------------------
// Idealize graph, using DU info. Must clone result into new-space
return NULL; // Default to no change
}
//------------------------------hash-------------------------------------------
// Hash function over Nodes.
}
//------------------------------cmp--------------------------------------------
// Compare special parts of simple Nodes
return 1; // Must be same
}
//------------------------------rematerialize-----------------------------------
// Should we clone rather than spill this instruction?
bool Node::rematerialize() const {
if ( is_Mach() )
return this->as_Mach()->rematerialize();
else
return (_flags & Flag_rematerialize) != 0;
}
//------------------------------needs_anti_dependence_check---------------------
// Nodes which use memory without consuming it, hence need antidependences.
bool Node::needs_anti_dependence_check() const {
return false;
else
}
// Get an integer constant from a ConNode (or CastIINode).
// Return a default value if there is no apparent constant here.
if (this->is_Type()) {
} else if (this->is_Con()) {
return this->bottom_type()->isa_int();
}
return NULL;
}
// Get a pointer constant from a ConstNode.
// Returns the constant if it is a pointer ConstNode
}
// Get a narrow oop constant from a ConNNode.
}
// Get a long constant from a ConNode.
// Return a default value if there is no apparent constant here.
if (this->is_Type()) {
} else if (this->is_Con()) {
return this->bottom_type()->isa_long();
}
return NULL;
}
// Get a double constant from a ConstNode.
// Returns the constant if it is a double ConstNode
}
// Get a float constant from a ConstNode.
// Returns the constant if it is a float ConstNode
}
#ifndef PRODUCT
//----------------------------NotANode----------------------------------------
// Used in debugging code to avoid walking across dead or uninitialized edges.
if (n == NULL) return true;
return false;
}
//------------------------------find------------------------------------------
// Find a neighbor of this Node with the given _idx
// If idx is negative, find its absolute value, following both _in and _out.
if (NotANode(n)) return; // Gracefully handle NULL, -1, 0xabababab, etc.
// Contained in new_space or old_space? Check old_arena first since it's mostly empty.
result = n;
}
if( only_ctrl && !(n->is_Region()) && (n->Opcode() != Op_Root) && (i != TypeFunc::Control) ) continue;
}
// Search along forward edges also:
}
}
#ifdef ASSERT
// Search along debug_orig edges last, checking for cycles
do {
}
#endif //ASSERT
}
// call this from debugger:
}
//------------------------------find-------------------------------------------
return result;
}
//------------------------------find_ctrl--------------------------------------
// Find an ancestor to this node in the control history with given _idx
return result;
}
#endif
#ifndef PRODUCT
int Node::_in_dump_cnt = 0;
// -----------------------------Name-------------------------------------------
extern const char *NodeClassNames[];
static bool is_disconnected(const Node* n) {
}
return true;
}
#ifdef ASSERT
// Step fast twice for each single step of orig:
}
break;
}
}
}
}
_debug_orig = orig;
if (BreakAtNode == 0) return;
int trip = 10;
}
if (trip-- <= 0) break;
}
}
#endif //ASSERT
//------------------------------dump------------------------------------------
// Dump a Node
_in_dump_cnt++;
// Dump the required and precedence inputs
// Dump the outputs
if (is_disconnected(this)) {
#ifdef ASSERT
#endif
_in_dump_cnt--;
return; // don't process dead nodes
}
// Dump node-specific info
#ifdef ASSERT
// Dump the non-reset _debug_idx
if (Verbose && WizardMode) {
}
#endif
const Type *t = bottom_type();
} else if (toop) {
} else if (tkls) {
}
} else if (Verbose || WizardMode) {
if (t) {
} else {
}
} else if (t->isa_vect() && this->is_MachSpillCopy()) {
// Dump MachSpillcopy vector type.
}
if (is_new) {
}
}
}
_in_dump_cnt--;
}
//------------------------------dump_req--------------------------------------
// Dump the required input edges
if (d == NULL) {
} else if (NotANode(d)) {
} else {
}
}
}
//------------------------------dump_prec-------------------------------------
// Dump the precedence edges
int any_prec = 0;
if (p != NULL) {
}
}
}
//------------------------------dump_out--------------------------------------
// Delimit the output edges
// Dump the output edges
if (u == NULL) {
} else if (NotANode(u)) {
} else {
}
}
}
//------------------------------dump_nodes-------------------------------------
if (NotANode(s)) return;
int direction = d;
int begin = 0;
int end = 0;
if (NotANode(n)) continue;
// do not recurse through top or the root (would reach unrelated stuff)
if (!on_stack) {
}
}
}
}
if (direction > 0) {
for(int j = end-1; j >= 0; j--) {
}
} else {
for(int j = 0; j < end; j++) {
}
}
}
//------------------------------dump-------------------------------------------
dump_nodes(this, d, false);
}
//------------------------------dump_ctrl--------------------------------------
// Dump a Node's control history to depth
dump_nodes(this, d, true);
}
// VERIFICATION CODE
// For each input edge to a node (ie - for each Use-Def edge), verify that
// there is a corresponding Def-Use edge.
//------------------------------verify_edges-----------------------------------
int cnt;
Node *n;
// Recursive termination test
// Walk over all input edges, checking for correspondence
for( i = 0; i < len(); i++ ) {
n = in(i);
// Count instances of (Node *)this
cnt = 0;
}
// Check for duplicate edges
// walk the input array downcounting the input edges to n
for( j = 0; j < len(); j++ ) {
}
} else if (n == NULL) {
assert(i >= req() || i == 0 || is_Region() || is_Phi(), "only regions or phis have null data edges");
} else {
// Nothing to check.
}
}
// Recursive walk over all input edges
for( i = 0; i < len(); i++ ) {
n = in(i);
if( n != NULL )
}
}
//------------------------------verify_recur-----------------------------------
if ( verify_depth == 0 ) return;
if (verify_depth > 0) --verify_depth;
// Contained in new_space or old_space?
// Check for visited in the proper space. Numberings are not unique
// across spaces so we need a separate VectorSet for each space.
if (C->cached_top_node() == NULL)
C->set_cached_top_node((Node*)n);
}
if (!x || x->is_top()) continue;
// Verify my input has a def-use edge to me
if (true /*VerifyDefUse*/) {
// Count use-def edges from n to x
int cnt = 0;
if( n->in(j) == x )
cnt++;
// Count def-use edges from x to n
if (x->_out[k] == n)
cnt--;
}
}
}
//------------------------------verify-----------------------------------------
// Check Def-Use info for my subgraph
}
#endif
//------------------------------walk-------------------------------------------
// Graph walk, with both pre-order and post-order functions
}
if( in(i) ) // Input exists and is not walked?
}
//------------------------------Registers--------------------------------------
// Do we Match on this edge index or not? Generally false for Control
// and true for everything else. Weird for calls & returns.
return idx; // True for other than index 0 (control)
}
// Register classes are defined for specific machines
return *(new RegMask());
}
return *(new RegMask());
}
//=============================================================================
//-----------------------------------------------------------------------------
_max = 0;
}
//------------------------------clear------------------------------------------
// Clear all entries in _nodes to NULL but keep storage
void Node_Array::clear() {
}
//-----------------------------------------------------------------------------
if( !_max ) {
_max = 1;
}
}
//-----------------------------------------------------------------------------
Copy::conjoint_words_to_higher((HeapWord*)&_nodes[i], (HeapWord*)&_nodes[i+1], ((_max-i-1)*sizeof(Node*)));
_nodes[i] = n;
}
//-----------------------------------------------------------------------------
Copy::conjoint_words_to_lower((HeapWord*)&_nodes[i+1], (HeapWord*)&_nodes[i], ((_max-i-1)*sizeof(Node*)));
}
//-----------------------------------------------------------------------------
}
//-----------------------------------------------------------------------------
void Node_Array::dump() const {
#ifndef PRODUCT
}
}
#endif
}
//--------------------------is_iteratively_computed------------------------------
// Operation appears to be iteratively computed (such as an induction variable)
// It is possible for this operation to return false for a loop-varying
// value, if it appears (by local graph inspection) to be computed by a simple conditional.
bool Node::is_iteratively_computed() {
if (ideal_reg()) { // does operation have a result register?
if (n->in(j) == this) {
return true;
}
}
}
}
}
return false;
}
//--------------------------find_similar------------------------------
// Return a node with opcode "opc" and same inputs as "this" if one can
// be found; Otherwise return NULL;
if (req() >= 2) {
uint j;
break;
}
}
return use;
}
}
}
}
}
return NULL;
}
//--------------------------unique_ctrl_out------------------------------
// Return the unique control out if only one. Null if none or more than one.
}
}
return found;
}
//=============================================================================
//------------------------------yank-------------------------------------------
// Find and remove
uint i;
for( i = 0; i < _cnt; i++ )
if( _nodes[i] == n )
break;
if( i < _cnt )
}
//------------------------------dump-------------------------------------------
#ifndef PRODUCT
if( _nodes[i] ) {
}
#endif
}
//=============================================================================
//------------------------------remove-----------------------------------------
if( _in_worklist[n->_idx] ) {
if( _nodes[i] == n ) {
_in_worklist >>= n->_idx;
return;
}
}
}
//-----------------------remove_useless_nodes----------------------------------
// Remove useless nodes from worklist
_in_worklist >>= n->_idx;
// Node *replacement = Node_List::pop();
// if( i != size() ) { // Check if removing last entry
// _nodes[i] = replacement;
// }
--i; // Visit popped node
// If it was last entry, loop terminates since size() was also reduced
}
}
}
//=============================================================================
void Node_Stack::grow() {
}
// Node_Stack is used to map nodes.
return node_at(i);
}
return NULL;
}
//=============================================================================
#ifndef PRODUCT
if( !Verbose && !WizardMode ) {
// standard dump does this in Verbose and WizardMode
}
}
#endif
}
//------------------------------ideal_reg--------------------------------------
}