mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 03:24:38 +02:00
6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP
Execute IGVN optimization before and after Escape Analysis Reviewed-by: never
This commit is contained in:
parent
bf1ca00b7c
commit
cc513a8564
5 changed files with 77 additions and 60 deletions
|
@ -1524,7 +1524,7 @@ Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
ConnectionGraph *cgr = phase->C->congraph();
|
ConnectionGraph *cgr = phase->C->congraph();
|
||||||
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
|
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
|
||||||
if (cgr != NULL)
|
if (cgr != NULL)
|
||||||
es = cgr->escape_state(obj_node(), phase);
|
es = cgr->escape_state(obj_node());
|
||||||
if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
|
if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
|
||||||
// Mark it eliminated to update any counters
|
// Mark it eliminated to update any counters
|
||||||
this->set_eliminated();
|
this->set_eliminated();
|
||||||
|
@ -1627,7 +1627,7 @@ Node *UnlockNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||||
ConnectionGraph *cgr = phase->C->congraph();
|
ConnectionGraph *cgr = phase->C->congraph();
|
||||||
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
|
PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
|
||||||
if (cgr != NULL)
|
if (cgr != NULL)
|
||||||
es = cgr->escape_state(obj_node(), phase);
|
es = cgr->escape_state(obj_node());
|
||||||
if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
|
if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
|
||||||
// Mark it eliminated to update any counters
|
// Mark it eliminated to update any counters
|
||||||
this->set_eliminated();
|
this->set_eliminated();
|
||||||
|
|
|
@ -637,34 +637,6 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||||
if (failing()) return;
|
if (failing()) return;
|
||||||
NOT_PRODUCT( verify_graph_edges(); )
|
NOT_PRODUCT( verify_graph_edges(); )
|
||||||
|
|
||||||
// Perform escape analysis
|
|
||||||
if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
|
|
||||||
TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
|
|
||||||
// Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction.
|
|
||||||
PhaseGVN* igvn = initial_gvn();
|
|
||||||
Node* oop_null = igvn->zerocon(T_OBJECT);
|
|
||||||
Node* noop_null = igvn->zerocon(T_NARROWOOP);
|
|
||||||
|
|
||||||
_congraph = new(comp_arena()) ConnectionGraph(this);
|
|
||||||
bool has_non_escaping_obj = _congraph->compute_escape();
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
|
||||||
if (PrintEscapeAnalysis) {
|
|
||||||
_congraph->dump();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Cleanup.
|
|
||||||
if (oop_null->outcnt() == 0)
|
|
||||||
igvn->hash_delete(oop_null);
|
|
||||||
if (noop_null->outcnt() == 0)
|
|
||||||
igvn->hash_delete(noop_null);
|
|
||||||
|
|
||||||
if (!has_non_escaping_obj) {
|
|
||||||
_congraph = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (failing()) return;
|
|
||||||
}
|
|
||||||
// Now optimize
|
// Now optimize
|
||||||
Optimize();
|
Optimize();
|
||||||
if (failing()) return;
|
if (failing()) return;
|
||||||
|
@ -1601,6 +1573,20 @@ void Compile::Optimize() {
|
||||||
|
|
||||||
if (failing()) return;
|
if (failing()) return;
|
||||||
|
|
||||||
|
// Perform escape analysis
|
||||||
|
if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) {
|
||||||
|
TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, true);
|
||||||
|
ConnectionGraph::do_analysis(this, &igvn);
|
||||||
|
|
||||||
|
if (failing()) return;
|
||||||
|
|
||||||
|
igvn.optimize();
|
||||||
|
print_method("Iter GVN 3", 2);
|
||||||
|
|
||||||
|
if (failing()) return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Loop transforms on the ideal graph. Range Check Elimination,
|
// Loop transforms on the ideal graph. Range Check Elimination,
|
||||||
// peeling, unrolling, etc.
|
// peeling, unrolling, etc.
|
||||||
|
|
||||||
|
|
|
@ -362,6 +362,7 @@ class Compile : public Phase {
|
||||||
Node* macro_node(int idx) { return _macro_nodes->at(idx); }
|
Node* macro_node(int idx) { return _macro_nodes->at(idx); }
|
||||||
Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);}
|
Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);}
|
||||||
ConnectionGraph* congraph() { return _congraph;}
|
ConnectionGraph* congraph() { return _congraph;}
|
||||||
|
void set_congraph(ConnectionGraph* congraph) { _congraph = congraph;}
|
||||||
void add_macro_node(Node * n) {
|
void add_macro_node(Node * n) {
|
||||||
//assert(n->is_macro(), "must be a macro node");
|
//assert(n->is_macro(), "must be a macro node");
|
||||||
assert(!_macro_nodes->contains(n), " duplicate entry in expand list");
|
assert(!_macro_nodes->contains(n), " duplicate entry in expand list");
|
||||||
|
|
|
@ -81,18 +81,18 @@ void PointsToNode::dump(bool print_state) const {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConnectionGraph::ConnectionGraph(Compile * C) :
|
ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
|
||||||
_nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
|
_nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
|
||||||
_processed(C->comp_arena()),
|
_processed(C->comp_arena()),
|
||||||
_collecting(true),
|
_collecting(true),
|
||||||
_compile(C),
|
_compile(C),
|
||||||
|
_igvn(igvn),
|
||||||
_node_map(C->comp_arena()) {
|
_node_map(C->comp_arena()) {
|
||||||
|
|
||||||
_phantom_object = C->top()->_idx,
|
_phantom_object = C->top()->_idx,
|
||||||
add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true);
|
add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true);
|
||||||
|
|
||||||
// Add ConP(#NULL) and ConN(#NULL) nodes.
|
// Add ConP(#NULL) and ConN(#NULL) nodes.
|
||||||
PhaseGVN* igvn = C->initial_gvn();
|
|
||||||
Node* oop_null = igvn->zerocon(T_OBJECT);
|
Node* oop_null = igvn->zerocon(T_OBJECT);
|
||||||
_oop_null = oop_null->_idx;
|
_oop_null = oop_null->_idx;
|
||||||
assert(_oop_null < C->unique(), "should be created already");
|
assert(_oop_null < C->unique(), "should be created already");
|
||||||
|
@ -182,7 +182,7 @@ void ConnectionGraph::add_node(Node *n, PointsToNode::NodeType nt,
|
||||||
_processed.set(n->_idx);
|
_processed.set(n->_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform *phase) {
|
PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
|
||||||
uint idx = n->_idx;
|
uint idx = n->_idx;
|
||||||
PointsToNode::EscapeState es;
|
PointsToNode::EscapeState es;
|
||||||
|
|
||||||
|
@ -207,22 +207,26 @@ PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform
|
||||||
if (n->uncast()->_idx >= nodes_size())
|
if (n->uncast()->_idx >= nodes_size())
|
||||||
return PointsToNode::UnknownEscape;
|
return PointsToNode::UnknownEscape;
|
||||||
|
|
||||||
|
PointsToNode::EscapeState orig_es = es;
|
||||||
|
|
||||||
// compute max escape state of anything this node could point to
|
// compute max escape state of anything this node could point to
|
||||||
VectorSet ptset(Thread::current()->resource_area());
|
VectorSet ptset(Thread::current()->resource_area());
|
||||||
PointsTo(ptset, n, phase);
|
PointsTo(ptset, n);
|
||||||
for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
|
for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
|
||||||
uint pt = i.elem;
|
uint pt = i.elem;
|
||||||
PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
|
PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
|
||||||
if (pes > es)
|
if (pes > es)
|
||||||
es = pes;
|
es = pes;
|
||||||
}
|
}
|
||||||
|
if (orig_es != es) {
|
||||||
// cache the computed escape state
|
// cache the computed escape state
|
||||||
assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
|
assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
|
||||||
ptnode_adr(idx)->set_escape_state(es);
|
ptnode_adr(idx)->set_escape_state(es);
|
||||||
|
} // orig_es could be PointsToNode::UnknownEscape
|
||||||
return es;
|
return es;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) {
|
void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
|
||||||
VectorSet visited(Thread::current()->resource_area());
|
VectorSet visited(Thread::current()->resource_area());
|
||||||
GrowableArray<uint> worklist;
|
GrowableArray<uint> worklist;
|
||||||
|
|
||||||
|
@ -990,7 +994,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
||||||
GrowableArray<Node *> memnode_worklist;
|
GrowableArray<Node *> memnode_worklist;
|
||||||
GrowableArray<PhiNode *> orig_phis;
|
GrowableArray<PhiNode *> orig_phis;
|
||||||
|
|
||||||
PhaseGVN *igvn = _compile->initial_gvn();
|
PhaseGVN *igvn = _igvn;
|
||||||
uint new_index_start = (uint) _compile->num_alias_types();
|
uint new_index_start = (uint) _compile->num_alias_types();
|
||||||
Arena* arena = Thread::current()->resource_area();
|
Arena* arena = Thread::current()->resource_area();
|
||||||
VectorSet visited(arena);
|
VectorSet visited(arena);
|
||||||
|
@ -1012,7 +1016,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
||||||
CallNode *alloc = n->as_Call();
|
CallNode *alloc = n->as_Call();
|
||||||
// copy escape information to call node
|
// copy escape information to call node
|
||||||
PointsToNode* ptn = ptnode_adr(alloc->_idx);
|
PointsToNode* ptn = ptnode_adr(alloc->_idx);
|
||||||
PointsToNode::EscapeState es = escape_state(alloc, igvn);
|
PointsToNode::EscapeState es = escape_state(alloc);
|
||||||
// We have an allocation or call which returns a Java object,
|
// We have an allocation or call which returns a Java object,
|
||||||
// see if it is unescaped.
|
// see if it is unescaped.
|
||||||
if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable)
|
if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable)
|
||||||
|
@ -1123,7 +1127,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
||||||
}
|
}
|
||||||
} else if (n->is_AddP()) {
|
} else if (n->is_AddP()) {
|
||||||
ptset.Clear();
|
ptset.Clear();
|
||||||
PointsTo(ptset, get_addp_base(n), igvn);
|
PointsTo(ptset, get_addp_base(n));
|
||||||
assert(ptset.Size() == 1, "AddP address is unique");
|
assert(ptset.Size() == 1, "AddP address is unique");
|
||||||
uint elem = ptset.getelem(); // Allocation node's index
|
uint elem = ptset.getelem(); // Allocation node's index
|
||||||
if (elem == _phantom_object) {
|
if (elem == _phantom_object) {
|
||||||
|
@ -1143,7 +1147,7 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
|
||||||
continue; // already processed
|
continue; // already processed
|
||||||
}
|
}
|
||||||
ptset.Clear();
|
ptset.Clear();
|
||||||
PointsTo(ptset, n, igvn);
|
PointsTo(ptset, n);
|
||||||
if (ptset.Size() == 1) {
|
if (ptset.Size() == 1) {
|
||||||
uint elem = ptset.getelem(); // Allocation node's index
|
uint elem = ptset.getelem(); // Allocation node's index
|
||||||
if (elem == _phantom_object) {
|
if (elem == _phantom_object) {
|
||||||
|
@ -1478,6 +1482,26 @@ bool ConnectionGraph::has_candidates(Compile *C) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConnectionGraph::do_analysis(Compile *C, PhaseIterGVN *igvn) {
|
||||||
|
// Add ConP#NULL and ConN#NULL nodes before ConnectionGraph construction
|
||||||
|
// to create space for them in ConnectionGraph::_nodes[].
|
||||||
|
Node* oop_null = igvn->zerocon(T_OBJECT);
|
||||||
|
Node* noop_null = igvn->zerocon(T_NARROWOOP);
|
||||||
|
|
||||||
|
ConnectionGraph* congraph = new(C->comp_arena()) ConnectionGraph(C, igvn);
|
||||||
|
// Perform escape analysis
|
||||||
|
if (congraph->compute_escape()) {
|
||||||
|
// There are non escaping objects.
|
||||||
|
C->set_congraph(congraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup.
|
||||||
|
if (oop_null->outcnt() == 0)
|
||||||
|
igvn->hash_delete(oop_null);
|
||||||
|
if (noop_null->outcnt() == 0)
|
||||||
|
igvn->hash_delete(noop_null);
|
||||||
|
}
|
||||||
|
|
||||||
bool ConnectionGraph::compute_escape() {
|
bool ConnectionGraph::compute_escape() {
|
||||||
Compile* C = _compile;
|
Compile* C = _compile;
|
||||||
|
|
||||||
|
@ -1492,7 +1516,7 @@ bool ConnectionGraph::compute_escape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
GrowableArray<int> cg_worklist;
|
GrowableArray<int> cg_worklist;
|
||||||
PhaseGVN* igvn = C->initial_gvn();
|
PhaseGVN* igvn = _igvn;
|
||||||
bool has_allocations = false;
|
bool has_allocations = false;
|
||||||
|
|
||||||
// Push all useful nodes onto CG list and set their type.
|
// Push all useful nodes onto CG list and set their type.
|
||||||
|
@ -1661,6 +1685,12 @@ bool ConnectionGraph::compute_escape() {
|
||||||
_collecting = false;
|
_collecting = false;
|
||||||
assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
|
assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
|
||||||
|
|
||||||
|
#ifndef PRODUCT
|
||||||
|
if (PrintEscapeAnalysis) {
|
||||||
|
dump(); // Dump ConnectionGraph
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0;
|
bool has_scalar_replaceable_candidates = alloc_worklist.length() > 0;
|
||||||
if ( has_scalar_replaceable_candidates &&
|
if ( has_scalar_replaceable_candidates &&
|
||||||
C->AliasLevel() >= 3 && EliminateAllocations ) {
|
C->AliasLevel() >= 3 && EliminateAllocations ) {
|
||||||
|
@ -1671,10 +1701,6 @@ bool ConnectionGraph::compute_escape() {
|
||||||
|
|
||||||
if (C->failing()) return false;
|
if (C->failing()) return false;
|
||||||
|
|
||||||
// Clean up after split unique types.
|
|
||||||
ResourceMark rm;
|
|
||||||
PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn());
|
|
||||||
|
|
||||||
C->print_method("After Escape Analysis", 2);
|
C->print_method("After Escape Analysis", 2);
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -1711,7 +1737,7 @@ void ConnectionGraph::verify_escape_state(int nidx, VectorSet& ptset, PhaseTrans
|
||||||
int offset = ptn->offset();
|
int offset = ptn->offset();
|
||||||
Node* base = get_addp_base(n);
|
Node* base = get_addp_base(n);
|
||||||
ptset.Clear();
|
ptset.Clear();
|
||||||
PointsTo(ptset, base, phase);
|
PointsTo(ptset, base);
|
||||||
int ptset_size = ptset.Size();
|
int ptset_size = ptset.Size();
|
||||||
|
|
||||||
// Check if a oop field's initializing value is recorded and add
|
// Check if a oop field's initializing value is recorded and add
|
||||||
|
@ -1889,7 +1915,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
|
||||||
arg = get_addp_base(arg);
|
arg = get_addp_base(arg);
|
||||||
}
|
}
|
||||||
ptset.Clear();
|
ptset.Clear();
|
||||||
PointsTo(ptset, arg, phase);
|
PointsTo(ptset, arg);
|
||||||
for( VectorSetI j(&ptset); j.test(); ++j ) {
|
for( VectorSetI j(&ptset); j.test(); ++j ) {
|
||||||
uint pt = j.elem;
|
uint pt = j.elem;
|
||||||
set_escape_state(pt, PointsToNode::ArgEscape);
|
set_escape_state(pt, PointsToNode::ArgEscape);
|
||||||
|
@ -1934,7 +1960,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
|
||||||
}
|
}
|
||||||
|
|
||||||
ptset.Clear();
|
ptset.Clear();
|
||||||
PointsTo(ptset, arg, phase);
|
PointsTo(ptset, arg);
|
||||||
for( VectorSetI j(&ptset); j.test(); ++j ) {
|
for( VectorSetI j(&ptset); j.test(); ++j ) {
|
||||||
uint pt = j.elem;
|
uint pt = j.elem;
|
||||||
if (global_escapes) {
|
if (global_escapes) {
|
||||||
|
@ -1970,7 +1996,7 @@ void ConnectionGraph::process_call_arguments(CallNode *call, PhaseTransform *pha
|
||||||
Node *arg = call->in(i)->uncast();
|
Node *arg = call->in(i)->uncast();
|
||||||
set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
|
set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
|
||||||
ptset.Clear();
|
ptset.Clear();
|
||||||
PointsTo(ptset, arg, phase);
|
PointsTo(ptset, arg);
|
||||||
for( VectorSetI j(&ptset); j.test(); ++j ) {
|
for( VectorSetI j(&ptset); j.test(); ++j ) {
|
||||||
uint pt = j.elem;
|
uint pt = j.elem;
|
||||||
set_escape_state(pt, PointsToNode::GlobalEscape);
|
set_escape_state(pt, PointsToNode::GlobalEscape);
|
||||||
|
@ -2433,7 +2459,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
|
||||||
Node *base = get_addp_base(n);
|
Node *base = get_addp_base(n);
|
||||||
// Create a field edge to this node from everything base could point to.
|
// Create a field edge to this node from everything base could point to.
|
||||||
VectorSet ptset(Thread::current()->resource_area());
|
VectorSet ptset(Thread::current()->resource_area());
|
||||||
PointsTo(ptset, base, phase);
|
PointsTo(ptset, base);
|
||||||
for( VectorSetI i(&ptset); i.test(); ++i ) {
|
for( VectorSetI i(&ptset); i.test(); ++i ) {
|
||||||
uint pt = i.elem;
|
uint pt = i.elem;
|
||||||
add_field_edge(pt, n_idx, address_offset(n, phase));
|
add_field_edge(pt, n_idx, address_offset(n, phase));
|
||||||
|
@ -2501,7 +2527,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
|
||||||
// For everything "adr_base" could point to, create a deferred edge from
|
// For everything "adr_base" could point to, create a deferred edge from
|
||||||
// this node to each field with the same offset.
|
// this node to each field with the same offset.
|
||||||
VectorSet ptset(Thread::current()->resource_area());
|
VectorSet ptset(Thread::current()->resource_area());
|
||||||
PointsTo(ptset, adr_base, phase);
|
PointsTo(ptset, adr_base);
|
||||||
int offset = address_offset(adr, phase);
|
int offset = address_offset(adr, phase);
|
||||||
for( VectorSetI i(&ptset); i.test(); ++i ) {
|
for( VectorSetI i(&ptset); i.test(); ++i ) {
|
||||||
uint pt = i.elem;
|
uint pt = i.elem;
|
||||||
|
@ -2594,7 +2620,7 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
|
||||||
// For everything "adr_base" could point to, create a deferred edge
|
// For everything "adr_base" could point to, create a deferred edge
|
||||||
// to "val" from each field with the same offset.
|
// to "val" from each field with the same offset.
|
||||||
VectorSet ptset(Thread::current()->resource_area());
|
VectorSet ptset(Thread::current()->resource_area());
|
||||||
PointsTo(ptset, adr_base, phase);
|
PointsTo(ptset, adr_base);
|
||||||
for( VectorSetI i(&ptset); i.test(); ++i ) {
|
for( VectorSetI i(&ptset); i.test(); ++i ) {
|
||||||
uint pt = i.elem;
|
uint pt = i.elem;
|
||||||
add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
|
add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
|
||||||
|
@ -2638,7 +2664,6 @@ void ConnectionGraph::build_connection_graph(Node *n, PhaseTransform *phase) {
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void ConnectionGraph::dump() {
|
void ConnectionGraph::dump() {
|
||||||
PhaseGVN *igvn = _compile->initial_gvn();
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
uint size = nodes_size();
|
uint size = nodes_size();
|
||||||
|
@ -2648,7 +2673,7 @@ void ConnectionGraph::dump() {
|
||||||
|
|
||||||
if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL)
|
if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL)
|
||||||
continue;
|
continue;
|
||||||
PointsToNode::EscapeState es = escape_state(ptn->_node, igvn);
|
PointsToNode::EscapeState es = escape_state(ptn->_node);
|
||||||
if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
|
if (ptn->_node->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) {
|
||||||
if (first) {
|
if (first) {
|
||||||
tty->cr();
|
tty->cr();
|
||||||
|
|
|
@ -227,6 +227,7 @@ private:
|
||||||
uint _noop_null; // ConN(#NULL)
|
uint _noop_null; // ConN(#NULL)
|
||||||
|
|
||||||
Compile * _compile; // Compile object for current compilation
|
Compile * _compile; // Compile object for current compilation
|
||||||
|
PhaseIterGVN * _igvn; // Value numbering
|
||||||
|
|
||||||
// Address of an element in _nodes. Used when the element is to be modified
|
// Address of an element in _nodes. Used when the element is to be modified
|
||||||
PointsToNode *ptnode_adr(uint idx) const {
|
PointsToNode *ptnode_adr(uint idx) const {
|
||||||
|
@ -257,7 +258,7 @@ private:
|
||||||
// walk the connection graph starting at the node corresponding to "n" and
|
// walk the connection graph starting at the node corresponding to "n" and
|
||||||
// add the index of everything it could point to, to "ptset". This may cause
|
// add the index of everything it could point to, to "ptset". This may cause
|
||||||
// Phi's encountered to get (re)processed (which requires "phase".)
|
// Phi's encountered to get (re)processed (which requires "phase".)
|
||||||
void PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase);
|
void PointsTo(VectorSet &ptset, Node * n);
|
||||||
|
|
||||||
// Edge manipulation. The "from_i" and "to_i" arguments are the
|
// Edge manipulation. The "from_i" and "to_i" arguments are the
|
||||||
// node indices of the source and destination of the edge
|
// node indices of the source and destination of the edge
|
||||||
|
@ -310,7 +311,7 @@ private:
|
||||||
// Node: This assumes that escape analysis is run before
|
// Node: This assumes that escape analysis is run before
|
||||||
// PhaseIterGVN creation
|
// PhaseIterGVN creation
|
||||||
void record_for_optimizer(Node *n) {
|
void record_for_optimizer(Node *n) {
|
||||||
_compile->record_for_igvn(n);
|
_igvn->_worklist.push(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the escape state of a node
|
// Set the escape state of a node
|
||||||
|
@ -320,16 +321,20 @@ private:
|
||||||
void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase);
|
void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ConnectionGraph(Compile *C);
|
ConnectionGraph(Compile *C, PhaseIterGVN *igvn);
|
||||||
|
|
||||||
// Check for non-escaping candidates
|
// Check for non-escaping candidates
|
||||||
static bool has_candidates(Compile *C);
|
static bool has_candidates(Compile *C);
|
||||||
|
|
||||||
|
// Perform escape analysis
|
||||||
|
static void do_analysis(Compile *C, PhaseIterGVN *igvn);
|
||||||
|
|
||||||
// Compute the escape information
|
// Compute the escape information
|
||||||
bool compute_escape();
|
bool compute_escape();
|
||||||
|
|
||||||
// escape state of a node
|
// escape state of a node
|
||||||
PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase);
|
PointsToNode::EscapeState escape_state(Node *n);
|
||||||
|
|
||||||
// other information we have collected
|
// other information we have collected
|
||||||
bool is_scalar_replaceable(Node *n) {
|
bool is_scalar_replaceable(Node *n) {
|
||||||
if (_collecting || (n->_idx >= nodes_size()))
|
if (_collecting || (n->_idx >= nodes_size()))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue