Top


定義場所(file name)

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

名前(function name)

void VMThread::execute(VM_Operation* op) {

本体部(body)

  {- -------------------------------------------
  (1) (変数宣言など)
      ---------------------------------------- -}

      Thread* t = Thread::current();

  {- -------------------------------------------
  (1) (以下では, 呼び出し元のスレッドが VMThread かそうでないかに応じて処理を分ける)
      ---------------------------------------- -}

  {- -------------------------------------------
  (1) (以下は VMThread 以外から呼び出されたケース (nested VM Operation ではない場合) の処理)
      ---------------------------------------- -}

      if (!t->is_VM_thread()) {

    {- -------------------------------------------
  (1.1) (デバッグ用の処理)
        (See: SkipGCALot, No_Safepoint_Verifier)
        ---------------------------------------- -}

        SkipGCALot sgcalot(t);    // avoid re-entrant attempts to gc-a-lot
        // JavaThread or WatcherThread
        t->check_for_valid_safepoint_state(true);

    {- -------------------------------------------
  (1.1) VM_Operation::doit_prologue() を呼び出す.
        doit_prologue() が false を返せば, VM_Operation はキャンセルされたと見なし, ここで終了.
        ---------------------------------------- -}

        // New request from Java thread, evaluate prologue
        if (!op->doit_prologue()) {
          return;   // op was cancelled
        }

    {- -------------------------------------------
  (1.1) VM_Operation オブジェクトのフィールドを初期化.
        ---------------------------------------- -}

        // Setup VM_operations for execution
        op->set_calling_thread(t, Thread::get_priority(t));

    {- -------------------------------------------
  (1.1) (変数宣言など)
        ---------------------------------------- -}

        // It does not make sense to execute the epilogue, if the VM operation object is getting
        // deallocated by the VM thread.
        bool concurrent     = op->evaluate_concurrently();
        bool execute_epilog = !op->is_cheap_allocated();
        assert(!concurrent || op->is_cheap_allocated(), "concurrent => cheap_allocated");

    {- -------------------------------------------
  (1.1) もし VM Operation の完了を待つ必要があれば, 
        現在の vm_operation_ticket() を取得しておく.
        ---------------------------------------- -}

        // Get ticket number for non-concurrent VM operations
        int ticket = 0;
        if (!concurrent) {
          ticket = t->vm_operation_ticket();
        }

    {- -------------------------------------------
  (1.1) _vm_queue に VM_Operation オブジェクトを追加する.
        その後, VMOperationQueue_lock の Monitor::notify() を呼び出して 
        追加したことを VMThread に通知する.
        ---------------------------------------- -}

        // Add VM operation to list of waiting threads. We are guaranteed not to block while holding the
        // VMOperationQueue_lock, so we can block without a safepoint check. This allows vm operation requests
        // to be queued up during a safepoint synchronization.
        {
          VMOperationQueue_lock->lock_without_safepoint_check();
          bool ok = _vm_queue->add(op);
          op->set_timestamp(os::javaTimeMillis());
          VMOperationQueue_lock->notify();
          VMOperationQueue_lock->unlock();
          // VM_Operation got skipped
          if (!ok) {
            assert(concurrent, "can only skip concurrent tasks");
            if (op->is_cheap_allocated()) delete op;
            return;
          }
        }

    {- -------------------------------------------
  (1.1) もし VM Operation の完了を待つ必要があれば, 
        VMOperationRequest_lock の Monitor::wait() を呼び出して VM Operation の完了を待つ
        (See: VMThread::evaluate_operation(), VMThread::loop())
        ---------------------------------------- -}

        if (!concurrent) {
          // Wait for completion of request (non-concurrent)
          // Note: only a JavaThread triggers the safepoint check when locking
          MutexLocker mu(VMOperationRequest_lock);
          while(t->vm_operation_completed_count() < ticket) {
            VMOperationRequest_lock->wait(!t->is_Java_thread());
          }
        }

    {- -------------------------------------------
  (1.1) もし VMThread によって delete されない種類の VM_Operation オブジェクトであれば, 
        VM_Operation::doit_epilogue() を呼び出す.
        ---------------------------------------- -}

        if (execute_epilog) {
          op->doit_epilogue();
        }

  {- -------------------------------------------
  (1) (以下は VMThread から呼び出されたケース (nested VM Operation 等の場合) の処理)
      ---------------------------------------- -}

      } else {

    {- -------------------------------------------
  (1.1) (assert)
        ---------------------------------------- -}

        // invoked by VM thread; usually nested VM operation
        assert(t->is_VM_thread(), "must be a VM thread");

    {- -------------------------------------------
  (1.1) もし現在実行中の VM_Operation があった場合は (= _cur_vm_operation が NULL ではない場合は), 
        新しい VM_Operation の呼び出し元や優先度は現在実行中のものに合わせておく.

        (なお, 実行中だった VM_Operation は, ここでいったん待避しておく)

        (なお, 実行中の VM_Operation が入れ子になった実行ができない種類のもの 
         (= VM_Operation::allow_nested_vm_operations() が false) だった場合には, 
         ここで fatal() によって異常終了.)
        ---------------------------------------- -}

        VM_Operation* prev_vm_operation = vm_operation();
        if (prev_vm_operation != NULL) {
          // Check the VM operation allows nested VM operation. This normally not the case, e.g., the compiler
          // does not allow nested scavenges or compiles.
          if (!prev_vm_operation->allow_nested_vm_operations()) {
            fatal(err_msg("Nested VM operation %s requested by operation %s",
                          op->name(), vm_operation()->name()));
          }
          op->set_calling_thread(prev_vm_operation->calling_thread(), prev_vm_operation->priority());
        }

    {- -------------------------------------------
  (1.1) (トレース出力) (See: EventMark)
        ---------------------------------------- -}

        EventMark em("Executing %s VM operation: %s", prev_vm_operation ? "nested" : "", op->name());

    {- -------------------------------------------
  (1.1) (変数宣言など)
        ---------------------------------------- -}

        // Release all internal handles after operation is evaluated
        HandleMark hm(t);

    {- -------------------------------------------
  (1.1) VM_Operation::evaluate() を呼び出して VM Operation を実行する.
        (なお safepoint 停止が必要であれば, 前後で 
         SafepointSynchronize::begin() と SafepointSynchronize::end() の呼び出しも行う)
        ---------------------------------------- -}

        _cur_vm_operation = op;

        if (op->evaluate_at_safepoint() && !SafepointSynchronize::is_at_safepoint()) {
          SafepointSynchronize::begin();
          op->evaluate();
          SafepointSynchronize::end();
        } else {
          op->evaluate();
        }

    {- -------------------------------------------
  (1.1) もし VM_Operation オブジェクトが C ヒープ上に確保されたものであれば delete しておく.
        ---------------------------------------- -}

        // Free memory if needed
        if (op->is_cheap_allocated()) delete op;

    {- -------------------------------------------
  (1.1) _cur_vm_operation を元の状態に戻しておく.
        ---------------------------------------- -}

        _cur_vm_operation = prev_vm_operation;
      }
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.