Top


定義場所(file name)

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

名前(function name)

static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o,
                                                                   bool bulk_rebias,
                                                                   bool attempt_rebias_of_object,
                                                                   JavaThread* requesting_thread) {

本体部(body)

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