Sat, 04 Jun 2011 10:36:22 -0700
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
1.1 --- a/src/share/vm/opto/escape.cpp Fri Jun 03 22:31:43 2011 -0700 1.2 +++ b/src/share/vm/opto/escape.cpp Sat Jun 04 10:36:22 2011 -0700 1.3 @@ -1747,6 +1747,25 @@ 1.4 _collecting = false; 1.5 assert(C->unique() == nodes_size(), "there should be no new ideal nodes during ConnectionGraph build"); 1.6 1.7 + if (EliminateLocks) { 1.8 + // Mark locks before changing ideal graph. 1.9 + int cnt = C->macro_count(); 1.10 + for( int i=0; i < cnt; i++ ) { 1.11 + Node *n = C->macro_node(i); 1.12 + if (n->is_AbstractLock()) { // Lock and Unlock nodes 1.13 + AbstractLockNode* alock = n->as_AbstractLock(); 1.14 + if (!alock->is_eliminated()) { 1.15 + PointsToNode::EscapeState es = escape_state(alock->obj_node()); 1.16 + assert(es != PointsToNode::UnknownEscape, "should know"); 1.17 + if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { 1.18 + // Mark it eliminated 1.19 + alock->set_eliminated(); 1.20 + } 1.21 + } 1.22 + } 1.23 + } 1.24 + } 1.25 + 1.26 #ifndef PRODUCT 1.27 if (PrintEscapeAnalysis) { 1.28 dump(); // Dump ConnectionGraph
2.1 --- a/src/share/vm/opto/macro.cpp Fri Jun 03 22:31:43 2011 -0700 2.2 +++ b/src/share/vm/opto/macro.cpp Sat Jun 04 10:36:22 2011 -0700 2.3 @@ -1693,25 +1693,31 @@ 2.4 OptoRuntime::new_array_Java()); 2.5 } 2.6 2.7 - 2.8 -// we have determined that this lock/unlock can be eliminated, we simply 2.9 -// eliminate the node without expanding it. 2.10 -// 2.11 -// Note: The membar's associated with the lock/unlock are currently not 2.12 -// eliminated. This should be investigated as a future enhancement. 2.13 -// 2.14 -bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { 2.15 - 2.16 +//-----------------------mark_eliminated_locking_nodes----------------------- 2.17 +// During EA obj may point to several objects but after few ideal graph 2.18 +// transformations (CCP) it may point to only one non escaping object 2.19 +// (but still using phi), corresponding locks and unlocks will be marked 2.20 +// for elimination. Later obj could be replaced with a new node (new phi) 2.21 +// and which does not have escape information. And later after some graph 2.22 +// reshape other locks and unlocks (which were not marked for elimination 2.23 +// before) are connected to this new obj (phi) but they still will not be 2.24 +// marked for elimination since new obj has no escape information. 2.25 +// Mark all associated (same box and obj) lock and unlock nodes for 2.26 +// elimination if some of them marked already. 2.27 +void PhaseMacroExpand::mark_eliminated_locking_nodes(AbstractLockNode *alock) { 2.28 if (!alock->is_eliminated()) { 2.29 - return false; 2.30 + return; 2.31 } 2.32 - if (alock->is_Lock() && !alock->is_coarsened()) { 2.33 + if (!alock->is_coarsened()) { // Eliminated by EA 2.34 // Create new "eliminated" BoxLock node and use it 2.35 // in monitor debug info for the same object. 2.36 BoxLockNode* oldbox = alock->box_node()->as_BoxLock(); 2.37 Node* obj = alock->obj_node(); 2.38 if (!oldbox->is_eliminated()) { 2.39 BoxLockNode* newbox = oldbox->clone()->as_BoxLock(); 2.40 + // Note: BoxLock node is marked eliminated only here 2.41 + // and it is used to indicate that all associated lock 2.42 + // and unlock nodes are marked for elimination. 2.43 newbox->set_eliminated(); 2.44 transform_later(newbox); 2.45 // Replace old box node with new box for all users 2.46 @@ -1720,22 +1726,14 @@ 2.47 2.48 bool next_edge = true; 2.49 Node* u = oldbox->raw_out(i); 2.50 - if (u == alock) { 2.51 - i++; 2.52 - continue; // It will be removed below 2.53 - } 2.54 - if (u->is_Lock() && 2.55 - u->as_Lock()->obj_node() == obj && 2.56 - // oldbox could be referenced in debug info also 2.57 - u->as_Lock()->box_node() == oldbox) { 2.58 - assert(u->as_Lock()->is_eliminated(), "sanity"); 2.59 + if (u->is_AbstractLock() && 2.60 + u->as_AbstractLock()->obj_node() == obj && 2.61 + u->as_AbstractLock()->box_node() == oldbox) { 2.62 + // Mark all associated locks and unlocks. 2.63 + u->as_AbstractLock()->set_eliminated(); 2.64 _igvn.hash_delete(u); 2.65 u->set_req(TypeFunc::Parms + 1, newbox); 2.66 next_edge = false; 2.67 -#ifdef ASSERT 2.68 - } else if (u->is_Unlock() && u->as_Unlock()->obj_node() == obj) { 2.69 - assert(u->as_Unlock()->is_eliminated(), "sanity"); 2.70 -#endif 2.71 } 2.72 // Replace old box in monitor debug info. 2.73 if (u->is_SafePoint() && u->as_SafePoint()->jvms()) { 2.74 @@ -1761,8 +1759,27 @@ 2.75 if (next_edge) i++; 2.76 } // for (uint i = 0; i < oldbox->outcnt();) 2.77 } // if (!oldbox->is_eliminated()) 2.78 - } // if (alock->is_Lock() && !lock->is_coarsened()) 2.79 + } // if (!alock->is_coarsened()) 2.80 +} 2.81 2.82 +// we have determined that this lock/unlock can be eliminated, we simply 2.83 +// eliminate the node without expanding it. 2.84 +// 2.85 +// Note: The membar's associated with the lock/unlock are currently not 2.86 +// eliminated. This should be investigated as a future enhancement. 2.87 +// 2.88 +bool PhaseMacroExpand::eliminate_locking_node(AbstractLockNode *alock) { 2.89 + 2.90 + if (!alock->is_eliminated()) { 2.91 + return false; 2.92 + } 2.93 +#ifdef ASSERT 2.94 + if (alock->is_Lock() && !alock->is_coarsened()) { 2.95 + // Check that new "eliminated" BoxLock node is created. 2.96 + BoxLockNode* oldbox = alock->box_node()->as_BoxLock(); 2.97 + assert(oldbox->is_eliminated(), "should be done already"); 2.98 + } 2.99 +#endif 2.100 CompileLog* log = C->log(); 2.101 if (log != NULL) { 2.102 log->head("eliminate_lock lock='%d'", 2.103 @@ -2145,6 +2162,15 @@ 2.104 if (C->macro_count() == 0) 2.105 return false; 2.106 // First, attempt to eliminate locks 2.107 + int cnt = C->macro_count(); 2.108 + for (int i=0; i < cnt; i++) { 2.109 + Node *n = C->macro_node(i); 2.110 + if (n->is_AbstractLock()) { // Lock and Unlock nodes 2.111 + // Before elimination mark all associated (same box and obj) 2.112 + // lock and unlock nodes. 2.113 + mark_eliminated_locking_nodes(n->as_AbstractLock()); 2.114 + } 2.115 + } 2.116 bool progress = true; 2.117 while (progress) { 2.118 progress = false;
3.1 --- a/src/share/vm/opto/macro.hpp Fri Jun 03 22:31:43 2011 -0700 3.2 +++ b/src/share/vm/opto/macro.hpp Sat Jun 04 10:36:22 2011 -0700 3.3 @@ -92,6 +92,7 @@ 3.4 void process_users_of_allocation(AllocateNode *alloc); 3.5 3.6 void eliminate_card_mark(Node *cm); 3.7 + void mark_eliminated_locking_nodes(AbstractLockNode *alock); 3.8 bool eliminate_locking_node(AbstractLockNode *alock); 3.9 void expand_lock_node(LockNode *lock); 3.10 void expand_unlock_node(UnlockNode *unlock);