Created
November 8, 2018 07:35
-
-
Save farmerjohngit/9ba90dc0a549243c39e9914dca0c52b2 to your computer and use it in GitHub Desktop.
sync
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attempt_rebias, TRAPS) { | |
assert(!SafepointSynchronize::is_at_safepoint(), "must not be called while at safepoint"); | |
// We can revoke the biases of anonymously-biased objects | |
// efficiently enough that we should not cause these revocations to | |
// update the heuristics because doing so may cause unwanted bulk | |
// revocations (which are expensive) to occur. | |
markOop mark = obj->mark(); | |
if (mark->is_biased_anonymously() && !attempt_rebias) { | |
// We are probably trying to revoke the bias of this object due to | |
// an identity hash code computation. Try to revoke the bias | |
// without a safepoint. This is possible if we can successfully | |
// compare-and-exchange an unbiased header into the mark word of | |
// the object, meaning that no other thread has raced to acquire | |
// the bias of the object. | |
markOop biased_value = mark; | |
markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age()); | |
markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark); | |
if (res_mark == biased_value) { | |
return BIAS_REVOKED; | |
} | |
} else if (mark->has_bias_pattern()) { | |
Klass* k = obj->klass(); | |
markOop prototype_header = k->prototype_header(); | |
if (!prototype_header->has_bias_pattern()) { | |
// This object has a stale bias from before the bulk revocation | |
// for this data type occurred. It's pointless to update the | |
// heuristics at this point so simply update the header with a | |
// CAS. If we fail this race, the object's bias has been revoked | |
// by another thread so we simply return and let the caller deal | |
// with it. | |
markOop biased_value = mark; | |
markOop res_mark = (markOop) Atomic::cmpxchg_ptr(prototype_header, obj->mark_addr(), mark); | |
assert(!(*(obj->mark_addr()))->has_bias_pattern(), "even if we raced, should still be revoked"); | |
return BIAS_REVOKED; | |
} else if (prototype_header->bias_epoch() != mark->bias_epoch()) { | |
// The epoch of this biasing has expired indicating that the | |
// object is effectively unbiased. Depending on whether we need | |
// to rebias or revoke the bias of this object we can do it | |
// efficiently enough with a CAS that we shouldn't update the | |
// heuristics. This is normally done in the assembly code but we | |
// can reach this point due to various points in the runtime | |
// needing to revoke biases. | |
if (attempt_rebias) { | |
assert(THREAD->is_Java_thread(), ""); | |
markOop biased_value = mark; | |
markOop rebiased_prototype = markOopDesc::encode((JavaThread*) THREAD, mark->age(), prototype_header->bias_epoch()); | |
markOop res_mark = (markOop) Atomic::cmpxchg_ptr(rebiased_prototype, obj->mark_addr(), mark); | |
if (res_mark == biased_value) { | |
return BIAS_REVOKED_AND_REBIASED; | |
} | |
} else { | |
markOop biased_value = mark; | |
markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age()); | |
markOop res_mark = (markOop) Atomic::cmpxchg_ptr(unbiased_prototype, obj->mark_addr(), mark); | |
if (res_mark == biased_value) { | |
return BIAS_REVOKED; | |
} | |
} | |
} | |
} | |
HeuristicsResult heuristics = update_heuristics(obj(), attempt_rebias); | |
if (heuristics == HR_NOT_BIASED) { | |
return NOT_BIASED; | |
} else if (heuristics == HR_SINGLE_REVOKE) { | |
Klass *k = obj->klass(); | |
markOop prototype_header = k->prototype_header(); | |
if (mark->biased_locker() == THREAD && | |
prototype_header->bias_epoch() == mark->bias_epoch()) { | |
// A thread is trying to revoke the bias of an object biased | |
// toward it, again likely due to an identity hash code | |
// computation. We can again avoid a safepoint in this case | |
// since we are only going to walk our own stack. There are no | |
// races with revocations occurring in other threads because we | |
// reach no safepoints in the revocation path. | |
// Also check the epoch because even if threads match, another thread | |
// can come in with a CAS to steal the bias of an object that has a | |
// stale epoch. | |
ResourceMark rm; | |
if (TraceBiasedLocking) { | |
tty->print_cr("Revoking bias by walking my own stack:"); | |
} | |
BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD); | |
((JavaThread*) THREAD)->set_cached_monitor_info(NULL); | |
assert(cond == BIAS_REVOKED, "why not?"); | |
return cond; | |
} else { | |
VM_RevokeBias revoke(&obj, (JavaThread*) THREAD); | |
VMThread::execute(&revoke); | |
return revoke.status_code(); | |
} | |
} | |
assert((heuristics == HR_BULK_REVOKE) || | |
(heuristics == HR_BULK_REBIAS), "?"); | |
VM_BulkRevokeBias bulk_revoke(&obj, (JavaThread*) THREAD, | |
(heuristics == HR_BULK_REBIAS), | |
attempt_rebias); | |
VMThread::execute(&bulk_revoke); | |
return bulk_revoke.status_code(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment