hotspot/src/share/vm/runtime/biasedLocking.cpp
static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) {
{- -------------------------------------------
(1) (なお, 引数の allow_rebias が true で呼ばれるのは bulk rebias からのパスだけである模様)
---------------------------------------- -}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
markOop mark = obj->mark();
{- -------------------------------------------
(1) もう revoke されてしまっていたら, ここで終了.
---------------------------------------- -}
if (!mark->has_bias_pattern()) {
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking) {
ResourceMark rm;
tty->print_cr(" (Skipping revocation of object of type %s because it's no longer biased)",
Klass::cast(obj->klass())->external_name());
}
return BiasedLocking::NOT_BIASED;
}
{- -------------------------------------------
(1) (変数宣言など)
---------------------------------------- -}
int age = mark->age();
markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age);
markOop unbiased_prototype = markOopDesc::prototype()->set_age(age);
{- -------------------------------------------
(1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking && (Verbose || !is_bulk)) {
ResourceMark rm;
tty->print_cr("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT " , allow rebias %d , requesting thread " INTPTR_FORMAT,
(intptr_t) obj, (intptr_t) mark, Klass::cast(obj->klass())->external_name(), (intptr_t) Klass::cast(obj->klass())->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread);
}
{- -------------------------------------------
(1) 対象のオブジェクトが anonymously biased だった場合は, ここでリターン.
なお, 引数で「以降の rebias を禁止する (allow_rebias = false)」と指定されていれば
リターン前に mark フィールドを 非 biased locking pattern なものに置き換えている.
(ただし, 置き換える場合も, age フィールドだけは情報が消えるともったいないので,
現在の age フィールドの値で入れ替えている.
上の unbiased_prototype の定義部を参照)
---------------------------------------- -}
JavaThread* biased_thread = mark->biased_locker();
if (biased_thread == NULL) {
// Object is anonymously biased. We can get here if, for
// example, we revoke the bias due to an identity hash code
// being computed for an object.
if (!allow_rebias) {
obj->set_mark(unbiased_prototype);
}
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking && (Verbose || !is_bulk)) {
tty->print_cr(" Revoked bias of anonymously-biased object");
}
return BiasedLocking::BIAS_REVOKED;
}
{- -------------------------------------------
(1) (次に, 以下の処理で biased 対象のスレッドがまだ生きているか(存在しているか)どうかを調べる.
生きていなければ, スタックを調べるまでもなく, アンロックして構わない状態だと分かるので,
mark フィールドをアンロック状態にしてここでリターン.)
(まぁ調べる必要がないというか, 正確にはもうスタック自体がない訳だが...
スレッドが終了していれば, 終了処理でロックは全てアンロックされたはずなので,
勝手に mark フィールドをアンロックにしても問題ない)
(なお「mark フィールドをアンロック状態にする」処理としては, 以下の2通りがある.
* 引数で「以降の rebias を許可する (allow_rebias = true)」と指定されていた場合:
anonymously biased にする.
* そうではない場合:
neutral にする.)
---------------------------------------- -}
// Handle case where the thread toward which the object was biased has exited
bool thread_is_alive = false;
{- -------------------------------------------
(1.1) まず, biased 対象のスレッドがまだ生きているかどうかを調査する.
調査は, revoke を要求したスレッド自身が biased 対象であれば簡単 (生きている!).
---------------------------------------- -}
if (requesting_thread == biased_thread) {
thread_is_alive = true;
{- -------------------------------------------
(1.1) そうでなければ, 全スレッドを iterate して調べる.
---------------------------------------- -}
} else {
for (JavaThread* cur_thread = Threads::first(); cur_thread != NULL; cur_thread = cur_thread->next()) {
if (cur_thread == biased_thread) {
thread_is_alive = true;
break;
}
}
}
{- -------------------------------------------
(1.1) もし生きていなければ, mark フィールドに (allow_rebias の値に応じて) biased_prototype か unbiased_prototype を書き込む.
---------------------------------------- -}
if (!thread_is_alive) {
if (allow_rebias) {
obj->set_mark(biased_prototype);
} else {
obj->set_mark(unbiased_prototype);
}
{- -------------------------------------------
(1.1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking && (Verbose || !is_bulk)) {
tty->print_cr(" Revoked bias of object biased toward dead thread");
}
{- -------------------------------------------
(1.1) ここでリターン.
---------------------------------------- -}
return BiasedLocking::BIAS_REVOKED;
}
{- -------------------------------------------
(1) (biased 対象のスレッドが生きていた場合, そのスタック内の BasicObjectLock を調べる必要がある.
以下でその処理を行う.)
ここで行う処理は, 具体的には以下の通り.
* 対象のオブジェクトを指している BasicObjectLock が見つかった場合:
オブジェクトはロックされた状態なので, stack-locked にする
* 逆に, 対象のオブジェクトを指している BasicObjectLock が無かった場合:
オブジェクトはロックされていないので, アンロック状態にする.
(なお, 該当する BasicObjectLock を見つけた場合は,
その BasicObjectLock 内の displaced_header を埋める処理も行っている.
通常のロック処理時と同じく, 最初のものには mark フィールド, 再帰ロックで取られたものには NULL を入れる.)
(該当する BasicObjectLock が無かった場合に「mark フィールドをアンロック状態にする」処理としては, 以下の2通りがある.
* 引数で「以降の rebias を許可する (allow_rebias = true)」と指定されていた場合:
anonymously biased にする.
* そうではない場合:
neutral にする.)
---------------------------------------- -}
// Thread owning bias is alive.
// Check to see whether it currently owns the lock and, if so,
// write down the needed displaced headers to the thread's stack.
// Otherwise, restore the object's header either to the unlocked
// or unbiased state.
{- -------------------------------------------
(1.1) (まず, get_or_compute_monitor_info() で
biased 対象のスレッドのスタック内から使用中のロックの情報を取得し, 一つ一つ調べていく)
---------------------------------------- -}
GrowableArray<MonitorInfo*>* cached_monitor_info = get_or_compute_monitor_info(biased_thread);
BasicLock* highest_lock = NULL;
for (int i = 0; i < cached_monitor_info->length(); i++) {
MonitorInfo* mon_info = cached_monitor_info->at(i);
{- -------------------------------------------
(1.1.1) もし対象のオブジェクトを指している BasicObjectLock が見つかれば, highest_lock に記録する.
(なおこの時点では, 再起ロックかもしれないため, displaced header は NULL にしておく)
---------------------------------------- -}
if (mon_info->owner() == obj) {
if (TraceBiasedLocking && Verbose) {
tty->print_cr(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")",
(intptr_t) mon_info->owner(),
(intptr_t) obj);
}
// Assume recursive case and fix up highest lock later
markOop mark = markOopDesc::encode((BasicLock*) NULL);
highest_lock = mon_info->lock();
highest_lock->set_displaced_header(mark);
{- -------------------------------------------
(1.1.1) (トレース出力)
(対象のオブジェクトを指していなかった場合には出力を出す)
---------------------------------------- -}
} else {
if (TraceBiasedLocking && Verbose) {
tty->print_cr(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")",
(intptr_t) mon_info->owner(),
(intptr_t) obj);
}
}
}
{- -------------------------------------------
(1.1) もし対象のオブジェクトを指している BasicObjectLock が見つかっていれば (= highest_lock が NULL でなければ),
最初の BasicObjectLock (= highest_lock) の displaced header には mark フィールドを埋め,
対象のオブジェクトの方は stack-locked 状態に変更する.
---------------------------------------- -}
if (highest_lock != NULL) {
// Fix up highest lock to contain displaced header and point
// object at it
highest_lock->set_displaced_header(unbiased_prototype);
// Reset object header to point to displaced mark
obj->set_mark(markOopDesc::encode(highest_lock));
assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit");
{- -------------------------------------------
(1.1.1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking && (Verbose || !is_bulk)) {
tty->print_cr(" Revoked bias of currently-locked object");
}
{- -------------------------------------------
(1.1) もし対象のオブジェクトを指している BasicObjectLock が見つからなかった場合は,
対象のオブジェクトはアンロック状態にする.
(なおアンロック状態としては,
引数で「以降の rebias を許可する (allow_rebias = true)」と指定されていたかどうかに応じて,
anonymously biased にする場合と neutral にする場合の2種類がある)
---------------------------------------- -}
} else {
{- -------------------------------------------
(1.1.1) (トレース出力)
---------------------------------------- -}
if (TraceBiasedLocking && (Verbose || !is_bulk)) {
tty->print_cr(" Revoked bias of currently-unlocked object");
}
{- -------------------------------------------
(1.1.1) mark フィールドに (allow_rebias の値に応じて) biased_prototype か unbiased_prototype を書き込む.
---------------------------------------- -}
if (allow_rebias) {
obj->set_mark(biased_prototype);
} else {
// Store the unlocked value into the object's header.
obj->set_mark(unbiased_prototype);
}
}
{- -------------------------------------------
(1) リターン
---------------------------------------- -}
return BiasedLocking::BIAS_REVOKED;
}
This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.