hotspot/src/share/vm/runtime/biasedLocking.cpp
static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,
bool bulk_rebias,
bool attempt_rebias_of_object,
JavaThread* requesting_thread) {
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint");
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking) {
tty->print_cr("* Beginning bulk revocation (kind == %s) because of object "
INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
(bulk_rebias ? "rebias" : "revoke"),
(intptr_t) o, (intptr_t) o->mark(), Klass::cast(o->klass())->external_name());
}
{- -------------------------------------------
(1) クラスオブジェクトの _last_biased_lock_bulk_revocation_time フィールドを現在時刻に更新する.
(これは heuristics 計算に使う情報.
See: update_heuristics())
---------------------------------------- -}
jlong cur_time = os::javaTimeMillis();
o->blueprint()->set_last_biased_lock_bulk_revocation_time(cur_time);
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
klassOop k_o = o->klass();
Klass* klass = Klass::cast(k_o);
{- -------------------------------------------
(1) (以下で, bulk rebias 処理 または bulk revoke 処理を行う.
どちらを行うかは, bulk_rebias 引数での指定によって決まる)
(その後に, 両方のケースに共通の処理を少し行って, この関数は終了)
---------------------------------------- -}
{- -------------------------------------------
(1) (次の if の then ブロック内が, bulk rebias の場合の処理)
---------------------------------------- -}
if (bulk_rebias) {
// Use the epoch in the klass of the object to implicitly revoke
// all biases of objects of this data type and force them to be
// reacquired. However, we also need to walk the stacks of all
// threads and update the headers of lightweight locked objects
// with biases to have the current epoch.
{- -------------------------------------------
(1.1) まず, 以下の if ブロック内で epoch の増加処理を行う.
(ただし, もし既に bulk revoke されていたら, やる必要が無いのでこの処理は省略する.
これは, 他の VM operation によって bulk revoke されてしまった場合に起こりうる.)
---------------------------------------- -}
// If the prototype header doesn't have the bias pattern, don't
// try to update the epoch -- assume another VM operation came in
// and reset the header to the unbiased state, which will
// implicitly cause all existing biases to be revoked
if (klass->prototype_header()->has_bias_pattern()) {
{- -------------------------------------------
(1.1.1) まず, 対象のオブジェクトのクラスオブジェクト内にある
prototype header の epoch を増加させる.
---------------------------------------- -}
int prev_epoch = klass->prototype_header()->bias_epoch();
klass->set_prototype_header(klass->prototype_header()->incr_bias_epoch());
int cur_epoch = klass->prototype_header()->bias_epoch();
{- -------------------------------------------
(1.1.1) 次に, 対象のオブジェクトと同じクラスに所属するオブジェクトで,
「biased 状態であり, かつ現在ロックを確保されているオブジェクト」に付いて,
epoch を増加させる.
---------------------------------------- -}
// Now walk all threads' stacks and adjust epochs of any biased
// and locked objects of this data type we encounter
for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
for (int i = 0; i < cached_monitor_info->length(); i++) {
MonitorInfo* mon_info = cached_monitor_info->at(i);
oop owner = mon_info->owner();
markOop mark = owner->mark();
if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
// We might have encountered this object already in the case of recursive locking
assert(mark->bias_epoch() == prev_epoch || mark->bias_epoch() == cur_epoch, "error in bias epoch adjustment");
owner->set_mark(mark->set_bias_epoch(cur_epoch));
}
}
}
}
{- -------------------------------------------
(1.1) 次に, 対象のオブジェクトについて, revoke_bias() で revoke 処理を行う.
---------------------------------------- -}
// At this point we're done. All we have to do is potentially
// adjust the header of the given object to revoke its bias.
revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread);
{- -------------------------------------------
(1) (ここまでが bulk rebias 処理)
(逆に, 次の else ブロック内が bulk revoke の場合の処理)
---------------------------------------- -}
} else {
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking) {
ResourceMark rm;
tty->print_cr("* Disabling biased locking for type %s", klass->external_name());
}
{- -------------------------------------------
(1.1) まず, 対象のオブジェクトのクラスオブジェクト内にある
prototype header を非 biased locking patter に変更する.
---------------------------------------- -}
// Disable biased locking for this data type. Not only will this
// cause future instances to not be biased, but existing biased
// instances will notice that this implicitly caused their biases
// to be revoked.
klass->set_prototype_header(markOopDesc::prototype());
{- -------------------------------------------
(1.1) 次に, 対象のオブジェクトと同じクラスに所属するオブジェクトで,
「biased 状態であり, かつ現在ロックを確保されているオブジェクト」に付いて,
revoke_bias() で revoke する.
---------------------------------------- -}
// Now walk all threads' stacks and forcibly revoke the biases of
// any locked and biased objects of this data type we encounter.
for (JavaThread* thr = Threads::first(); thr != NULL; thr = thr->next()) {
GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(thr);
for (int i = 0; i < cached_monitor_info->length(); i++) {
MonitorInfo* mon_info = cached_monitor_info->at(i);
oop owner = mon_info->owner();
markOop mark = owner->mark();
if ((owner->klass() == k_o) && mark->has_bias_pattern()) {
revoke_bias(owner, false, true, requesting_thread);
}
}
}
{- -------------------------------------------
(1.1) 最後に, 対象のオブジェクトについても revoke_bias() で revoke 処理を行う.
---------------------------------------- -}
// Must force the bias of the passed object to be forcibly revoked
// as well to ensure guarantees to callers
revoke_bias(o, false, true, requesting_thread);
{- -------------------------------------------
(1) (ここまでが bulk revoke 処理)
---------------------------------------- -}
}
{- -------------------------------------------
(1) (以下は, bulk rebias でも bulk revoke でも実行される共通処理)
---------------------------------------- -}
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking) {
tty->print_cr("* Ending bulk revocation");
}
{- -------------------------------------------
(1) (以上で対象のオブジェクトは revoke してしまったが)
もし以下の条件が両方とも成り立っていれば, 対象のオブジェクトを revoke を要求したスレッドに biased させておく.
* 引数で rebias するように要求されている
(= 引数の attempt_rebias_of_object が true)
* 対象のオブジェクトが biased 可能な状態にある
(= 対象のオブジェクトの mark フィールドが biased pattern, かつ
そのクラスの prototype header も biased pattern)
---------------------------------------- -}
BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED;
if (attempt_rebias_of_object &&
o->mark()->has_bias_pattern() &&
klass->prototype_header()->has_bias_pattern()) {
markOop new_mark = markOopDesc::encode(requesting_thread, o->mark()->age(),
klass->prototype_header()->bias_epoch());
o->set_mark(new_mark);
status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED;
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking) {
tty->print_cr(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread);
}
}
{- -------------------------------------------
(1) (assert)
---------------------------------------- -}
assert(!o->mark()->has_bias_pattern() ||
(attempt_rebias_of_object && (o->mark()->biased_locker() == requesting_thread)),
"bug in bulk bias revocation");
{- -------------------------------------------
(1) リターン
---------------------------------------- -}
return status_code;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.