1.1 --- a/src/share/vm/opto/callnode.cpp Sat Jan 07 10:39:23 2012 -0800 1.2 +++ b/src/share/vm/opto/callnode.cpp Sat Jan 07 13:26:43 2012 -0800 1.3 @@ -400,10 +400,10 @@ 1.4 Node *box = mcall->monitor_box(this, i); 1.5 Node *obj = mcall->monitor_obj(this, i); 1.6 if ( OptoReg::is_valid(regalloc->get_reg_first(box)) ) { 1.7 - while( !box->is_BoxLock() ) box = box->in(1); 1.8 + box = BoxLockNode::box_node(box); 1.9 format_helper( regalloc, st, box, "MON-BOX[", i, &scobjs ); 1.10 } else { 1.11 - OptoReg::Name box_reg = BoxLockNode::stack_slot(box); 1.12 + OptoReg::Name box_reg = BoxLockNode::reg(box); 1.13 st->print(" MON-BOX%d=%s+%d", 1.14 i, 1.15 OptoReg::regname(OptoReg::c_frame_pointer), 1.16 @@ -411,8 +411,7 @@ 1.17 } 1.18 const char* obj_msg = "MON-OBJ["; 1.19 if (EliminateLocks) { 1.20 - while( !box->is_BoxLock() ) box = box->in(1); 1.21 - if (box->as_BoxLock()->is_eliminated()) 1.22 + if (BoxLockNode::box_node(box)->is_eliminated()) 1.23 obj_msg = "MON-OBJ(LOCK ELIMINATED)["; 1.24 } 1.25 format_helper( regalloc, st, obj, obj_msg, i, &scobjs ); 1.26 @@ -1388,7 +1387,8 @@ 1.27 if (n != NULL && n->is_Unlock()) { 1.28 UnlockNode *unlock = n->as_Unlock(); 1.29 if ((lock->obj_node() == unlock->obj_node()) && 1.30 - (lock->box_node() == unlock->box_node()) && !unlock->is_eliminated()) { 1.31 + BoxLockNode::same_slot(lock->box_node(), unlock->box_node()) && 1.32 + !unlock->is_eliminated()) { 1.33 lock_ops.append(unlock); 1.34 return true; 1.35 } 1.36 @@ -1432,7 +1432,7 @@ 1.37 if (ctrl->is_Lock()) { 1.38 LockNode *lock = ctrl->as_Lock(); 1.39 if ((lock->obj_node() == unlock->obj_node()) && 1.40 - (lock->box_node() == unlock->box_node())) { 1.41 + BoxLockNode::same_slot(lock->box_node(), unlock->box_node())) { 1.42 lock_result = lock; 1.43 } 1.44 } 1.45 @@ -1463,7 +1463,8 @@ 1.46 if (lock1_node != NULL && lock1_node->is_Lock()) { 1.47 LockNode *lock1 = lock1_node->as_Lock(); 1.48 if ((lock->obj_node() == lock1->obj_node()) && 1.49 - (lock->box_node() == lock1->box_node()) && !lock1->is_eliminated()) { 1.50 + BoxLockNode::same_slot(lock->box_node(), lock1->box_node()) && 1.51 + !lock1->is_eliminated()) { 1.52 lock_ops.append(lock1); 1.53 return true; 1.54 } 1.55 @@ -1507,19 +1508,16 @@ 1.56 void AbstractLockNode::create_lock_counter(JVMState* state) { 1.57 _counter = OptoRuntime::new_named_counter(state, NamedCounter::LockCounter); 1.58 } 1.59 -#endif 1.60 1.61 -void AbstractLockNode::set_eliminated() { 1.62 - _eliminate = true; 1.63 -#ifndef PRODUCT 1.64 +void AbstractLockNode::set_eliminated_lock_counter() { 1.65 if (_counter) { 1.66 // Update the counter to indicate that this lock was eliminated. 1.67 // The counter update code will stay around even though the 1.68 // optimizer will eliminate the lock operation itself. 1.69 _counter->set_tag(NamedCounter::EliminatedLockCounter); 1.70 } 1.71 +} 1.72 #endif 1.73 -} 1.74 1.75 //============================================================================= 1.76 Node *LockNode::Ideal(PhaseGVN *phase, bool can_reshape) { 1.77 @@ -1535,7 +1533,7 @@ 1.78 // prevents macro expansion from expanding the lock. Since we don't 1.79 // modify the graph, the value returned from this function is the 1.80 // one computed above. 1.81 - if (can_reshape && EliminateLocks && (!is_eliminated() || is_coarsened())) { 1.82 + if (can_reshape && EliminateLocks && !is_non_esc_obj()) { 1.83 // 1.84 // If we are locking an unescaped object, the lock/unlock is unnecessary 1.85 // 1.86 @@ -1544,16 +1542,11 @@ 1.87 if (cgr != NULL) 1.88 es = cgr->escape_state(obj_node()); 1.89 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { 1.90 - if (!is_eliminated()) { 1.91 - // Mark it eliminated to update any counters 1.92 - this->set_eliminated(); 1.93 - } else { 1.94 - assert(is_coarsened(), "sanity"); 1.95 - // The lock could be marked eliminated by lock coarsening 1.96 - // code during first IGVN before EA. Clear coarsened flag 1.97 - // to eliminate all associated locks/unlocks. 1.98 - this->clear_coarsened(); 1.99 - } 1.100 + assert(!is_eliminated() || is_coarsened(), "sanity"); 1.101 + // The lock could be marked eliminated by lock coarsening 1.102 + // code during first IGVN before EA. Replace coarsened flag 1.103 + // to eliminate all associated locks/unlocks. 1.104 + this->set_non_esc_obj(); 1.105 return result; 1.106 } 1.107 1.108 @@ -1613,8 +1606,7 @@ 1.109 for (int i = 0; i < lock_ops.length(); i++) { 1.110 AbstractLockNode* lock = lock_ops.at(i); 1.111 1.112 - // Mark it eliminated to update any counters 1.113 - lock->set_eliminated(); 1.114 + // Mark it eliminated by coarsening and update any counters 1.115 lock->set_coarsened(); 1.116 } 1.117 } else if (ctrl->is_Region() && 1.118 @@ -1632,6 +1624,41 @@ 1.119 } 1.120 1.121 //============================================================================= 1.122 +bool LockNode::is_nested_lock_region() { 1.123 + Node* box = box_node(); 1.124 + if (!box->is_BoxLock() || box->as_BoxLock()->stack_slot() <= 0) 1.125 + return false; // External lock or it is not Box (Phi node). 1.126 + 1.127 + // Ignore complex cases: merged locks or multiple locks. 1.128 + BoxLockNode* box_lock = box->as_BoxLock(); 1.129 + Node* obj = obj_node(); 1.130 + LockNode* unique_lock = NULL; 1.131 + if (!box_lock->is_simple_lock_region(&unique_lock, obj) || 1.132 + (unique_lock != this)) { 1.133 + return false; 1.134 + } 1.135 + 1.136 + // Look for external lock for the same object. 1.137 + int stk_slot = box_lock->stack_slot(); 1.138 + SafePointNode* sfn = this->as_SafePoint(); 1.139 + JVMState* youngest_jvms = sfn->jvms(); 1.140 + int max_depth = youngest_jvms->depth(); 1.141 + for (int depth = 1; depth <= max_depth; depth++) { 1.142 + JVMState* jvms = youngest_jvms->of_depth(depth); 1.143 + int num_mon = jvms->nof_monitors(); 1.144 + // Loop over monitors 1.145 + for (int idx = 0; idx < num_mon; idx++) { 1.146 + Node* obj_node = sfn->monitor_obj(jvms, idx); 1.147 + BoxLockNode* box_node = BoxLockNode::box_node(sfn->monitor_box(jvms, idx)); 1.148 + if ((obj_node == obj) && (box_node->stack_slot() < stk_slot)) { 1.149 + return true; 1.150 + } 1.151 + } 1.152 + } 1.153 + return false; 1.154 +} 1.155 + 1.156 +//============================================================================= 1.157 uint UnlockNode::size_of() const { return sizeof(*this); } 1.158 1.159 //============================================================================= 1.160 @@ -1649,7 +1676,7 @@ 1.161 // modify the graph, the value returned from this function is the 1.162 // one computed above. 1.163 // Escape state is defined after Parse phase. 1.164 - if (can_reshape && EliminateLocks && (!is_eliminated() || is_coarsened())) { 1.165 + if (can_reshape && EliminateLocks && !is_non_esc_obj()) { 1.166 // 1.167 // If we are unlocking an unescaped object, the lock/unlock is unnecessary. 1.168 // 1.169 @@ -1658,16 +1685,11 @@ 1.170 if (cgr != NULL) 1.171 es = cgr->escape_state(obj_node()); 1.172 if (es != PointsToNode::UnknownEscape && es != PointsToNode::GlobalEscape) { 1.173 - if (!is_eliminated()) { 1.174 - // Mark it eliminated to update any counters 1.175 - this->set_eliminated(); 1.176 - } else { 1.177 - assert(is_coarsened(), "sanity"); 1.178 - // The lock could be marked eliminated by lock coarsening 1.179 - // code during first IGVN before EA. Clear coarsened flag 1.180 - // to eliminate all associated locks/unlocks. 1.181 - this->clear_coarsened(); 1.182 - } 1.183 + assert(!is_eliminated() || is_coarsened(), "sanity"); 1.184 + // The lock could be marked eliminated by lock coarsening 1.185 + // code during first IGVN before EA. Replace coarsened flag 1.186 + // to eliminate all associated locks/unlocks. 1.187 + this->set_non_esc_obj(); 1.188 } 1.189 } 1.190 return result;