提交 1e33d97d 编写于 作者: B bharadwaj

7092905: C2: Keep track of the number of dead nodes

Summary: keep an (almost) accurate running count of the reachable (live) flow graph nodes.
Reviewed-by: kvn, twisti, jrose, vlivanov
上级 4df65638
...@@ -13,6 +13,6 @@ Adding the -i option with also report inlining like PrintInlining. ...@@ -13,6 +13,6 @@ Adding the -i option with also report inlining like PrintInlining.
More information about the LogCompilation output can be found at More information about the LogCompilation output can be found at
http://wikis.sun.com/display/HotSpotInternals/LogCompilation+overview https://wikis.oracle.com/display/HotSpotInternals/LogCompilation+overview
http://wikis.sun.com/display/HotSpotInternals/PrintCompilation https://wikis.oracle.com/display/HotSpotInternals/PrintCompilation
http://wikis.sun.com/display/HotSpotInternals/LogCompilation+tool https://wikis.oracle.com/display/HotSpotInternals/LogCompilation+tool
...@@ -38,6 +38,7 @@ public class CallSite { ...@@ -38,6 +38,7 @@ public class CallSite {
private String reason; private String reason;
private List<CallSite> calls; private List<CallSite> calls;
private int endNodes; private int endNodes;
private int endLiveNodes;
private double timeStamp; private double timeStamp;
CallSite() { CallSite() {
...@@ -106,7 +107,7 @@ public class CallSite { ...@@ -106,7 +107,7 @@ public class CallSite {
} }
} }
if (getEndNodes() > 0) { if (getEndNodes() > 0) {
stream.printf(" (end time: %6.4f nodes: %d)", getTimeStamp(), getEndNodes()); stream.printf(" (end time: %6.4f nodes: %d live: %d)", getTimeStamp(), getEndNodes(), getEndLiveNodes());
} }
stream.println(""); stream.println("");
if (getReceiver() != null) { if (getReceiver() != null) {
...@@ -195,6 +196,14 @@ public class CallSite { ...@@ -195,6 +196,14 @@ public class CallSite {
return endNodes; return endNodes;
} }
void setEndLiveNodes(int n) {
endLiveNodes = n;
}
public int getEndLiveNodes() {
return endLiveNodes;
}
void setTimeStamp(double time) { void setTimeStamp(double time) {
timeStamp = time; timeStamp = time;
} }
......
...@@ -43,7 +43,7 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons ...@@ -43,7 +43,7 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons
System.out.println(" -S: print compilation statistics"); System.out.println(" -S: print compilation statistics");
System.out.println(" -s: sort events by start time"); System.out.println(" -s: sort events by start time");
System.out.println(" -e: sort events by elapsed time"); System.out.println(" -e: sort events by elapsed time");
System.out.println(" -N: sort events by name and start"); System.out.println(" -n: sort events by name and start");
System.exit(exitcode); System.exit(exitcode);
} }
...@@ -137,7 +137,11 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons ...@@ -137,7 +137,11 @@ public class LogCompilation extends DefaultHandler implements ErrorHandler, Cons
v2 = Integer.valueOf(0); v2 = Integer.valueOf(0);
} }
phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes())); phaseNodes.put(phase.getName(), Integer.valueOf(v2.intValue() + phase.getNodes()));
out.printf("\t%s %6.4f %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes()); /* Print phase name, elapsed time, nodes at the start of the phase,
nodes created in the phase, live nodes at the start of the phase,
live nodes added in the phase.
*/
out.printf("\t%s %6.4f %d %d %d %d\n", phase.getName(), phase.getElapsedTime(), phase.getStartNodes(), phase.getNodes(), phase.getStartLiveNodes(), phase.getLiveNodes());
} }
} else if (e instanceof MakeNotEntrantEvent) { } else if (e instanceof MakeNotEntrantEvent) {
MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e; MakeNotEntrantEvent mne = (MakeNotEntrantEvent) e;
......
...@@ -268,12 +268,18 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -268,12 +268,18 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
if (qname.equals("phase")) { if (qname.equals("phase")) {
Phase p = new Phase(search(atts, "name"), Phase p = new Phase(search(atts, "name"),
Double.parseDouble(search(atts, "stamp")), Double.parseDouble(search(atts, "stamp")),
Integer.parseInt(search(atts, "nodes"))); Integer.parseInt(search(atts, "nodes")),
Integer.parseInt(search(atts, "live")));
phaseStack.push(p); phaseStack.push(p);
} else if (qname.equals("phase_done")) { } else if (qname.equals("phase_done")) {
Phase p = phaseStack.pop(); Phase p = phaseStack.pop();
p.setEndNodes(Integer.parseInt(search(atts, "nodes"))); if (! p.getId().equals(search(atts, "name"))) {
System.out.println("phase: " + p.getId());
throw new InternalError("phase name mismatch");
}
p.setEnd(Double.parseDouble(search(atts, "stamp"))); p.setEnd(Double.parseDouble(search(atts, "stamp")));
p.setEndNodes(Integer.parseInt(search(atts, "nodes")));
p.setEndLiveNodes(Integer.parseInt(search(atts, "live")));
compile.getPhases().add(p); compile.getPhases().add(p);
} else if (qname.equals("task")) { } else if (qname.equals("task")) {
compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1"))); compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1")));
...@@ -406,6 +412,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants ...@@ -406,6 +412,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
} else if (qname.equals("parse_done")) { } else if (qname.equals("parse_done")) {
CallSite call = scopes.pop(); CallSite call = scopes.pop();
call.setEndNodes(Integer.parseInt(search(atts, "nodes", "1"))); call.setEndNodes(Integer.parseInt(search(atts, "nodes", "1")));
call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "1")));
call.setTimeStamp(Double.parseDouble(search(atts, "stamp"))); call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
scopes.push(call); scopes.push(call);
} }
......
...@@ -30,10 +30,13 @@ public class Phase extends BasicLogEvent { ...@@ -30,10 +30,13 @@ public class Phase extends BasicLogEvent {
private final int startNodes; private final int startNodes;
private int endNodes; private int endNodes;
private final int startLiveNodes;
private int endLiveNodes;
Phase(String n, double s, int nodes) { Phase(String n, double s, int nodes, int live) {
super(s, n); super(s, n);
startNodes = nodes; startNodes = nodes;
startLiveNodes = live;
} }
int getNodes() { int getNodes() {
...@@ -55,6 +58,22 @@ public class Phase extends BasicLogEvent { ...@@ -55,6 +58,22 @@ public class Phase extends BasicLogEvent {
public int getEndNodes() { public int getEndNodes() {
return endNodes; return endNodes;
} }
/* Number of live nodes added by the phase */
int getLiveNodes() {
return getEndLiveNodes() - getStartLiveNodes();
}
void setEndLiveNodes(int n) {
endLiveNodes = n;
}
public int getStartLiveNodes() {
return startLiveNodes;
}
public int getEndLiveNodes() {
return endLiveNodes;
}
@Override @Override
public void print(PrintStream stream) { public void print(PrintStream stream) {
......
...@@ -292,7 +292,7 @@ class Block : public CFGElement { ...@@ -292,7 +292,7 @@ class Block : public CFGElement {
void needed_for_next_call(Node *this_call, VectorSet &next_call, Block_Array &bbs); void needed_for_next_call(Node *this_call, VectorSet &next_call, Block_Array &bbs);
bool schedule_local(PhaseCFG *cfg, Matcher &m, GrowableArray<int> &ready_cnt, VectorSet &next_call); bool schedule_local(PhaseCFG *cfg, Matcher &m, GrowableArray<int> &ready_cnt, VectorSet &next_call);
// Cleanup if any code lands between a Call and his Catch // Cleanup if any code lands between a Call and his Catch
void call_catch_cleanup(Block_Array &bbs); void call_catch_cleanup(Block_Array &bbs, Compile *C);
// Detect implicit-null-check opportunities. Basically, find NULL checks // Detect implicit-null-check opportunities. Basically, find NULL checks
// with suitable memory ops nearby. Use the memory op to do the NULL check. // with suitable memory ops nearby. Use the memory op to do the NULL check.
// I can generate a memory op if there is not one nearby. // I can generate a memory op if there is not one nearby.
......
...@@ -115,6 +115,12 @@ ...@@ -115,6 +115,12 @@
notproduct(bool, VerifyOpto, false, \ notproduct(bool, VerifyOpto, false, \
"Apply more time consuming verification during compilation") \ "Apply more time consuming verification during compilation") \
\ \
notproduct(bool, VerifyIdealNodeCount, false, \
"Verify that tracked dead ideal node count is accurate") \
\
notproduct(bool, PrintIdealNodeCount, false, \
"Print liveness counts of ideal nodes") \
\
notproduct(bool, VerifyOptoOopOffsets, false, \ notproduct(bool, VerifyOptoOopOffsets, false, \
"Check types of base addresses in field references") \ "Check types of base addresses in field references") \
\ \
......
...@@ -1495,7 +1495,7 @@ void PhaseChaitin::fixup_spills() { ...@@ -1495,7 +1495,7 @@ void PhaseChaitin::fixup_spills() {
cisc->ins_req(1,src); // Requires a memory edge cisc->ins_req(1,src); // Requires a memory edge
} }
b->_nodes.map(j,cisc); // Insert into basic block b->_nodes.map(j,cisc); // Insert into basic block
n->subsume_by(cisc); // Correct graph n->subsume_by(cisc, C); // Correct graph
// //
++_used_cisc_instructions; ++_used_cisc_instructions;
#ifndef PRODUCT #ifndef PRODUCT
......
...@@ -316,7 +316,12 @@ void Compile::gvn_replace_by(Node* n, Node* nn) { ...@@ -316,7 +316,12 @@ void Compile::gvn_replace_by(Node* n, Node* nn) {
} }
static inline bool not_a_node(const Node* n) {
if (n == NULL) return true;
if (((intptr_t)n & 1) != 0) return true; // uninitialized, etc.
if (*(address*)n == badAddress) return true; // kill by Node::destruct
return false;
}
// Identify all nodes that are reachable from below, useful. // Identify all nodes that are reachable from below, useful.
// Use breadth-first pass that records state in a Unique_Node_List, // Use breadth-first pass that records state in a Unique_Node_List,
...@@ -337,12 +342,27 @@ void Compile::identify_useful_nodes(Unique_Node_List &useful) { ...@@ -337,12 +342,27 @@ void Compile::identify_useful_nodes(Unique_Node_List &useful) {
uint max = n->len(); uint max = n->len();
for( uint i = 0; i < max; ++i ) { for( uint i = 0; i < max; ++i ) {
Node *m = n->in(i); Node *m = n->in(i);
if( m == NULL ) continue; if (not_a_node(m)) continue;
useful.push(m); useful.push(m);
} }
} }
} }
// Update dead_node_list with any missing dead nodes using useful
// list. Consider all non-useful nodes to be useless i.e., dead nodes.
void Compile::update_dead_node_list(Unique_Node_List &useful) {
uint max_idx = unique();
VectorSet& useful_node_set = useful.member_set();
for (uint node_idx = 0; node_idx < max_idx; node_idx++) {
// If node with index node_idx is not in useful set,
// mark it as dead in dead node list.
if (! useful_node_set.test(node_idx) ) {
record_dead_node(node_idx);
}
}
}
// Disconnect all useless nodes by disconnecting those at the boundary. // Disconnect all useless nodes by disconnecting those at the boundary.
void Compile::remove_useless_nodes(Unique_Node_List &useful) { void Compile::remove_useless_nodes(Unique_Node_List &useful) {
uint next = 0; uint next = 0;
...@@ -582,6 +602,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -582,6 +602,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_inner_loops(0), _inner_loops(0),
_scratch_const_size(-1), _scratch_const_size(-1),
_in_scratch_emit_size(false), _in_scratch_emit_size(false),
_dead_node_list(comp_arena()),
_dead_node_count(0),
#ifndef PRODUCT #ifndef PRODUCT
_trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")), _trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
_printer(IdealGraphPrinter::printer()), _printer(IdealGraphPrinter::printer()),
...@@ -873,6 +895,8 @@ Compile::Compile( ciEnv* ci_env, ...@@ -873,6 +895,8 @@ Compile::Compile( ciEnv* ci_env,
_trace_opto_output(TraceOptoOutput), _trace_opto_output(TraceOptoOutput),
_printer(NULL), _printer(NULL),
#endif #endif
_dead_node_list(comp_arena()),
_dead_node_count(0),
_congraph(NULL) { _congraph(NULL) {
C = this; C = this;
...@@ -1069,6 +1093,72 @@ void Compile::set_cached_top_node(Node* tn) { ...@@ -1069,6 +1093,72 @@ void Compile::set_cached_top_node(Node* tn) {
assert(_top == NULL || top()->is_top(), ""); assert(_top == NULL || top()->is_top(), "");
} }
#ifdef ASSERT
uint Compile::count_live_nodes_by_graph_walk() {
Unique_Node_List useful(comp_arena());
// Get useful node list by walking the graph.
identify_useful_nodes(useful);
return useful.size();
}
void Compile::print_missing_nodes() {
// Return if CompileLog is NULL and PrintIdealNodeCount is false.
if ((_log == NULL) && (! PrintIdealNodeCount)) {
return;
}
// This is an expensive function. It is executed only when the user
// specifies VerifyIdealNodeCount option or otherwise knows the
// additional work that needs to be done to identify reachable nodes
// by walking the flow graph and find the missing ones using
// _dead_node_list.
Unique_Node_List useful(comp_arena());
// Get useful node list by walking the graph.
identify_useful_nodes(useful);
uint l_nodes = C->live_nodes();
uint l_nodes_by_walk = useful.size();
if (l_nodes != l_nodes_by_walk) {
if (_log != NULL) {
_log->begin_head("mismatched_nodes count='%d'", abs((int) (l_nodes - l_nodes_by_walk)));
_log->stamp();
_log->end_head();
}
VectorSet& useful_member_set = useful.member_set();
int last_idx = l_nodes_by_walk;
for (int i = 0; i < last_idx; i++) {
if (useful_member_set.test(i)) {
if (_dead_node_list.test(i)) {
if (_log != NULL) {
_log->elem("mismatched_node_info node_idx='%d' type='both live and dead'", i);
}
if (PrintIdealNodeCount) {
// Print the log message to tty
tty->print_cr("mismatched_node idx='%d' both live and dead'", i);
useful.at(i)->dump();
}
}
}
else if (! _dead_node_list.test(i)) {
if (_log != NULL) {
_log->elem("mismatched_node_info node_idx='%d' type='neither live nor dead'", i);
}
if (PrintIdealNodeCount) {
// Print the log message to tty
tty->print_cr("mismatched_node idx='%d' type='neither live nor dead'", i);
}
}
}
if (_log != NULL) {
_log->tail("mismatched_nodes");
}
}
}
#endif
#ifndef PRODUCT #ifndef PRODUCT
void Compile::verify_top(Node* tn) const { void Compile::verify_top(Node* tn) const {
if (tn != NULL) { if (tn != NULL) {
...@@ -2087,7 +2177,7 @@ static bool oop_offset_is_sane(const TypeInstPtr* tp) { ...@@ -2087,7 +2177,7 @@ static bool oop_offset_is_sane(const TypeInstPtr* tp) {
// Eliminate trivially redundant StoreCMs and accumulate their // Eliminate trivially redundant StoreCMs and accumulate their
// precedence edges. // precedence edges.
static void eliminate_redundant_card_marks(Node* n) { void Compile::eliminate_redundant_card_marks(Node* n) {
assert(n->Opcode() == Op_StoreCM, "expected StoreCM"); assert(n->Opcode() == Op_StoreCM, "expected StoreCM");
if (n->in(MemNode::Address)->outcnt() > 1) { if (n->in(MemNode::Address)->outcnt() > 1) {
// There are multiple users of the same address so it might be // There are multiple users of the same address so it might be
...@@ -2122,7 +2212,7 @@ static void eliminate_redundant_card_marks(Node* n) { ...@@ -2122,7 +2212,7 @@ static void eliminate_redundant_card_marks(Node* n) {
// Eliminate the previous StoreCM // Eliminate the previous StoreCM
prev->set_req(MemNode::Memory, mem->in(MemNode::Memory)); prev->set_req(MemNode::Memory, mem->in(MemNode::Memory));
assert(mem->outcnt() == 0, "should be dead"); assert(mem->outcnt() == 0, "should be dead");
mem->disconnect_inputs(NULL); mem->disconnect_inputs(NULL, this);
} else { } else {
prev = mem; prev = mem;
} }
...@@ -2133,7 +2223,7 @@ static void eliminate_redundant_card_marks(Node* n) { ...@@ -2133,7 +2223,7 @@ static void eliminate_redundant_card_marks(Node* n) {
//------------------------------final_graph_reshaping_impl---------------------- //------------------------------final_graph_reshaping_impl----------------------
// Implement items 1-5 from final_graph_reshaping below. // Implement items 1-5 from final_graph_reshaping below.
static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) {
if ( n->outcnt() == 0 ) return; // dead node if ( n->outcnt() == 0 ) return; // dead node
uint nop = n->Opcode(); uint nop = n->Opcode();
...@@ -2163,8 +2253,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2163,8 +2253,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
#ifdef ASSERT #ifdef ASSERT
if( n->is_Mem() ) { if( n->is_Mem() ) {
Compile* C = Compile::current(); int alias_idx = get_alias_index(n->as_Mem()->adr_type());
int alias_idx = C->get_alias_index(n->as_Mem()->adr_type());
assert( n->in(0) != NULL || alias_idx != Compile::AliasIdxRaw || assert( n->in(0) != NULL || alias_idx != Compile::AliasIdxRaw ||
// oop will be recorded in oop map if load crosses safepoint // oop will be recorded in oop map if load crosses safepoint
n->is_Load() && (n->as_Load()->bottom_type()->isa_oopptr() || n->is_Load() && (n->as_Load()->bottom_type()->isa_oopptr() ||
...@@ -2213,7 +2302,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2213,7 +2302,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
break; break;
case Op_Opaque1: // Remove Opaque Nodes before matching case Op_Opaque1: // Remove Opaque Nodes before matching
case Op_Opaque2: // Remove Opaque Nodes before matching case Op_Opaque2: // Remove Opaque Nodes before matching
n->subsume_by(n->in(1)); n->subsume_by(n->in(1), this);
break; break;
case Op_CallStaticJava: case Op_CallStaticJava:
case Op_CallJava: case Op_CallJava:
...@@ -2337,8 +2426,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2337,8 +2426,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
int op = t->isa_oopptr() ? Op_ConN : Op_ConNKlass; int op = t->isa_oopptr() ? Op_ConN : Op_ConNKlass;
// Look for existing ConN node of the same exact type. // Look for existing ConN node of the same exact type.
Compile* C = Compile::current(); Node* r = root();
Node* r = C->root();
uint cnt = r->outcnt(); uint cnt = r->outcnt();
for (uint i = 0; i < cnt; i++) { for (uint i = 0; i < cnt; i++) {
Node* m = r->raw_out(i); Node* m = r->raw_out(i);
...@@ -2352,14 +2440,14 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2352,14 +2440,14 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
// Decode a narrow oop to match address // Decode a narrow oop to match address
// [R12 + narrow_oop_reg<<3 + offset] // [R12 + narrow_oop_reg<<3 + offset]
if (t->isa_oopptr()) { if (t->isa_oopptr()) {
nn = new (C) DecodeNNode(nn, t); nn = new (this) DecodeNNode(nn, t);
} else { } else {
nn = new (C) DecodeNKlassNode(nn, t); nn = new (this) DecodeNKlassNode(nn, t);
} }
n->set_req(AddPNode::Base, nn); n->set_req(AddPNode::Base, nn);
n->set_req(AddPNode::Address, nn); n->set_req(AddPNode::Address, nn);
if (addp->outcnt() == 0) { if (addp->outcnt() == 0) {
addp->disconnect_inputs(NULL); addp->disconnect_inputs(NULL, this);
} }
} }
} }
...@@ -2371,7 +2459,6 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2371,7 +2459,6 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
#ifdef _LP64 #ifdef _LP64
case Op_CastPP: case Op_CastPP:
if (n->in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks()) { if (n->in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks()) {
Compile* C = Compile::current();
Node* in1 = n->in(1); Node* in1 = n->in(1);
const Type* t = n->bottom_type(); const Type* t = n->bottom_type();
Node* new_in1 = in1->clone(); Node* new_in1 = in1->clone();
...@@ -2400,9 +2487,9 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2400,9 +2487,9 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
new_in1->set_req(0, n->in(0)); new_in1->set_req(0, n->in(0));
} }
n->subsume_by(new_in1); n->subsume_by(new_in1, this);
if (in1->outcnt() == 0) { if (in1->outcnt() == 0) {
in1->disconnect_inputs(NULL); in1->disconnect_inputs(NULL, this);
} }
} }
break; break;
...@@ -2419,7 +2506,6 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2419,7 +2506,6 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
} }
assert(in1->is_DecodeNarrowPtr(), "sanity"); assert(in1->is_DecodeNarrowPtr(), "sanity");
Compile* C = Compile::current();
Node* new_in2 = NULL; Node* new_in2 = NULL;
if (in2->is_DecodeNarrowPtr()) { if (in2->is_DecodeNarrowPtr()) {
assert(in2->Opcode() == in1->Opcode(), "must be same node type"); assert(in2->Opcode() == in1->Opcode(), "must be same node type");
...@@ -2432,7 +2518,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2432,7 +2518,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
// oops implicit null check is not generated. // oops implicit null check is not generated.
// This will allow to generate normal oop implicit null check. // This will allow to generate normal oop implicit null check.
if (Matcher::gen_narrow_oop_implicit_null_checks()) if (Matcher::gen_narrow_oop_implicit_null_checks())
new_in2 = ConNode::make(C, TypeNarrowOop::NULL_PTR); new_in2 = ConNode::make(this, TypeNarrowOop::NULL_PTR);
// //
// This transformation together with CastPP transformation above // This transformation together with CastPP transformation above
// will generated code for implicit NULL checks for compressed oops. // will generated code for implicit NULL checks for compressed oops.
...@@ -2471,19 +2557,19 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2471,19 +2557,19 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
// NullCheck base_reg // NullCheck base_reg
// //
} else if (t->isa_oopptr()) { } else if (t->isa_oopptr()) {
new_in2 = ConNode::make(C, t->make_narrowoop()); new_in2 = ConNode::make(this, t->make_narrowoop());
} else if (t->isa_klassptr()) { } else if (t->isa_klassptr()) {
new_in2 = ConNode::make(C, t->make_narrowklass()); new_in2 = ConNode::make(this, t->make_narrowklass());
} }
} }
if (new_in2 != NULL) { if (new_in2 != NULL) {
Node* cmpN = new (C) CmpNNode(in1->in(1), new_in2); Node* cmpN = new (this) CmpNNode(in1->in(1), new_in2);
n->subsume_by( cmpN ); n->subsume_by(cmpN, this);
if (in1->outcnt() == 0) { if (in1->outcnt() == 0) {
in1->disconnect_inputs(NULL); in1->disconnect_inputs(NULL, this);
} }
if (in2->outcnt() == 0) { if (in2->outcnt() == 0) {
in2->disconnect_inputs(NULL); in2->disconnect_inputs(NULL, this);
} }
} }
} }
...@@ -2501,21 +2587,20 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2501,21 +2587,20 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
case Op_EncodePKlass: { case Op_EncodePKlass: {
Node* in1 = n->in(1); Node* in1 = n->in(1);
if (in1->is_DecodeNarrowPtr()) { if (in1->is_DecodeNarrowPtr()) {
n->subsume_by(in1->in(1)); n->subsume_by(in1->in(1), this);
} else if (in1->Opcode() == Op_ConP) { } else if (in1->Opcode() == Op_ConP) {
Compile* C = Compile::current();
const Type* t = in1->bottom_type(); const Type* t = in1->bottom_type();
if (t == TypePtr::NULL_PTR) { if (t == TypePtr::NULL_PTR) {
assert(t->isa_oopptr(), "null klass?"); assert(t->isa_oopptr(), "null klass?");
n->subsume_by(ConNode::make(C, TypeNarrowOop::NULL_PTR)); n->subsume_by(ConNode::make(this, TypeNarrowOop::NULL_PTR), this);
} else if (t->isa_oopptr()) { } else if (t->isa_oopptr()) {
n->subsume_by(ConNode::make(C, t->make_narrowoop())); n->subsume_by(ConNode::make(this, t->make_narrowoop()), this);
} else if (t->isa_klassptr()) { } else if (t->isa_klassptr()) {
n->subsume_by(ConNode::make(C, t->make_narrowklass())); n->subsume_by(ConNode::make(this, t->make_narrowklass()), this);
} }
} }
if (in1->outcnt() == 0) { if (in1->outcnt() == 0) {
in1->disconnect_inputs(NULL); in1->disconnect_inputs(NULL, this);
} }
break; break;
} }
...@@ -2538,7 +2623,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2538,7 +2623,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
} }
} }
assert(proj != NULL, "must be found"); assert(proj != NULL, "must be found");
p->subsume_by(proj); p->subsume_by(proj, this);
} }
} }
break; break;
...@@ -2558,7 +2643,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2558,7 +2643,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
unique_in = NULL; unique_in = NULL;
} }
if (unique_in != NULL) { if (unique_in != NULL) {
n->subsume_by(unique_in); n->subsume_by(unique_in, this);
} }
} }
break; break;
...@@ -2571,16 +2656,15 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2571,16 +2656,15 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
Node* d = n->find_similar(Op_DivI); Node* d = n->find_similar(Op_DivI);
if (d) { if (d) {
// Replace them with a fused divmod if supported // Replace them with a fused divmod if supported
Compile* C = Compile::current();
if (Matcher::has_match_rule(Op_DivModI)) { if (Matcher::has_match_rule(Op_DivModI)) {
DivModINode* divmod = DivModINode::make(C, n); DivModINode* divmod = DivModINode::make(this, n);
d->subsume_by(divmod->div_proj()); d->subsume_by(divmod->div_proj(), this);
n->subsume_by(divmod->mod_proj()); n->subsume_by(divmod->mod_proj(), this);
} else { } else {
// replace a%b with a-((a/b)*b) // replace a%b with a-((a/b)*b)
Node* mult = new (C) MulINode(d, d->in(2)); Node* mult = new (this) MulINode(d, d->in(2));
Node* sub = new (C) SubINode(d->in(1), mult); Node* sub = new (this) SubINode(d->in(1), mult);
n->subsume_by( sub ); n->subsume_by(sub, this);
} }
} }
} }
...@@ -2592,16 +2676,15 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2592,16 +2676,15 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
Node* d = n->find_similar(Op_DivL); Node* d = n->find_similar(Op_DivL);
if (d) { if (d) {
// Replace them with a fused divmod if supported // Replace them with a fused divmod if supported
Compile* C = Compile::current();
if (Matcher::has_match_rule(Op_DivModL)) { if (Matcher::has_match_rule(Op_DivModL)) {
DivModLNode* divmod = DivModLNode::make(C, n); DivModLNode* divmod = DivModLNode::make(this, n);
d->subsume_by(divmod->div_proj()); d->subsume_by(divmod->div_proj(), this);
n->subsume_by(divmod->mod_proj()); n->subsume_by(divmod->mod_proj(), this);
} else { } else {
// replace a%b with a-((a/b)*b) // replace a%b with a-((a/b)*b)
Node* mult = new (C) MulLNode(d, d->in(2)); Node* mult = new (this) MulLNode(d, d->in(2));
Node* sub = new (C) SubLNode(d->in(1), mult); Node* sub = new (this) SubLNode(d->in(1), mult);
n->subsume_by( sub ); n->subsume_by(sub, this);
} }
} }
} }
...@@ -2620,8 +2703,8 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2620,8 +2703,8 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
if (n->req()-1 > 2) { if (n->req()-1 > 2) {
// Replace many operand PackNodes with a binary tree for matching // Replace many operand PackNodes with a binary tree for matching
PackNode* p = (PackNode*) n; PackNode* p = (PackNode*) n;
Node* btp = p->binary_tree_pack(Compile::current(), 1, n->req()); Node* btp = p->binary_tree_pack(this, 1, n->req());
n->subsume_by(btp); n->subsume_by(btp, this);
} }
break; break;
case Op_Loop: case Op_Loop:
...@@ -2645,18 +2728,16 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2645,18 +2728,16 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
if (t != NULL && t->is_con()) { if (t != NULL && t->is_con()) {
juint shift = t->get_con(); juint shift = t->get_con();
if (shift > mask) { // Unsigned cmp if (shift > mask) { // Unsigned cmp
Compile* C = Compile::current(); n->set_req(2, ConNode::make(this, TypeInt::make(shift & mask)));
n->set_req(2, ConNode::make(C, TypeInt::make(shift & mask)));
} }
} else { } else {
if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) { if (t == NULL || t->_lo < 0 || t->_hi > (int)mask) {
Compile* C = Compile::current(); Node* shift = new (this) AndINode(in2, ConNode::make(this, TypeInt::make(mask)));
Node* shift = new (C) AndINode(in2, ConNode::make(C, TypeInt::make(mask)));
n->set_req(2, shift); n->set_req(2, shift);
} }
} }
if (in2->outcnt() == 0) { // Remove dead node if (in2->outcnt() == 0) { // Remove dead node
in2->disconnect_inputs(NULL); in2->disconnect_inputs(NULL, this);
} }
} }
break; break;
...@@ -2674,7 +2755,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) { ...@@ -2674,7 +2755,7 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
//------------------------------final_graph_reshaping_walk--------------------- //------------------------------final_graph_reshaping_walk---------------------
// Replacing Opaque nodes with their input in final_graph_reshaping_impl(), // Replacing Opaque nodes with their input in final_graph_reshaping_impl(),
// requires that the walk visits a node's inputs before visiting the node. // requires that the walk visits a node's inputs before visiting the node.
static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc ) { void Compile::final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc ) {
ResourceArea *area = Thread::current()->resource_area(); ResourceArea *area = Thread::current()->resource_area();
Unique_Node_List sfpt(area); Unique_Node_List sfpt(area);
...@@ -2741,7 +2822,7 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re ...@@ -2741,7 +2822,7 @@ static void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Re
n->set_req(j, in->in(1)); n->set_req(j, in->in(1));
} }
if (in->outcnt() == 0) { if (in->outcnt() == 0) {
in->disconnect_inputs(NULL); in->disconnect_inputs(NULL, this);
} }
} }
} }
...@@ -3014,7 +3095,8 @@ void Compile::record_failure(const char* reason) { ...@@ -3014,7 +3095,8 @@ void Compile::record_failure(const char* reason) {
} }
Compile::TracePhase::TracePhase(const char* name, elapsedTimer* accumulator, bool dolog) Compile::TracePhase::TracePhase(const char* name, elapsedTimer* accumulator, bool dolog)
: TraceTime(NULL, accumulator, false NOT_PRODUCT( || TimeCompiler ), false) : TraceTime(NULL, accumulator, false NOT_PRODUCT( || TimeCompiler ), false),
_phase_name(name), _dolog(dolog)
{ {
if (dolog) { if (dolog) {
C = Compile::current(); C = Compile::current();
...@@ -3024,15 +3106,34 @@ Compile::TracePhase::TracePhase(const char* name, elapsedTimer* accumulator, boo ...@@ -3024,15 +3106,34 @@ Compile::TracePhase::TracePhase(const char* name, elapsedTimer* accumulator, boo
_log = NULL; _log = NULL;
} }
if (_log != NULL) { if (_log != NULL) {
_log->begin_head("phase name='%s' nodes='%d'", name, C->unique()); _log->begin_head("phase name='%s' nodes='%d' live='%d'", _phase_name, C->unique(), C->live_nodes());
_log->stamp(); _log->stamp();
_log->end_head(); _log->end_head();
} }
} }
Compile::TracePhase::~TracePhase() { Compile::TracePhase::~TracePhase() {
C = Compile::current();
if (_dolog) {
_log = C->log();
} else {
_log = NULL;
}
#ifdef ASSERT
if (PrintIdealNodeCount) {
tty->print_cr("phase name='%s' nodes='%d' live='%d' live_graph_walk='%d'",
_phase_name, C->unique(), C->live_nodes(), C->count_live_nodes_by_graph_walk());
}
if (VerifyIdealNodeCount) {
Compile::current()->print_missing_nodes();
}
#endif
if (_log != NULL) { if (_log != NULL) {
_log->done("phase nodes='%d'", C->unique()); _log->done("phase name='%s' nodes='%d' live='%d'", _phase_name, C->unique(), C->live_nodes());
} }
} }
......
...@@ -75,6 +75,8 @@ class TypeFunc; ...@@ -75,6 +75,8 @@ class TypeFunc;
class Unique_Node_List; class Unique_Node_List;
class nmethod; class nmethod;
class WarmCallInfo; class WarmCallInfo;
class Node_Stack;
struct Final_Reshape_Counts;
//------------------------------Compile---------------------------------------- //------------------------------Compile----------------------------------------
// This class defines a top-level Compiler invocation. // This class defines a top-level Compiler invocation.
...@@ -98,6 +100,8 @@ class Compile : public Phase { ...@@ -98,6 +100,8 @@ class Compile : public Phase {
private: private:
Compile* C; Compile* C;
CompileLog* _log; CompileLog* _log;
const char* _phase_name;
bool _dolog;
public: public:
TracePhase(const char* name, elapsedTimer* accumulator, bool dolog); TracePhase(const char* name, elapsedTimer* accumulator, bool dolog);
~TracePhase(); ~TracePhase();
...@@ -313,6 +317,9 @@ class Compile : public Phase { ...@@ -313,6 +317,9 @@ class Compile : public Phase {
// Node management // Node management
uint _unique; // Counter for unique Node indices uint _unique; // Counter for unique Node indices
VectorSet _dead_node_list; // Set of dead nodes
uint _dead_node_count; // Number of dead nodes; VectorSet::Size() is O(N).
// So use this to keep count and make the call O(1).
debug_only(static int _debug_idx;) // Monotonic counter (not reset), use -XX:BreakAtNode=<idx> debug_only(static int _debug_idx;) // Monotonic counter (not reset), use -XX:BreakAtNode=<idx>
Arena _node_arena; // Arena for new-space Nodes Arena _node_arena; // Arena for new-space Nodes
Arena _old_arena; // Arena for old-space Nodes, lifetime during xform Arena _old_arena; // Arena for old-space Nodes, lifetime during xform
...@@ -534,7 +541,7 @@ class Compile : public Phase { ...@@ -534,7 +541,7 @@ class Compile : public Phase {
ciEnv* env() const { return _env; } ciEnv* env() const { return _env; }
CompileLog* log() const { return _log; } CompileLog* log() const { return _log; }
bool failing() const { return _env->failing() || _failure_reason != NULL; } bool failing() const { return _env->failing() || _failure_reason != NULL; }
const char* failure_reason() { return _failure_reason; } const char* failure_reason() { return _failure_reason; }
bool failure_reason_is(const char* r) { return (r==_failure_reason) || (r!=NULL && _failure_reason!=NULL && strcmp(r, _failure_reason)==0); } bool failure_reason_is(const char* r) { return (r==_failure_reason) || (r!=NULL && _failure_reason!=NULL && strcmp(r, _failure_reason)==0); }
void record_failure(const char* reason); void record_failure(const char* reason);
...@@ -549,7 +556,7 @@ class Compile : public Phase { ...@@ -549,7 +556,7 @@ class Compile : public Phase {
record_method_not_compilable(reason, true); record_method_not_compilable(reason, true);
} }
bool check_node_count(uint margin, const char* reason) { bool check_node_count(uint margin, const char* reason) {
if (unique() + margin > (uint)MaxNodeLimit) { if (live_nodes() + margin > (uint)MaxNodeLimit) {
record_method_not_compilable(reason); record_method_not_compilable(reason);
return true; return true;
} else { } else {
...@@ -558,25 +565,41 @@ class Compile : public Phase { ...@@ -558,25 +565,41 @@ class Compile : public Phase {
} }
// Node management // Node management
uint unique() const { return _unique; } uint unique() const { return _unique; }
uint next_unique() { return _unique++; } uint next_unique() { return _unique++; }
void set_unique(uint i) { _unique = i; } void set_unique(uint i) { _unique = i; }
static int debug_idx() { return debug_only(_debug_idx)+0; } static int debug_idx() { return debug_only(_debug_idx)+0; }
static void set_debug_idx(int i) { debug_only(_debug_idx = i); } static void set_debug_idx(int i) { debug_only(_debug_idx = i); }
Arena* node_arena() { return &_node_arena; } Arena* node_arena() { return &_node_arena; }
Arena* old_arena() { return &_old_arena; } Arena* old_arena() { return &_old_arena; }
RootNode* root() const { return _root; } RootNode* root() const { return _root; }
void set_root(RootNode* r) { _root = r; } void set_root(RootNode* r) { _root = r; }
StartNode* start() const; // (Derived from root.) StartNode* start() const; // (Derived from root.)
void init_start(StartNode* s); void init_start(StartNode* s);
Node* immutable_memory(); Node* immutable_memory();
Node* recent_alloc_ctl() const { return _recent_alloc_ctl; } Node* recent_alloc_ctl() const { return _recent_alloc_ctl; }
Node* recent_alloc_obj() const { return _recent_alloc_obj; } Node* recent_alloc_obj() const { return _recent_alloc_obj; }
void set_recent_alloc(Node* ctl, Node* obj) { void set_recent_alloc(Node* ctl, Node* obj) {
_recent_alloc_ctl = ctl; _recent_alloc_ctl = ctl;
_recent_alloc_obj = obj; _recent_alloc_obj = obj;
} }
void record_dead_node(uint idx) { if (_dead_node_list.test_set(idx)) return;
_dead_node_count++;
}
uint dead_node_count() { return _dead_node_count; }
void reset_dead_node_list() { _dead_node_list.Reset();
_dead_node_count = 0;
}
uint live_nodes() {
int val = _unique - _dead_node_count;
assert (val >= 0, err_msg_res("number of tracked dead nodes %d more than created nodes %d", _unique, _dead_node_count));
return (uint) val;
}
#ifdef ASSERT
uint count_live_nodes_by_graph_walk();
void print_missing_nodes();
#endif
// Constant table // Constant table
ConstantTable& constant_table() { return _constant_table; } ConstantTable& constant_table() { return _constant_table; }
...@@ -678,6 +701,7 @@ class Compile : public Phase { ...@@ -678,6 +701,7 @@ class Compile : public Phase {
void identify_useful_nodes(Unique_Node_List &useful); void identify_useful_nodes(Unique_Node_List &useful);
void update_dead_node_list(Unique_Node_List &useful);
void remove_useless_nodes (Unique_Node_List &useful); void remove_useless_nodes (Unique_Node_List &useful);
WarmCallInfo* warm_calls() const { return _warm_calls; } WarmCallInfo* warm_calls() const { return _warm_calls; }
...@@ -892,6 +916,11 @@ class Compile : public Phase { ...@@ -892,6 +916,11 @@ class Compile : public Phase {
static juint _intrinsic_hist_count[vmIntrinsics::ID_LIMIT]; static juint _intrinsic_hist_count[vmIntrinsics::ID_LIMIT];
static jubyte _intrinsic_hist_flags[vmIntrinsics::ID_LIMIT]; static jubyte _intrinsic_hist_flags[vmIntrinsics::ID_LIMIT];
#endif #endif
// Function calls made by the public function final_graph_reshaping.
// No need to be made public as they are not called elsewhere.
void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc);
void final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_Reshape_Counts &frc );
void eliminate_redundant_card_marks(Node* n);
public: public:
......
...@@ -2320,7 +2320,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro ...@@ -2320,7 +2320,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro
} }
} }
} }
if ((int)C->unique() + 2*NodeLimitFudgeFactor > MaxNodeLimit) { if ((int) (C->live_nodes() + 2*NodeLimitFudgeFactor) > MaxNodeLimit) {
if (C->do_escape_analysis() == true && !C->failing()) { if (C->do_escape_analysis() == true && !C->failing()) {
// Retry compilation without escape analysis. // Retry compilation without escape analysis.
// If this is the first failure, the sentinel string will "stick" // If this is the first failure, the sentinel string will "stick"
......
...@@ -1359,7 +1359,7 @@ void PhaseCFG::GlobalCodeMotion( Matcher &matcher, uint unique, Node_List &proj_ ...@@ -1359,7 +1359,7 @@ void PhaseCFG::GlobalCodeMotion( Matcher &matcher, uint unique, Node_List &proj_
// If we inserted any instructions between a Call and his CatchNode, // If we inserted any instructions between a Call and his CatchNode,
// clone the instructions on all paths below the Catch. // clone the instructions on all paths below the Catch.
for( i=0; i < _num_blocks; i++ ) for( i=0; i < _num_blocks; i++ )
_blocks[i]->call_catch_cleanup(_bbs); _blocks[i]->call_catch_cleanup(_bbs, C);
#ifndef PRODUCT #ifndef PRODUCT
if (trace_opto_pipelining()) { if (trace_opto_pipelining()) {
......
...@@ -153,7 +153,7 @@ void GraphKit::verify_exception_state(SafePointNode* ex_map) { ...@@ -153,7 +153,7 @@ void GraphKit::verify_exception_state(SafePointNode* ex_map) {
void GraphKit::stop_and_kill_map() { void GraphKit::stop_and_kill_map() {
SafePointNode* dead_map = stop(); SafePointNode* dead_map = stop();
if (dead_map != NULL) { if (dead_map != NULL) {
dead_map->disconnect_inputs(NULL); // Mark the map as killed. dead_map->disconnect_inputs(NULL, C); // Mark the map as killed.
assert(dead_map->is_killed(), "must be so marked"); assert(dead_map->is_killed(), "must be so marked");
} }
} }
...@@ -1811,7 +1811,7 @@ void GraphKit::replace_call(CallNode* call, Node* result) { ...@@ -1811,7 +1811,7 @@ void GraphKit::replace_call(CallNode* call, Node* result) {
} }
// Disconnect the call from the graph // Disconnect the call from the graph
call->disconnect_inputs(NULL); call->disconnect_inputs(NULL, C);
C->gvn_replace_by(call, C->top()); C->gvn_replace_by(call, C->top());
// Clean up any MergeMems that feed other MergeMems since the // Clean up any MergeMems that feed other MergeMems since the
......
...@@ -573,7 +573,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { ...@@ -573,7 +573,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
(n2lidx(def) && !liveout.member(n2lidx(def)) ) ) { (n2lidx(def) && !liveout.member(n2lidx(def)) ) ) {
b->_nodes.remove(j - 1); b->_nodes.remove(j - 1);
if( lrgs(r)._def == n ) lrgs(r)._def = 0; if( lrgs(r)._def == n ) lrgs(r)._def = 0;
n->disconnect_inputs(NULL); n->disconnect_inputs(NULL, C);
_cfg._bbs.map(n->_idx,NULL); _cfg._bbs.map(n->_idx,NULL);
n->replace_by(C->top()); n->replace_by(C->top());
// Since yanking a Node from block, high pressure moves up one // Since yanking a Node from block, high pressure moves up one
......
...@@ -1006,7 +1006,7 @@ static void catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Bloc ...@@ -1006,7 +1006,7 @@ static void catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Bloc
//------------------------------call_catch_cleanup----------------------------- //------------------------------call_catch_cleanup-----------------------------
// If we inserted any instructions between a Call and his CatchNode, // If we inserted any instructions between a Call and his CatchNode,
// clone the instructions on all paths below the Catch. // clone the instructions on all paths below the Catch.
void Block::call_catch_cleanup(Block_Array &bbs) { void Block::call_catch_cleanup(Block_Array &bbs, Compile* C) {
// End of region to clone // End of region to clone
uint end = end_idx(); uint end = end_idx();
...@@ -1068,7 +1068,7 @@ void Block::call_catch_cleanup(Block_Array &bbs) { ...@@ -1068,7 +1068,7 @@ void Block::call_catch_cleanup(Block_Array &bbs) {
// Remove the now-dead cloned ops // Remove the now-dead cloned ops
for(uint i3 = beg; i3 < end; i3++ ) { for(uint i3 = beg; i3 < end; i3++ ) {
_nodes[beg]->disconnect_inputs(NULL); _nodes[beg]->disconnect_inputs(NULL, C);
_nodes.remove(beg); _nodes.remove(beg);
} }
...@@ -1081,7 +1081,7 @@ void Block::call_catch_cleanup(Block_Array &bbs) { ...@@ -1081,7 +1081,7 @@ void Block::call_catch_cleanup(Block_Array &bbs) {
Node *n = sb->_nodes[j]; Node *n = sb->_nodes[j];
if (n->outcnt() == 0 && if (n->outcnt() == 0 &&
(!n->is_Proj() || n->as_Proj()->in(0)->outcnt() == 1) ){ (!n->is_Proj() || n->as_Proj()->in(0)->outcnt() == 1) ){
n->disconnect_inputs(NULL); n->disconnect_inputs(NULL, C);
sb->_nodes.remove(j); sb->_nodes.remove(j);
new_cnt--; new_cnt--;
} }
......
...@@ -269,10 +269,10 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) { ...@@ -269,10 +269,10 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) {
bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const { bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const {
Node *test = ((IdealLoopTree*)this)->tail(); Node *test = ((IdealLoopTree*)this)->tail();
int body_size = ((IdealLoopTree*)this)->_body.size(); int body_size = ((IdealLoopTree*)this)->_body.size();
int uniq = phase->C->unique(); int live_node_count = phase->C->live_nodes();
// Peeling does loop cloning which can result in O(N^2) node construction // Peeling does loop cloning which can result in O(N^2) node construction
if( body_size > 255 /* Prevent overflow for large body_size */ if( body_size > 255 /* Prevent overflow for large body_size */
|| (body_size * body_size + uniq > MaxNodeLimit) ) { || (body_size * body_size + live_node_count > MaxNodeLimit) ) {
return false; // too large to safely clone return false; // too large to safely clone
} }
while( test != _head ) { // Scan till run off top of loop while( test != _head ) { // Scan till run off top of loop
...@@ -601,7 +601,7 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const { ...@@ -601,7 +601,7 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
return false; return false;
if (new_body_size > unroll_limit || if (new_body_size > unroll_limit ||
// Unrolling can result in a large amount of node construction // Unrolling can result in a large amount of node construction
new_body_size >= MaxNodeLimit - phase->C->unique()) { new_body_size >= MaxNodeLimit - (uint) phase->C->live_nodes()) {
return false; return false;
} }
...@@ -2268,7 +2268,7 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_ ...@@ -2268,7 +2268,7 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_
// Skip next optimizations if running low on nodes. Note that // Skip next optimizations if running low on nodes. Note that
// policy_unswitching and policy_maximally_unroll have this check. // policy_unswitching and policy_maximally_unroll have this check.
uint nodes_left = MaxNodeLimit - phase->C->unique(); uint nodes_left = MaxNodeLimit - (uint) phase->C->live_nodes();
if ((2 * _body.size()) > nodes_left) { if ((2 * _body.size()) > nodes_left) {
return true; return true;
} }
......
...@@ -59,7 +59,7 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const { ...@@ -59,7 +59,7 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
if (!_head->is_Loop()) { if (!_head->is_Loop()) {
return false; return false;
} }
uint nodes_left = MaxNodeLimit - phase->C->unique(); uint nodes_left = MaxNodeLimit - phase->C->live_nodes();
if (2 * _body.size() > nodes_left) { if (2 * _body.size() > nodes_left) {
return false; // Too speculative if running low on nodes. return false; // Too speculative if running low on nodes.
} }
......
...@@ -729,7 +729,7 @@ static bool merge_point_too_heavy(Compile* C, Node* region) { ...@@ -729,7 +729,7 @@ static bool merge_point_too_heavy(Compile* C, Node* region) {
for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
weight += region->fast_out(i)->outcnt(); weight += region->fast_out(i)->outcnt();
} }
int nodes_left = MaxNodeLimit - C->unique(); int nodes_left = MaxNodeLimit - C->live_nodes();
if (weight * 8 > nodes_left) { if (weight * 8 > nodes_left) {
#ifndef PRODUCT #ifndef PRODUCT
if (PrintOpto) if (PrintOpto)
......
...@@ -2262,7 +2262,7 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) { ...@@ -2262,7 +2262,7 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) {
Node *slow_ctrl = _fallthroughproj->clone(); Node *slow_ctrl = _fallthroughproj->clone();
transform_later(slow_ctrl); transform_later(slow_ctrl);
_igvn.hash_delete(_fallthroughproj); _igvn.hash_delete(_fallthroughproj);
_fallthroughproj->disconnect_inputs(NULL); _fallthroughproj->disconnect_inputs(NULL, C);
region->init_req(1, slow_ctrl); region->init_req(1, slow_ctrl);
// region inputs are now complete // region inputs are now complete
transform_later(region); transform_later(region);
...@@ -2327,7 +2327,7 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) { ...@@ -2327,7 +2327,7 @@ void PhaseMacroExpand::expand_unlock_node(UnlockNode *unlock) {
Node *slow_ctrl = _fallthroughproj->clone(); Node *slow_ctrl = _fallthroughproj->clone();
transform_later(slow_ctrl); transform_later(slow_ctrl);
_igvn.hash_delete(_fallthroughproj); _igvn.hash_delete(_fallthroughproj);
_fallthroughproj->disconnect_inputs(NULL); _fallthroughproj->disconnect_inputs(NULL, C);
region->init_req(1, slow_ctrl); region->init_req(1, slow_ctrl);
// region inputs are now complete // region inputs are now complete
transform_later(region); transform_later(region);
......
...@@ -342,6 +342,7 @@ void Matcher::match( ) { ...@@ -342,6 +342,7 @@ void Matcher::match( ) {
// Reset node counter so MachNodes start with _idx at 0 // Reset node counter so MachNodes start with _idx at 0
int nodes = C->unique(); // save value int nodes = C->unique(); // save value
C->set_unique(0); C->set_unique(0);
C->reset_dead_node_list();
// Recursively match trees from old space into new space. // Recursively match trees from old space into new space.
// Correct leaves of new-space Nodes; they point to old-space. // Correct leaves of new-space Nodes; they point to old-space.
......
...@@ -57,7 +57,7 @@ void Node::verify_construction() { ...@@ -57,7 +57,7 @@ void Node::verify_construction() {
int new_debug_idx = old_debug_idx+1; int new_debug_idx = old_debug_idx+1;
if (new_debug_idx > 0) { if (new_debug_idx > 0) {
// Arrange that the lowest five decimal digits of _debug_idx // Arrange that the lowest five decimal digits of _debug_idx
// will repeat thos of _idx. In case this is somehow pathological, // will repeat those of _idx. In case this is somehow pathological,
// we continue to assign negative numbers (!) consecutively. // we continue to assign negative numbers (!) consecutively.
const int mod = 100000; const int mod = 100000;
int bump = (int)(_idx - new_debug_idx) % mod; int bump = (int)(_idx - new_debug_idx) % mod;
...@@ -67,7 +67,7 @@ void Node::verify_construction() { ...@@ -67,7 +67,7 @@ void Node::verify_construction() {
} }
Compile::set_debug_idx(new_debug_idx); Compile::set_debug_idx(new_debug_idx);
set_debug_idx( new_debug_idx ); set_debug_idx( new_debug_idx );
assert(Compile::current()->unique() < (uint)MaxNodeLimit, "Node limit exceeded"); assert(Compile::current()->unique() < (UINT_MAX - 1), "Node limit exceeded UINT_MAX");
if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) { if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) {
tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx); tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx);
BREAKPOINT; BREAKPOINT;
...@@ -802,7 +802,7 @@ int Node::replace_edge(Node* old, Node* neww) { ...@@ -802,7 +802,7 @@ int Node::replace_edge(Node* old, Node* neww) {
//-------------------------disconnect_inputs----------------------------------- //-------------------------disconnect_inputs-----------------------------------
// NULL out all inputs to eliminate incoming Def-Use edges. // NULL out all inputs to eliminate incoming Def-Use edges.
// Return the number of edges between 'n' and 'this' // Return the number of edges between 'n' and 'this'
int Node::disconnect_inputs(Node *n) { int Node::disconnect_inputs(Node *n, Compile* C) {
int edges_to_n = 0; int edges_to_n = 0;
uint cnt = req(); uint cnt = req();
...@@ -824,6 +824,9 @@ int Node::disconnect_inputs(Node *n) { ...@@ -824,6 +824,9 @@ int Node::disconnect_inputs(Node *n) {
// Node::destruct requires all out edges be deleted first // Node::destruct requires all out edges be deleted first
// debug_only(destruct();) // no reuse benefit expected // debug_only(destruct();) // no reuse benefit expected
if (edges_to_n == 0) {
C->record_dead_node(_idx);
}
return edges_to_n; return edges_to_n;
} }
......
...@@ -410,7 +410,7 @@ protected: ...@@ -410,7 +410,7 @@ protected:
int replace_edge(Node* old, Node* neww); int replace_edge(Node* old, Node* neww);
// NULL out all inputs to eliminate incoming Def-Use edges. // NULL out all inputs to eliminate incoming Def-Use edges.
// Return the number of edges between 'n' and 'this' // Return the number of edges between 'n' and 'this'
int disconnect_inputs(Node *n); int disconnect_inputs(Node *n, Compile *c);
// Quickly, return true if and only if I am Compile::current()->top(). // Quickly, return true if and only if I am Compile::current()->top().
bool is_top() const { bool is_top() const {
...@@ -458,9 +458,9 @@ public: ...@@ -458,9 +458,9 @@ public:
void replace_by(Node* new_node); void replace_by(Node* new_node);
// Globally replace this node by a given new node, updating all uses // Globally replace this node by a given new node, updating all uses
// and cutting input edges of old node. // and cutting input edges of old node.
void subsume_by(Node* new_node) { void subsume_by(Node* new_node, Compile* c) {
replace_by(new_node); replace_by(new_node);
disconnect_inputs(NULL); disconnect_inputs(NULL, c);
} }
void set_req_X( uint i, Node *n, PhaseIterGVN *igvn ); void set_req_X( uint i, Node *n, PhaseIterGVN *igvn );
// Find the one non-null required input. RegionNode only // Find the one non-null required input. RegionNode only
......
...@@ -513,7 +513,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size ...@@ -513,7 +513,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size
} }
adjust_block_start += diff; adjust_block_start += diff;
b->_nodes.map(idx, replacement); b->_nodes.map(idx, replacement);
mach->subsume_by(replacement); mach->subsume_by(replacement, C);
mach = replacement; mach = replacement;
progress = true; progress = true;
...@@ -1425,7 +1425,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { ...@@ -1425,7 +1425,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) {
jmp_rule[i] = mach->rule(); jmp_rule[i] = mach->rule();
#endif #endif
b->_nodes.map(j, replacement); b->_nodes.map(j, replacement);
mach->subsume_by(replacement); mach->subsume_by(replacement, C);
n = replacement; n = replacement;
mach = replacement; mach = replacement;
} }
......
...@@ -601,8 +601,8 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) ...@@ -601,8 +601,8 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
set_map(entry_map); set_map(entry_map);
do_exits(); do_exits();
if (log) log->done("parse nodes='%d' memory='%d'", if (log) log->done("parse nodes='%d' live='%d' memory='%d'",
C->unique(), C->node_arena()->used()); C->unique(), C->live_nodes(), C->node_arena()->used());
} }
//---------------------------do_all_blocks------------------------------------- //---------------------------do_all_blocks-------------------------------------
......
...@@ -383,6 +383,8 @@ PhaseRemoveUseless::PhaseRemoveUseless( PhaseGVN *gvn, Unique_Node_List *worklis ...@@ -383,6 +383,8 @@ PhaseRemoveUseless::PhaseRemoveUseless( PhaseGVN *gvn, Unique_Node_List *worklis
// Identify nodes that are reachable from below, useful. // Identify nodes that are reachable from below, useful.
C->identify_useful_nodes(_useful); C->identify_useful_nodes(_useful);
// Update dead node list
C->update_dead_node_list(_useful);
// Remove all useless nodes from PhaseValues' recorded types // Remove all useless nodes from PhaseValues' recorded types
// Must be done before disconnecting nodes to preserve hash-table-invariant // Must be done before disconnecting nodes to preserve hash-table-invariant
...@@ -1190,7 +1192,7 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { ...@@ -1190,7 +1192,7 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
} }
} }
} }
C->record_dead_node(dead->_idx);
if (dead->is_macro()) { if (dead->is_macro()) {
C->remove_macro_node(dead); C->remove_macro_node(dead);
} }
...@@ -1199,6 +1201,11 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) { ...@@ -1199,6 +1201,11 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
continue; continue;
} }
} }
// Constant node that has no out-edges and has only one in-edge from
// root is usually dead. However, sometimes reshaping walk makes
// it reachable by adding use edges. So, we will NOT count Con nodes
// as dead to be conservative about the dead node count at any
// given time.
} }
// Aggressively kill globally dead uses // Aggressively kill globally dead uses
......
...@@ -146,7 +146,7 @@ int PhaseChaitin::yank_if_dead_recurse(Node *old, Node *orig_old, Block *current ...@@ -146,7 +146,7 @@ int PhaseChaitin::yank_if_dead_recurse(Node *old, Node *orig_old, Block *current
} }
} }
// Disconnect control and remove precedence edges if any exist // Disconnect control and remove precedence edges if any exist
old->disconnect_inputs(NULL); old->disconnect_inputs(NULL, C);
} }
return blk_adjust; return blk_adjust;
} }
...@@ -513,7 +513,7 @@ void PhaseChaitin::post_allocate_copy_removal() { ...@@ -513,7 +513,7 @@ void PhaseChaitin::post_allocate_copy_removal() {
b->_nodes.remove(j--); phi_dex--; b->_nodes.remove(j--); phi_dex--;
_cfg._bbs.map(phi->_idx,NULL); _cfg._bbs.map(phi->_idx,NULL);
phi->replace_by(u); phi->replace_by(u);
phi->disconnect_inputs(NULL); phi->disconnect_inputs(NULL, C);
continue; continue;
} }
// Note that if value[pidx] exists, then we merged no new values here // Note that if value[pidx] exists, then we merged no new values here
......
...@@ -747,7 +747,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { ...@@ -747,7 +747,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
if( i >= cnt ) { // Found one unique input if( i >= cnt ) { // Found one unique input
assert(Find_id(n) == Find_id(u), "should be the same lrg"); assert(Find_id(n) == Find_id(u), "should be the same lrg");
n->replace_by(u); // Then replace with unique input n->replace_by(u); // Then replace with unique input
n->disconnect_inputs(NULL); n->disconnect_inputs(NULL, C);
b->_nodes.remove(insidx); b->_nodes.remove(insidx);
insidx--; insidx--;
b->_ihrp_index--; b->_ihrp_index--;
......
...@@ -241,13 +241,13 @@ class StringConcat : public ResourceObj { ...@@ -241,13 +241,13 @@ class StringConcat : public ResourceObj {
_stringopts->gvn()->transform(call); _stringopts->gvn()->transform(call);
C->gvn_replace_by(uct, call); C->gvn_replace_by(uct, call);
uct->disconnect_inputs(NULL); uct->disconnect_inputs(NULL, C);
} }
} }
void cleanup() { void cleanup() {
// disconnect the hook node // disconnect the hook node
_arguments->disconnect_inputs(NULL); _arguments->disconnect_inputs(NULL, _stringopts->C);
} }
}; };
...@@ -358,7 +358,7 @@ void StringConcat::eliminate_initialize(InitializeNode* init) { ...@@ -358,7 +358,7 @@ void StringConcat::eliminate_initialize(InitializeNode* init) {
C->gvn_replace_by(mem_proj, mem); C->gvn_replace_by(mem_proj, mem);
} }
C->gvn_replace_by(init, C->top()); C->gvn_replace_by(init, C->top());
init->disconnect_inputs(NULL); init->disconnect_inputs(NULL, C);
} }
Node_List PhaseStringOpts::collect_toString_calls() { Node_List PhaseStringOpts::collect_toString_calls() {
...@@ -1477,6 +1477,6 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) { ...@@ -1477,6 +1477,6 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
kit.replace_call(sc->end(), result); kit.replace_call(sc->end(), result);
// Unhook any hook nodes // Unhook any hook nodes
string_sizes->disconnect_inputs(NULL); string_sizes->disconnect_inputs(NULL, C);
sc->cleanup(); sc->cleanup();
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册