hotspot/src/share/vm/prims/jvmtiEnv.cpp
// Threads_lock NOT held, java_thread not protected by lock
// java_thread - pre-checked
jvmtiError
JvmtiEnv::PopFrame(JavaThread* java_thread) {
{- -------------------------------------------
(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.