6972759: Step over not working after thrown exception and Pop
Summary: reset jvmtithreadstate exception state after frame pop and forceearlyreturn processed
Reviewed-by: minqi, dholmes, dlong
Contributed-by: bill.pittore@oracle.com
--- a/hotspot/src/share/vm/prims/jvmtiThreadState.cpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/prims/jvmtiThreadState.cpp Sat Jan 21 23:02:40 2012 -0500
@@ -319,6 +319,15 @@
// clearing the flag indicates we are done with the PopFrame() dance
clr_pending_step_for_popframe();
+ // If exception was thrown in this frame, need to reset jvmti thread state.
+ // Single stepping may not get enabled correctly by the agent since
+ // exception state is passed in MethodExit event which may be sent at some
+ // time in the future. JDWP agent ignores MethodExit events if caused by
+ // an exception.
+ //
+ if (is_exception_detected()) {
+ clear_exception_detected();
+ }
// If step is pending for popframe then it may not be
// a repeat step. The new_bci and method_id is same as current_bci
// and current method_id after pop and step for recursive calls.
@@ -385,6 +394,15 @@
// the ForceEarlyReturn() dance
clr_pending_step_for_earlyret();
+ // If exception was thrown in this frame, need to reset jvmti thread state.
+ // Single stepping may not get enabled correctly by the agent since
+ // exception state is passed in MethodExit event which may be sent at some
+ // time in the future. JDWP agent ignores MethodExit events if caused by
+ // an exception.
+ //
+ if (is_exception_detected()) {
+ clear_exception_detected();
+ }
// If step is pending for earlyret then it may not be a repeat step.
// The new_bci and method_id is same as current_bci and current
// method_id after earlyret and step for recursive calls.
--- a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp Wed Jan 11 17:58:26 2012 -0500
+++ b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp Sat Jan 21 23:02:40 2012 -0500
@@ -165,6 +165,10 @@
inline bool is_exception_caught() { return _exception_caught; }
inline void set_exception_detected() { _exception_detected = true;
_exception_caught = false; }
+ inline void clear_exception_detected() {
+ _exception_detected = false;
+ assert(_exception_caught == false, "_exception_caught is out of phase");
+ }
inline void set_exception_caught() { _exception_caught = true;
_exception_detected = false; }