Top


定義場所(file name)

hotspot/src/share/vm/prims/jvmtiEnv.cpp

説明(description)

// Threads_lock NOT held, java_thread not protected by lock
// java_thread - pre-checked

名前(function name)

jvmtiError
JvmtiEnv::PopFrame(JavaThread* java_thread) {

本体部(body)

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

      JavaThread* current_thread  = JavaThread::current();
      HandleMark hm(current_thread);
      uint32_t debug_bits = 0;

  {- -------------------------------------------
  (1) JvmtiThreadState::state_for() を呼んで, 
      処理対象のスレッド(java_thread)に対応する JvmtiThreadState を取得する.
      (もし対象のスレッドが JvmtiThreadState を持っていなければ, この中で確保処理が行われる)

      (なお, スレッドが既に死んでいる場合(もしくは確保処理が失敗した場合)は, ここでリターン(JVMTI_ERROR_THREAD_NOT_ALIVE エラー))
      ---------------------------------------- -}

      // retrieve or create the state
      JvmtiThreadState* state = JvmtiThreadState::state_for(java_thread);
      if (state == NULL) {
        return JVMTI_ERROR_THREAD_NOT_ALIVE;
      }

  {- -------------------------------------------
  (1) 対象のスレッドが suspend されているかどうかを確認する.
      suspended されてなければ, ここでリターン(JVMTI_ERROR_THREAD_NOT_SUSPENDED).
      (これは JVMTI 仕様で要求されている挙動)
      ---------------------------------------- -}

      // Check if java_thread is fully suspended
      if (!is_thread_fully_suspended(java_thread, true /* wait for suspend completion */, &debug_bits)) {
        return JVMTI_ERROR_THREAD_NOT_SUSPENDED;
      }

  {- -------------------------------------------
  (1) もし対象のスレッドが既に PopFrame() をかけられた状態であれば, ここでリターン(JVMTI_ERROR_INTERNAL).
      ---------------------------------------- -}

      // Check to see if a PopFrame was already in progress
      if (java_thread->popframe_condition() != JavaThread::popframe_inactive) {
        // Probably possible for JVMTI clients to trigger this, but the
        // JPDA backend shouldn't allow this to happen
        return JVMTI_ERROR_INTERNAL;
      }

  {- -------------------------------------------
  (1) もしスレッドが MONITOR_WAIT 状態であれば, ここでリターン(JVMTI_ERROR_OPAQUE_FRAME).

      (この処理については bug 4812902 を参照とのこと #TODO)
      ---------------------------------------- -}

      {
        // Was workaround bug
        //    4812902: popFrame hangs if the method is waiting at a synchronize
        // Catch this condition and return an error to avoid hanging.
        // Now JVMTI spec allows an implementation to bail out with an opaque frame error.
        OSThread* osThread = java_thread->osthread();
        if (osThread->get_state() == MONITOR_WAIT) {
          return JVMTI_ERROR_OPAQUE_FRAME;
        }
      }

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

      {
        ResourceMark rm(current_thread);

  {- -------------------------------------------
  (1) 対象スレッドのスタックフレームの先頭2つ分を調べる.
      それらが non-native な Java メソッドのフレームでなければ, エラーをリターン(ここで終了).
      (これは JVMTI 仕様で要求されている挙動)

      (なお, ついでにフレームが interpreter frame か compiled frame かも調べている)
      ---------------------------------------- -}

        // Check if there are more than one Java frame in this thread, that the top two frames
        // are Java (not native) frames, and that there is no intervening VM frame
        int frame_count = 0;
        bool is_interpreted[2];
        intptr_t *frame_sp[2];
        // The 2-nd arg of constructor is needed to stop iterating at java entry frame.
        for (vframeStream vfs(java_thread, true); !vfs.at_end(); vfs.next()) {
          methodHandle mh(current_thread, vfs.method());

    {- -------------------------------------------
  (1.1) もし native frame を見つけたら JVMTI_ERROR_OPAQUE_FRAME をリターン.
        ---------------------------------------- -}

          if (mh->is_native()) return(JVMTI_ERROR_OPAQUE_FRAME);
          is_interpreted[frame_count] = vfs.is_interpreted_frame();
          frame_sp[frame_count] = vfs.frame_id();
          if (++frame_count > 1) break;
        }

    {- -------------------------------------------
  (1.1) もし上記の条件(先頭に 2個の non-native な Java メソッドのフレームがある)が満たされていなければ, 以下のエラーをリターン.
        * frame が 2個未満であれば, JVMTI_ERROR_NO_MORE_FRAMES
        * そうでなければ (= どちらかが native なら), JVMTI_ERROR_OPAQUE_FRAME
        ---------------------------------------- -}

        if (frame_count < 2)  {
          // We haven't found two adjacent non-native Java frames on the top.
          // There can be two situations here:
          //  1. There are no more java frames
          //  2. Two top java frames are separated by non-java native frames
          if(vframeFor(java_thread, 1) == NULL) {
            return JVMTI_ERROR_NO_MORE_FRAMES;
          } else {
            // Intervening non-java native or VM frames separate java frames.
            // Current implementation does not support this. See bug #5031735.
            // In theory it is possible to pop frames in such cases.
            return JVMTI_ERROR_OPAQUE_FRAME;
          }
        }

  {- -------------------------------------------
  (1) 先頭 2個のフレームのうち compiled frame のものについては, Deoptimization::deoptimize_frame() で deopt しておく.
      (Deoptimization::deoptimize_frame() は呼び出し1回につき1つのフレームを deopt する.
       どちらも compiled frame だったら, Deoptimization::deoptimize_frame() を 2回呼び出すことになる)
      ---------------------------------------- -}

        // If any of the top 2 frames is a compiled one, need to deoptimize it
        for (int i = 0; i < 2; i++) {
          if (!is_interpreted[i]) {
            Deoptimization::deoptimize_frame(java_thread, frame_sp[i]);
          }
        }

  {- -------------------------------------------
  (1) JvmtiThreadState::update_for_pop_top_frame() を呼び出し, 
      pop しようとしているフレームに対して設定されている NotifyFramePop() を全て破棄する.
      (これは JVMTI 仕様で要求されている挙動)
      ---------------------------------------- -}

        // Update the thread state to reflect that the top frame is popped
        // so that cur_stack_depth is maintained properly and all frameIDs
        // are invalidated.
        // The current frame will be popped later when the suspended thread
        // is resumed and right before returning from VM to Java.
        // (see call_VM_base() in assembler_<cpu>.cpp).

        // It's fine to update the thread state here because no JVMTI events
        // shall be posted for this PopFrame.

        state->update_for_pop_top_frame();

  {- -------------------------------------------
  (1) JavaThread::set_popframe_condition() と 
      JvmtiThreadState::set_pending_step_for_popframe() を呼んで, 
      PopFrame() 処理の対象になっていることを JavaThread (及び JvmtiThreadState) オブジェクト内に記録しておく.

      (これらはフレームの pop 処理を開始させるためのフラグ.
       実際の pop 処理は, deopt 処理または call_VM_base() からのリターン処理時に行われる.)
      ---------------------------------------- -}

        java_thread->set_popframe_condition(JavaThread::popframe_pending_bit);
        // Set pending step flag for this popframe and it is cleared when next
        // step event is posted.
        state->set_pending_step_for_popframe();
      }

  {- -------------------------------------------
  (1) リターン
      ---------------------------------------- -}

      return JVMTI_ERROR_NONE;
    } /* end PopFrame */

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