6681577: PIT: some VM tests fails with -XX:+AggressiveOpts in 6u5p b01
Summary: C2 spends > 60% in escape analysis code during test nsk/regression/b4675027.
Reviewed-by: never
--- a/hotspot/src/share/vm/opto/escape.cpp Wed Apr 02 12:09:59 2008 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp Wed Apr 02 16:59:37 2008 -0700
@@ -256,39 +256,49 @@
}
}
-void ConnectionGraph::remove_deferred(uint ni) {
- VectorSet visited(Thread::current()->resource_area());
+void ConnectionGraph::remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited) {
+ // This method is most expensive during ConnectionGraph construction.
+ // Reuse vectorSet and an additional growable array for deferred edges.
+ deferred_edges->clear();
+ visited->Clear();
uint i = 0;
PointsToNode *ptn = ptnode_adr(ni);
- while(i < ptn->edge_count()) {
+ // Mark current edges as visited and move deferred edges to separate array.
+ for (; i < ptn->edge_count(); i++) {
uint t = ptn->edge_target(i);
- PointsToNode *ptt = ptnode_adr(t);
- if (ptn->edge_type(i) != PointsToNode::DeferredEdge) {
- i++;
- } else {
+#ifdef ASSERT
+ assert(!visited->test_set(t), "expecting no duplications");
+#else
+ visited->set(t);
+#endif
+ if (ptn->edge_type(i) == PointsToNode::DeferredEdge) {
ptn->remove_edge(t, PointsToNode::DeferredEdge);
- if(!visited.test_set(t)) {
- for (uint j = 0; j < ptt->edge_count(); j++) {
- uint n1 = ptt->edge_target(j);
- PointsToNode *pt1 = ptnode_adr(n1);
- switch(ptt->edge_type(j)) {
- case PointsToNode::PointsToEdge:
- add_pointsto_edge(ni, n1);
- if(n1 == _phantom_object) {
- // Special case - field set outside (globally escaping).
- ptn->set_escape_state(PointsToNode::GlobalEscape);
- }
- break;
- case PointsToNode::DeferredEdge:
- add_deferred_edge(ni, n1);
- break;
- case PointsToNode::FieldEdge:
- assert(false, "invalid connection graph");
- break;
+ deferred_edges->append(t);
+ }
+ }
+ for (int next = 0; next < deferred_edges->length(); ++next) {
+ uint t = deferred_edges->at(next);
+ PointsToNode *ptt = ptnode_adr(t);
+ for (uint j = 0; j < ptt->edge_count(); j++) {
+ uint n1 = ptt->edge_target(j);
+ if (visited->test_set(n1))
+ continue;
+ switch(ptt->edge_type(j)) {
+ case PointsToNode::PointsToEdge:
+ add_pointsto_edge(ni, n1);
+ if(n1 == _phantom_object) {
+ // Special case - field set outside (globally escaping).
+ ptn->set_escape_state(PointsToNode::GlobalEscape);
}
- }
+ break;
+ case PointsToNode::DeferredEdge:
+ deferred_edges->append(n1);
+ break;
+ case PointsToNode::FieldEdge:
+ assert(false, "invalid connection graph");
+ break;
}
}
}
@@ -1236,8 +1246,10 @@
}
VectorSet ptset(Thread::current()->resource_area());
- GrowableArray<Node*> alloc_worklist;
- GrowableArray<int> worklist;
+ GrowableArray<Node*> alloc_worklist;
+ GrowableArray<int> worklist;
+ GrowableArray<uint> deferred_edges;
+ VectorSet visited(Thread::current()->resource_area());
// remove deferred edges from the graph and collect
// information we will need for type splitting
@@ -1247,7 +1259,7 @@
PointsToNode::NodeType nt = ptn->node_type();
Node *n = ptn->_node;
if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
- remove_deferred(ni);
+ remove_deferred(ni, &deferred_edges, &visited);
if (n->is_AddP()) {
// If this AddP computes an address which may point to more that one
// object, nothing the address points to can be scalar replaceable.
--- a/hotspot/src/share/vm/opto/escape.hpp Wed Apr 02 12:09:59 2008 -0700
+++ b/hotspot/src/share/vm/opto/escape.hpp Wed Apr 02 16:59:37 2008 -0700
@@ -269,7 +269,7 @@
// Remove outgoing deferred edges from the node referenced by "ni".
// Any outgoing edges from the target of the deferred edge are copied
// to "ni".
- void remove_deferred(uint ni);
+ void remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited);
Node_Array _node_map; // used for bookeeping during type splitting
// Used for the following purposes: