Top


定義場所(file name)

hotspot/src/share/vm/runtime/biasedLocking.cpp

名前(function name)

static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) {

本体部(body)

  {- -------------------------------------------
  (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.