changeset 2613:293f68bda347

7050280: assert(u->as_Unlock()->is_eliminated()) failed: sanity Summary: Mark all associated (same box and obj) lock and unlock nodes for elimination if some of them marked already. Reviewed-by: iveresov, never
author kvn
date Sat, 04 Jun 2011 10:36:22 -0700
parents f7d55ea6ee56
children 67c0f5f5deac
files src/share/vm/opto/escape.cpp src/share/vm/opto/macro.cpp src/share/vm/opto/macro.hpp
diffstat 3 files changed, 71 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/opto/escape.cpp	Fri Jun 03 22:31:43 2011 -0700
+++ b/src/share/vm/opto/escape.cpp	Sat Jun 04 10:36:22 2011 -0700
@@ -1747,6 +1747,25 @@
   _collecting = false;
   assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build");
 
+  if (EliminateLocks) {
+    // Mark locks before changing ideal graph.
+    int cnt = C->macro_count();
+    for( int i=0; i < cnt; i++ ) {
+      Node *n = C->macro_node(i);
+      if (n->is_AbstractLock()) { // Lock and Unlock nodes
+        AbstractLockNode* alock = n->as_AbstractLock();
+        if (!alock->is_eliminated()) {
+          PointsToNode::EscapeState es = escape_state(alock->obj_node());
+          assert(es != PointsToNode::UnknownEscape, "should know");
+          if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) {
+            // Mark it eliminated
+            alock->set_eliminated();
+          }
+        }
+      }
+    }
+  }
+
 #ifndef PRODUCT
   if (PrintEscapeAnalysis) {
     dump(); // Dump ConnectionGraph
--- a/src/share/vm/opto/macro.cpp	Fri Jun 03 22:31:43 2011 -0700
+++ b/src/share/vm/opto/macro.cpp	Sat Jun 04 10:36:22 2011 -0700
@@ -1693,25 +1693,31 @@
                          OptoRuntime::new_array_Java());
 }
 
-
-// we have determined that this lock/unlock can be eliminated, we simply
-// eliminate the node without expanding it.
-//
-// Note:  The membar's associated with the lock/unlock are currently not
-//        eliminated.  This should be investigated as a future enhancement.
-//
-bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
-
+//-----------------------mark_eliminated_locking_nodes-----------------------
+// During EA obj may point to several objects but after few ideal graph
+// transformations (CCP) it may point to only one non escaping object
+// (but still using phi), corresponding locks and unlocks will be marked
+// for elimination. Later obj could be replaced with a new node (new phi)
+// and which does not have escape information. And later after some graph
+// reshape other locks and unlocks (which were not marked for elimination
+// before) are connected to this new obj (phi) but they still will not be
+// marked for elimination since new obj has no escape information.
+// Mark all associated (same box and obj) lock and unlock nodes for
+// elimination if some of them marked already.
+void PhaseMacroExpand::mark_eliminated_locking_nodes(AbstractLockNode *alock) {
   if (!alock->is_eliminated()) {
-    return false;
+    return;
   }
-  if (alock->is_Lock() && !alock->is_coarsened()) {
+  if (!alock->is_coarsened()) { // Eliminated by EA
       // Create new "eliminated" BoxLock node and use it
       // in monitor debug info for the same object.
       BoxLockNode* oldbox = alock->box_node()->as_BoxLock();
       Node* obj = alock->obj_node();
       if (!oldbox->is_eliminated()) {
         BoxLockNode* newbox = oldbox->clone()->as_BoxLock();
+        // Note: BoxLock node is marked eliminated only here
+        // and it is used to indicate that all associated lock
+        // and unlock nodes are marked for elimination.
         newbox->set_eliminated();
         transform_later(newbox);
         // Replace old box node with new box for all users
@@ -1720,22 +1726,14 @@
 
           bool next_edge = true;
           Node* u = oldbox->raw_out(i);
-          if (u == alock) {
-            i++;
-            continue; // It will be removed below
-          }
-          if (u->is_Lock() &&
-              u->as_Lock()->obj_node() == obj &&
-              // oldbox could be referenced in debug info also
-              u->as_Lock()->box_node() == oldbox) {
-            assert(u->as_Lock()->is_eliminated(), "sanity");
+          if (u->is_AbstractLock() &&
+              u->as_AbstractLock()->obj_node() == obj &&
+              u->as_AbstractLock()->box_node() == oldbox) {
+            // Mark all associated locks and unlocks.
+            u->as_AbstractLock()->set_eliminated();
             _igvn.hash_delete(u);
             u->set_req(TypeFunc::Parms + 1, newbox);
             next_edge = false;
-#ifdef ASSERT
-          } else if (u->is_Unlock() && u->as_Unlock()->obj_node() == obj) {
-            assert(u->as_Unlock()->is_eliminated(), "sanity");
-#endif
           }
           // Replace old box in monitor debug info.
           if (u->is_SafePoint() && u->as_SafePoint()->jvms()) {
@@ -1761,8 +1759,27 @@
           if (next_edge) i++;
         } // for (uint i = 0; i < oldbox->outcnt();)
       } // if (!oldbox->is_eliminated())
-  } // if (alock->is_Lock() && !lock->is_coarsened())
+  } // if (!alock->is_coarsened())
+}
+
+// we have determined that this lock/unlock can be eliminated, we simply
+// eliminate the node without expanding it.
+//
+// Note:  The membar's associated with the lock/unlock are currently not
+//        eliminated.  This should be investigated as a future enhancement.
+//
+bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) {
 
+  if (!alock->is_eliminated()) {
+    return false;
+  }
+#ifdef ASSERT
+  if (alock->is_Lock() && !alock->is_coarsened()) {
+    // Check that new "eliminated" BoxLock node is created.
+    BoxLockNode* oldbox = alock->box_node()->as_BoxLock();
+    assert(oldbox->is_eliminated(), "should be done already");
+  }
+#endif
   CompileLog* log = C->log();
   if (log != NULL) {
     log->head("eliminate_lock lock='%d'",
@@ -2145,6 +2162,15 @@
   if (C->macro_count() == 0)
     return false;
   // First, attempt to eliminate locks
+  int cnt = C->macro_count();
+  for (int i=0; i < cnt; i++) {
+    Node *n = C->macro_node(i);
+    if (n->is_AbstractLock()) { // Lock and Unlock nodes
+      // Before elimination mark all associated (same box and obj)
+      // lock and unlock nodes.
+      mark_eliminated_locking_nodes(n->as_AbstractLock());
+    }
+  }
   bool progress = true;
   while (progress) {
     progress = false;
--- a/src/share/vm/opto/macro.hpp	Fri Jun 03 22:31:43 2011 -0700
+++ b/src/share/vm/opto/macro.hpp	Sat Jun 04 10:36:22 2011 -0700
@@ -92,6 +92,7 @@
   void process_users_of_allocation(AllocateNode *alloc);
 
   void eliminate_card_mark(Node *cm);
+  void mark_eliminated_locking_nodes(AbstractLockNode *alock);
   bool eliminate_locking_node(AbstractLockNode *alock);
   void expand_lock_node(LockNode *lock);
   void expand_unlock_node(UnlockNode *unlock);