# HG changeset patch # User kvn # Date 1307208982 25200 # Node ID 293f68bda3476986b7fc78fb34185ec29175c692 # Parent f7d55ea6ee564a98f2d5e6efcd35d6a4fdd904d7 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 diff -r f7d55ea6ee56 -r 293f68bda347 src/share/vm/opto/escape.cpp --- 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 diff -r f7d55ea6ee56 -r 293f68bda347 src/share/vm/opto/macro.cpp --- 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; diff -r f7d55ea6ee56 -r 293f68bda347 src/share/vm/opto/macro.hpp --- 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);