// lock method if synchronized if (METHOD->is_synchronized()) {
// oop rcvr = locals[0].j.r; oop rcvr;
if (METHOD->is_static()) {
rcvr = METHOD->constants()->pool_holder()->java_mirror();
} else {
rcvr = LOCALS_OBJECT(0);
VERIFY_OOP(rcvr);
}
// The initial monitor is ours for the taking BasicObjectLock* mon = &istate->monitor_base()[-1];
oop monobj = mon->obj();
assert(mon->obj() == rcvr, "method monitor mis-initialized");
bool success = UseBiasedLocking;
if (UseBiasedLocking) {
markOop mark = rcvr->mark();
if (mark->has_bias_pattern()) {
// The bias pattern is present in the object's header. Need to check // whether the bias owner and the epoch are both still current. intptr_t xx = ((intptr_t) THREAD) ^ (intptr_t) mark;
xx = (intptr_t) rcvr->klass()->prototype_header() ^ xx;
intptr_t yy = (xx & ~((int) markOopDesc::age_mask_in_place));
if (yy != 0 ) {
// At this point we know that the header has the bias pattern and // that we are not the bias owner in the current epoch. We need to // figure out more details about the state of the header in order to // know what operations can be legally performed on the object's // header.
// If the low three bits in the xor result aren't clear, that means // the prototype header is no longer biased and we have to revoke // the bias on this object.
if (yy & markOopDesc::biased_lock_mask_in_place == 0 ) {
// Biasing is still enabled for this data type. See whether the // epoch of the current bias is still valid, meaning that the epoch // bits of the mark word are equal to the epoch bits of the // prototype header. (Note that the prototype header's epoch bits // only change at a safepoint.) If not, attempt to rebias the object // toward the current thread. Note that we must be absolutely sure // that the current epoch is invalid in order to do this because // otherwise the manipulations it performs on the mark word are // illegal. if (yy & markOopDesc::epoch_mask_in_place == 0) {
// The epoch of the current bias is still valid but we know nothing // about the owner; it might be set or it might be clear. Try to // acquire the bias of the object using an atomic operation. If this // fails we will go in to the runtime to revoke the object's bias. // Note that we first construct the presumed unbiased header so we // don't accidentally blow away another thread's valid bias. intptr_t unbiased = (intptr_t) mark & (markOopDesc::biased_lock_mask_in_place |
markOopDesc::age_mask_in_place |
markOopDesc::epoch_mask_in_place);
if (Atomic::cmpxchg_ptr((intptr_t)THREAD | unbiased, (intptr_t*) rcvr->mark_addr(), unbiased) != unbiased) {
CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception);
}
} else {
try_rebias:
// At this point we know the epoch has expired, meaning that the // current "bias owner", if any, is actually invalid. Under these // circumstances _only_, we are allowed to use the current header's // value as the comparison value when doing the cas to acquire the // bias in the current epoch. In other words, we allow transfer of // the bias from one thread to another directly in this situation. xx = (intptr_t) rcvr->klass()->prototype_header() | (intptr_t) THREAD;
if (Atomic::cmpxchg_ptr((intptr_t)THREAD | (intptr_t) rcvr->klass()->prototype_header(),
(intptr_t*) rcvr->mark_addr(),
(intptr_t) mark) != (intptr_t) mark) {
CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception);
}
}
} else {
try_revoke_bias:
// The prototype mark in the klass doesn't have the bias bit set any // more, indicating that objects of this data type are not supposed // to be biased any more. We are going to try to reset the mark of // this object to the prototype value and fall through to the // CAS-based locking scheme. Note that if our CAS fails, it means // that another thread raced us for the privilege of revoking the // bias of this particular object, so it's okay to continue in the // normal locking code. // xx = (intptr_t) rcvr->klass()->prototype_header() | (intptr_t) THREAD;
if (Atomic::cmpxchg_ptr(rcvr->klass()->prototype_header(),
(intptr_t*) rcvr->mark_addr(),
mark) == mark) {
// (*counters->revoked_lock_entry_count_addr())++; success = false;
}
}
}
} else {
cas_label:
success = false;
}
}
if (!success) {
markOop displaced = rcvr->mark()->set_unlocked();
mon->lock()->set_displaced_header(displaced);
if (Atomic::cmpxchg_ptr(mon, rcvr->mark_addr(), displaced) != displaced) {
// Is it simple recursive case? if (THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {
mon->lock()->set_displaced_header(NULL);
} else {
CALL_VM(InterpreterRuntime::monitorenter(THREAD, mon), handle_exception);
}
}
}
}
THREAD->clr_do_not_unlock();
// Notify jvmti#ifdef VM_JVMTI if (_jvmti_interp_events) {
// Whenever JVMTI puts a thread in interp_only_mode, method // entry/exit events are sent for that thread to track stack depth. if (THREAD->is_interp_only_mode()) {
CALL_VM(InterpreterRuntime::post_method_entry(THREAD),
handle_exception);
}
}
#endif/* VM_JVMTI */
goto run;
}