From nobody Mon Sep 17 00:00:00 2001 From: Eugene Ostrovsky Date: Wed, 27 Sep 2006 20:22:05 +0400 Subject: [PATCH] [DRLVM] [JVMTI] GetFrameLocation() returns wrong method id. When throwing an exception, MethodExit event callback is called for every frame unwinded from the java stack. Though calling GetFrameLocation() from the callback returns information based on the state before exception throwing. Such behavious contradicts JVMTI spec for MethodExit event.. Proposed patch saves current frame information in topmost m2n frame while iterating through the unwinding stack. This issue depends on: HARMONY-1602 [DRLVM][JVMTI] The incorrect line num... --- vm/port/include/m2n.h | 4 + vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp | 1 vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp | 22 +++- vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp | 1 vm/vmcore/include/jvmti_direct.h | 1 vm/vmcore/src/exception/exceptions_jit.cpp | 5 + vm/vmcore/src/jvmti/jvmti_event.cpp | 100 +++++++++++++++----- vm/vmcore/src/jvmti/jvmti_pop_frame.cpp | 2 8 files changed, 99 insertions(+), 37 deletions(-) mode change 100644 => 100755 vm/port/include/m2n.h mode change 100644 => 100755 vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp mode change 100644 => 100755 vm/vmcore/include/jvmti_direct.h mode change 100644 => 100755 vm/vmcore/src/exception/exceptions_jit.cpp mode change 100644 => 100755 vm/vmcore/src/jvmti/jvmti_event.cpp mode change 100644 => 100755 vm/vmcore/src/jvmti/jvmti_pop_frame.cpp 9c2e78901ebb296810abd707e1d62028403ecce8 diff --git a/vm/port/include/m2n.h b/vm/port/include/m2n.h old mode 100644 new mode 100755 index ea98638..3fccbc9 --- a/vm/port/include/m2n.h +++ b/vm/port/include/m2n.h @@ -53,7 +53,9 @@ enum frame_type { FRAME_POP_MASK = 0x0700, - FRAME_SAFE_POINT = 0x0800 + FRAME_SAFE_POINT = 0x0800, + + FRAME_MODIFIED_STACK = 0x1000 }; // The pushing and popping of native frames is done only by stubs that diff --git a/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp b/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp index c331052..eae010f 100644 --- a/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp +++ b/vm/port/src/lil/em64t/pim/stack_iterator_em64t.cpp @@ -344,7 +344,6 @@ void si_transfer_control(StackIterator * void si_copy_to_registers(StackIterator * si, Registers * regs) { ASSERT_NO_INTERPRETER - m2n_set_last_frame(si->m2n_frame); regs->rsp = si->jit_frame_context.rsp; regs->rbp = *si->jit_frame_context.p_rbp; diff --git a/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp b/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp old mode 100644 new mode 100755 index 858c10b..2856270 --- a/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp +++ b/vm/port/src/lil/ia32/pim/stack_iterator_ia32.cpp @@ -88,7 +88,7 @@ #endif si->c.p_edi = &m2nfl->regs->edi; si->c.p_ebp = &m2nfl->regs->ebp; } else if (over_popped && - (FRAME_POP_DONE == (FRAME_POP_MASK & m2n_get_frame_type(m2nfl)))) { + (FRAME_MODIFIED_STACK == (FRAME_MODIFIED_STACK & m2n_get_frame_type(m2nfl)))) { si->c.esp = m2nfl->pop_regs->esp; si->c.p_eip = &(m2nfl->pop_regs->eip); si->c.is_ip_past = FALSE; @@ -494,17 +494,23 @@ #endif // _WIN32 tcs(&local_si); } +inline static uint32 unref_reg(uint32* p_reg) { + return p_reg ? *p_reg : 0; +} + void si_copy_to_registers(StackIterator* si, Registers* regs) { ASSERT_NO_INTERPRETER - m2n_set_last_frame(si->m2nfl); + regs->esp = si->c.esp; - regs->eip = *si->c.p_eip; - regs->ebp = *si->c.p_ebp; - regs->edi = *si->c.p_edi; - regs->esi = *si->c.p_esi; - regs->ebx = *si->c.p_ebx; - regs->eax = *si->c.p_eax; + regs->eip = unref_reg(si->c.p_eip); + regs->ebp = unref_reg(si->c.p_ebp); + regs->edi = unref_reg(si->c.p_edi); + regs->esi = unref_reg(si->c.p_esi); + regs->edx = unref_reg(si->c.p_edx); + regs->ecx = unref_reg(si->c.p_ecx); + regs->ebx = unref_reg(si->c.p_ebx); + regs->eax = unref_reg(si->c.p_eax); } void si_set_callbak(StackIterator* si, NativeCodePtr* callback) { diff --git a/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp b/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp index 87472a5..dcbf0b9 100644 --- a/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp +++ b/vm/port/src/lil/ipf/pim/stack_iterator_ipf.cpp @@ -617,7 +617,6 @@ void si_transfer_control(StackIterator* void si_copy_to_registers(StackIterator* si, Registers*) { ABORT("Not implemented"); - m2n_set_last_frame(si->m2nfl); } extern "C" void do_loadrs_asm(int loadrs); diff --git a/vm/vmcore/include/jvmti_direct.h b/vm/vmcore/include/jvmti_direct.h old mode 100644 new mode 100755 index b6855f0..03c28c4 --- a/vm/vmcore/include/jvmti_direct.h +++ b/vm/vmcore/include/jvmti_direct.h @@ -131,6 +131,7 @@ ManagedObject *jvmti_jit_exception_catch NativeCodePtr native_catch_location); VMEXPORT void jvmti_process_method_entry_event(jmethodID method); VMEXPORT void jvmti_process_method_exit_event(jmethodID method, jboolean exn_flag, jvalue ret_val); +VMEXPORT void jvmti_process_method_exception_exit_event(jmethodID method, jboolean exn_flag, jvalue ret_val, StackIterator* si); VMEXPORT void jvmti_process_field_access_event(Field_Handle field, jmethodID method, jlocation location, ManagedObject* object); VMEXPORT void jvmti_process_field_modification_event(Field_Handle field, diff --git a/vm/vmcore/src/exception/exceptions_jit.cpp b/vm/vmcore/src/exception/exceptions_jit.cpp old mode 100644 new mode 100755 index 15344ca..38ad36c --- a/vm/vmcore/src/exception/exceptions_jit.cpp +++ b/vm/vmcore/src/exception/exceptions_jit.cpp @@ -338,8 +338,8 @@ #endif // VM_STATS BEGIN_RAISE_AREA; jvalue ret_val = {(jlong)0}; - jvmti_process_method_exit_event(reinterpret_cast(method), - JNI_TRUE, ret_val); + jvmti_process_method_exception_exit_event( + reinterpret_cast(method), JNI_TRUE, ret_val, si); END_RAISE_AREA; // Goto previous frame @@ -468,6 +468,7 @@ #ifndef _IPF_ ManagedObject *local_exn_obj = NULL; exn_propagate_exception(si, &local_exn_obj, exn_class, NULL, NULL, NULL); si_copy_to_registers(si, regs); + m2n_set_last_frame(si_get_m2n(si)); si_free(si); STD_FREE(m2nf); #endif diff --git a/vm/vmcore/src/jvmti/jvmti_event.cpp b/vm/vmcore/src/jvmti/jvmti_event.cpp old mode 100644 new mode 100755 index 751ca3a..c1209bf --- a/vm/vmcore/src/jvmti/jvmti_event.cpp +++ b/vm/vmcore/src/jvmti/jvmti_event.cpp @@ -37,6 +37,8 @@ #include "jit_intf_cpp.h" #include "vm_log.h" #include "compile.h" #include "jvmti_break_intf.h" +#include "stack_iterator.h" +#include "m2n.h" /* * Set Event Callbacks @@ -657,20 +659,12 @@ jvmti_process_method_entry_event(jmethod tmn_suspend_disable(); } -VMEXPORT void -jvmti_process_method_exit_event(jmethodID method, jboolean was_popped_by_exception, jvalue ret_val) { - SuspendDisabledChecker sdc; - +static void +jvmti_process_method_exit_event_internal(jmethodID method, + jboolean was_popped_by_exception, + jvalue ret_val) +{ DebugUtilsTI *ti = VM_Global_State::loader_env->TI; - if (!ti->isEnabled() ) - return; - - if (JVMTI_PHASE_LIVE != ti->getPhase()) - return; - - if (!ti->get_global_capability(DebugUtilsTI::TI_GC_ENABLE_METHOD_EXIT)) - return; - tmn_suspend_enable(); jvmtiEvent event_type = JVMTI_EVENT_METHOD_EXIT; hythread_t curr_native_thread = hythread_self(); @@ -699,7 +693,6 @@ jvmti_process_method_exit_event(jmethodI jthread thread = getCurrentThread(); JNIEnv *jni_env = (JNIEnv *)jni_native_intf; jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env; - if (NULL != ti_env->event_table.MethodExit) ti_env->event_table.MethodExit(jvmti_env, jni_env, thread, method, was_popped_by_exception, ret_val); ti_env = next_env; @@ -719,31 +712,92 @@ jvmti_process_method_exit_event(jmethodI } VM_thread *curr_thread = p_TLS_vmthread; - jvmti_frame_pop_listener *fpl = curr_thread->frame_pop_listener; jint UNREF skip; jint depth = get_thread_stack_depth(curr_thread, &skip); - while (fpl) + jvmti_frame_pop_listener *last = NULL; + for( jvmti_frame_pop_listener *fpl = curr_thread->frame_pop_listener; + fpl; + last = fpl, (fpl = fpl ? fpl->next : curr_thread->frame_pop_listener) ) { - jvmti_frame_pop_listener *next_fpl = fpl->next; if (fpl->depth == depth) { + jvmti_frame_pop_listener *report = fpl; + if(last) { + last->next = fpl->next; + } else { + curr_thread->frame_pop_listener = fpl->next; + } + fpl = last; + jvmti_process_frame_pop_event( - reinterpret_cast(fpl->env), + reinterpret_cast(report->env), method, was_popped_by_exception); - if( fpl == curr_thread->frame_pop_listener ) { - curr_thread->frame_pop_listener = fpl->next; - } - STD_FREE(fpl); + STD_FREE(report); } - fpl = next_fpl; } tmn_suspend_disable(); } VMEXPORT void +jvmti_process_method_exit_event(jmethodID method, + jboolean was_popped_by_exception, + jvalue ret_val) +{ + SuspendDisabledChecker sdc; + + DebugUtilsTI *ti = VM_Global_State::loader_env->TI; + if (!ti->isEnabled() ) + return; + + if (JVMTI_PHASE_LIVE != ti->getPhase()) + return; + + if (!ti->get_global_capability(DebugUtilsTI::TI_GC_ENABLE_METHOD_EXIT)) + return; +} + +VMEXPORT void +jvmti_process_method_exception_exit_event(jmethodID method, + jboolean was_popped_by_exception, + jvalue ret_val, + StackIterator* si) +{ + SuspendDisabledChecker sdc; + + DebugUtilsTI *ti = VM_Global_State::loader_env->TI; + if (!ti->isEnabled() ) + return; + + if (JVMTI_PHASE_LIVE != ti->getPhase()) + return; + + if (!ti->get_global_capability(DebugUtilsTI::TI_GC_ENABLE_METHOD_EXIT)) + return; + + // save context from stack interation to m2n frame + Registers regs; + si_copy_to_registers(si, ®s); + M2nFrame* m2nf = m2n_get_last_frame(); + set_pop_frame_registers(m2nf, ®s); + + // save old type of m2n frame + frame_type old_type = m2n_get_frame_type(m2nf); + + // enable modified stack context in m2n frame + m2n_set_frame_type(m2nf, frame_type(FRAME_MODIFIED_STACK | old_type)); + + // process method exit event + jvmti_process_method_exit_event_internal(method, was_popped_by_exception, ret_val); + + // restore old frame type and switch off context modification + m2n_set_frame_type(m2nf, old_type); + set_pop_frame_registers(m2nf, NULL); +} + +VMEXPORT void jvmti_process_frame_pop_event(jvmtiEnv *jvmti_env, jmethodID method, jboolean was_popped_by_exception) { DebugUtilsTI *ti = VM_Global_State::loader_env->TI; diff --git a/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp b/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp old mode 100644 new mode 100755 index 0dc470a..88fd529 --- a/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp +++ b/vm/vmcore/src/jvmti/jvmti_pop_frame.cpp @@ -315,7 +315,7 @@ void jvmti_jit_prepare_pop_frame() { } // set pop done frame state - m2n_set_frame_type(top_frame, FRAME_POP_DONE); + m2n_set_frame_type(top_frame, frame_type(FRAME_POP_DONE | FRAME_MODIFIED_STACK)); return; } -- 1.3.3