changeset 1833:60a14ad85270

6966411: escape.cpp:450 assert(base->Opcode() == Op_ConP Summary: Execute IGVN optimization before and after Escape Analysis Reviewed-by: never
author kvn
date Fri, 02 Jul 2010 17:30:30 -0700
parents 65b0c03b165d
children a693e51ac197
files src/share/vm/opto/callnode.cpp src/share/vm/opto/compile.cpp src/share/vm/opto/compile.hpp src/share/vm/opto/escape.cpp src/share/vm/opto/escape.hpp
diffstat 5 files changed, 77 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/opto/callnode.cpp	Fri Jul 02 15:01:47 2010 -0700
+++ b/src/share/vm/opto/callnode.cpp	Fri Jul 02 17:30:30 2010 -0700
@@ -1524,7 +1524,7 @@
     ConnectionGraph *cgr = phase->C->congraph();
     PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
     if (cgr != NULL)
-      es = cgr->escape_state(obj_node(), phase);
+      es = cgr->escape_state(obj_node());
     if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
       // Mark it eliminated to update any counters
       this->set_eliminated();
@@ -1627,7 +1627,7 @@
     ConnectionGraph *cgr = phase->C->congraph();
     PointsToNode::EscapeState es = PointsToNode::GlobalEscape;
     if (cgr != NULL)
-      es = cgr->escape_state(obj_node(), phase);
+      es = cgr->escape_state(obj_node());
     if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
       // Mark it eliminated to update any counters
       this->set_eliminated();
--- a/src/share/vm/opto/compile.cpp	Fri Jul 02 15:01:47 2010 -0700
+++ b/src/share/vm/opto/compile.cpp	Fri Jul 02 17:30:30 2010 -0700
@@ -637,34 +637,6 @@
   if (failing())  return;
   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
   Optimize();
   if (failing())  return;
@@ -1601,6 +1573,20 @@
 
   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,
   // peeling, unrolling, etc.
 
--- a/src/share/vm/opto/compile.hpp	Fri Jul 02 15:01:47 2010 -0700
+++ b/src/share/vm/opto/compile.hpp	Fri Jul 02 17:30:30 2010 -0700
@@ -362,6 +362,7 @@
   Node*         macro_node(int idx)             { return _macro_nodes->at(idx); }
   Node*         predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);}
   ConnectionGraph* congraph()                   { return _congraph;}
+  void set_congraph(ConnectionGraph* congraph)  { _congraph = congraph;}
   void add_macro_node(Node * n) {
     //assert(n->is_macro(), "must be a macro node");
     assert(!_macro_nodes->contains(n), " duplicate entry in expand list");
--- a/src/share/vm/opto/escape.cpp	Fri Jul 02 15:01:47 2010 -0700
+++ b/src/share/vm/opto/escape.cpp	Fri Jul 02 17:30:30 2010 -0700
@@ -81,18 +81,18 @@
 }
 #endif
 
-ConnectionGraph::ConnectionGraph(Compile * C) :
+ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
   _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
   _processed(C->comp_arena()),
   _collecting(true),
   _compile(C),
+  _igvn(igvn),
   _node_map(C->comp_arena()) {
 
   _phantom_object = C->top()->_idx,
   add_node(C->top(), PointsToNode::JavaObject, PointsToNode::GlobalEscape,true);
 
   // Add ConP(#NULL) and ConN(#NULL) nodes.
-  PhaseGVN* igvn = C->initial_gvn();
   Node* oop_null = igvn->zerocon(T_OBJECT);
   _oop_null = oop_null->_idx;
   assert(_oop_null < C->unique(), "should be created already");
@@ -182,7 +182,7 @@
     _processed.set(n->_idx);
 }
 
-PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n, PhaseTransform *phase) {
+PointsToNode::EscapeState ConnectionGraph::escape_state(Node *n) {
   uint idx = n->_idx;
   PointsToNode::EscapeState es;
 
@@ -207,22 +207,26 @@
   if (n->uncast()->_idx >= nodes_size())
     return PointsToNode::UnknownEscape;
 
+  PointsToNode::EscapeState orig_es = es;
+
   // compute max escape state of anything this node could point to
   VectorSet ptset(Thread::current()->resource_area());
-  PointsTo(ptset, n, phase);
+  PointsTo(ptset, n);
   for(VectorSetI i(&ptset); i.test() && es != PointsToNode::GlobalEscape; ++i) {
     uint pt = i.elem;
     PointsToNode::EscapeState pes = ptnode_adr(pt)->escape_state();
     if (pes > es)
       es = pes;
   }
-  // cache the computed escape state
-  assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
-  ptnode_adr(idx)->set_escape_state(es);
+  if (orig_es != es) {
+    // cache the computed escape state
+    assert(es != PointsToNode::UnknownEscape, "should have computed an escape state");
+    ptnode_adr(idx)->set_escape_state(es);
+  } // orig_es could be PointsToNode::UnknownEscape
   return es;
 }
 
-void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n, PhaseTransform *phase) {
+void ConnectionGraph::PointsTo(VectorSet &ptset, Node * n) {
   VectorSet visited(Thread::current()->resource_area());
   GrowableArray<uint>  worklist;
 
@@ -990,7 +994,7 @@
   GrowableArray<Node *>  memnode_worklist;
   GrowableArray<PhiNode *>  orig_phis;
 
-  PhaseGVN  *igvn = _compile->initial_gvn();
+  PhaseGVN  *igvn = _igvn;
   uint new_index_start = (uint) _compile->num_alias_types();
   Arena* arena = Thread::current()->resource_area();
   VectorSet visited(arena);
@@ -1012,7 +1016,7 @@
       CallNode *alloc = n->as_Call();
       // copy escape information to call node
       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,
       // see if it is unescaped.
       if (es != PointsToNode::NoEscape || !ptn->_scalar_replaceable)
@@ -1123,7 +1127,7 @@
       }
     } else if (n->is_AddP()) {
       ptset.Clear();
-      PointsTo(ptset, get_addp_base(n), igvn);
+      PointsTo(ptset, get_addp_base(n));
       assert(ptset.Size() == 1, "AddP address is unique");
       uint elem = ptset.getelem(); // Allocation node's index
       if (elem == _phantom_object) {
@@ -1143,7 +1147,7 @@
         continue;  // already processed
       }
       ptset.Clear();
-      PointsTo(ptset, n, igvn);
+      PointsTo(ptset, n);
       if (ptset.Size() == 1) {
         uint elem = ptset.getelem(); // Allocation node's index
         if (elem == _phantom_object) {
@@ -1478,6 +1482,26 @@
   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() {
   Compile* C = _compile;
 
@@ -1492,7 +1516,7 @@
   }
 
   GrowableArray<int> cg_worklist;
-  PhaseGVN* igvn = C->initial_gvn();
+  PhaseGVN* igvn = _igvn;
   bool has_allocations = false;
 
   // Push all useful nodes onto CG list and set their type.
@@ -1661,6 +1685,12 @@
   _collecting = false;
   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;
   if ( has_scalar_replaceable_candidates &&
        C->AliasLevel() >= 3 && EliminateAllocations ) {
@@ -1671,10 +1701,6 @@
 
     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);
 
 #ifdef ASSERT
@@ -1711,7 +1737,7 @@
   int offset = ptn->offset();
   Node* base = get_addp_base(n);
   ptset.Clear();
-  PointsTo(ptset, base, phase);
+  PointsTo(ptset, base);
   int ptset_size = ptset.Size();
 
   // Check if a oop field's initializing value is recorded and add
@@ -1889,7 +1915,7 @@
             arg = get_addp_base(arg);
           }
           ptset.Clear();
-          PointsTo(ptset, arg, phase);
+          PointsTo(ptset, arg);
           for( VectorSetI j(&ptset); j.test(); ++j ) {
             uint pt = j.elem;
             set_escape_state(pt, PointsToNode::ArgEscape);
@@ -1934,7 +1960,7 @@
             }
 
             ptset.Clear();
-            PointsTo(ptset, arg, phase);
+            PointsTo(ptset, arg);
             for( VectorSetI j(&ptset); j.test(); ++j ) {
               uint pt = j.elem;
               if (global_escapes) {
@@ -1970,7 +1996,7 @@
           Node *arg = call->in(i)->uncast();
           set_escape_state(arg->_idx, PointsToNode::GlobalEscape);
           ptset.Clear();
-          PointsTo(ptset, arg, phase);
+          PointsTo(ptset, arg);
           for( VectorSetI j(&ptset); j.test(); ++j ) {
             uint pt = j.elem;
             set_escape_state(pt, PointsToNode::GlobalEscape);
@@ -2433,7 +2459,7 @@
       Node *base = get_addp_base(n);
       // Create a field edge to this node from everything base could point to.
       VectorSet ptset(Thread::current()->resource_area());
-      PointsTo(ptset, base, phase);
+      PointsTo(ptset, base);
       for( VectorSetI i(&ptset); i.test(); ++i ) {
         uint pt = i.elem;
         add_field_edge(pt, n_idx, address_offset(n, phase));
@@ -2501,7 +2527,7 @@
       // For everything "adr_base" could point to, create a deferred edge from
       // this node to each field with the same offset.
       VectorSet ptset(Thread::current()->resource_area());
-      PointsTo(ptset, adr_base, phase);
+      PointsTo(ptset, adr_base);
       int offset = address_offset(adr, phase);
       for( VectorSetI i(&ptset); i.test(); ++i ) {
         uint pt = i.elem;
@@ -2594,7 +2620,7 @@
       // For everything "adr_base" could point to, create a deferred edge
       // to "val" from each field with the same offset.
       VectorSet ptset(Thread::current()->resource_area());
-      PointsTo(ptset, adr_base, phase);
+      PointsTo(ptset, adr_base);
       for( VectorSetI i(&ptset); i.test(); ++i ) {
         uint pt = i.elem;
         add_edge_from_fields(pt, val->_idx, address_offset(adr, phase));
@@ -2638,7 +2664,6 @@
 
 #ifndef PRODUCT
 void ConnectionGraph::dump() {
-  PhaseGVN  *igvn = _compile->initial_gvn();
   bool first = true;
 
   uint size = nodes_size();
@@ -2648,7 +2673,7 @@
 
     if (ptn_type != PointsToNode::JavaObject || ptn->_node == NULL)
       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 (first) {
         tty->cr();
--- a/src/share/vm/opto/escape.hpp	Fri Jul 02 15:01:47 2010 -0700
+++ b/src/share/vm/opto/escape.hpp	Fri Jul 02 17:30:30 2010 -0700
@@ -227,6 +227,7 @@
   uint                     _noop_null; // ConN(#NULL)
 
   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
   PointsToNode *ptnode_adr(uint idx) const {
@@ -257,7 +258,7 @@
   // 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
   // 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
   //  node indices of the source and destination of the edge
@@ -310,7 +311,7 @@
   // Node:  This assumes that escape analysis is run before
   //        PhaseIterGVN creation
   void record_for_optimizer(Node *n) {
-    _compile->record_for_igvn(n);
+    _igvn->_worklist.push(n);
   }
 
   // Set the escape state of a node
@@ -320,16 +321,20 @@
   void verify_escape_state(int nidx, VectorSet& ptset, PhaseTransform* phase);
 
 public:
-  ConnectionGraph(Compile *C);
+  ConnectionGraph(Compile *C, PhaseIterGVN *igvn);
 
   // Check for non-escaping candidates
   static bool has_candidates(Compile *C);
 
+  // Perform escape analysis
+  static void do_analysis(Compile *C, PhaseIterGVN *igvn);
+
   // Compute the escape information
   bool compute_escape();
 
   // escape state of a node
-  PointsToNode::EscapeState escape_state(Node *n, PhaseTransform *phase);
+  PointsToNode::EscapeState escape_state(Node *n);
+
   // other information we have collected
   bool is_scalar_replaceable(Node *n) {
     if (_collecting || (n->_idx >= nodes_size()))