From 6f1e93c7f179d40a03ce718a09331d584ff6a021 Mon Sep 17 00:00:00 2001 From: kgallowa Date: Mon, 29 Jan 2007 22:05:56 +0000 Subject: [PATCH] 2007-01-29 Kyle Galloway * include/java-interp.h: Added _Jv_Frame class and its two subclasses _Jv_InterpFrame and _Jv_NativeFrame. Also moved _Jv_FrameType from java-stack.h. * include/java-stack.h: Removed _Jv_FrameType. * java/lang/Thread.java: Added frame member to hold new composite frame stack. * java/lang/Thread.h: Regenerated. * java/lang/Thread.class: Rebuilt. * jni.cc (_Jv_JNIMethod::call): Push a frame onto the stack when calling a JNI method. * jvmti.cc (_Jv_JVMTI_GetStackTrace): New Method. (_Jv_JVMTI_GetFrameCount): New method. * stacktrace.cc (UnwindTraceFn): Modified to use new _Jv_Frame classes. * testsuite/libjava.jvmti/interp/getstacktrace.jar: New test. * testsuite/libjava.jvmti/interp/natgetstacktrace.cc: New test. * testsuite/libjava.jvmti/interp/getstacktrace.h: New test. * testsuite/libjava.jvmti/interp/getstacktrace.jar: New test. * testsuite/libjava.jvmti/interp/getstacktrace.out: Output file for test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121314 138bc75d-0d04-0410-961f-82ee72b054a4 --- libjava/ChangeLog | 23 +++ .../lib/java/lang/Thread$State.class | Bin 1242 -> 1242 bytes libjava/classpath/lib/java/lang/Thread.class | Bin 9327 -> 9343 bytes libjava/include/java-interp.h | 79 ++++++++-- libjava/include/java-stack.h | 7 - libjava/java/lang/Thread.h | 3 +- libjava/java/lang/Thread.java | 3 + libjava/jni.cc | 4 + libjava/jvmti.cc | 108 ++++++++++++- libjava/stacktrace.cc | 8 +- .../libjava.jvmti/interp/getstacktrace.h | 21 +++ .../libjava.jvmti/interp/getstacktrace.jar | Bin 0 -> 1237 bytes .../libjava.jvmti/interp/getstacktrace.java | 88 +++++++++++ .../libjava.jvmti/interp/getstacktrace.out | 76 +++++++++ .../libjava.jvmti/interp/natgetstacktrace.cc | 144 ++++++++++++++++++ 15 files changed, 537 insertions(+), 27 deletions(-) create mode 100644 libjava/testsuite/libjava.jvmti/interp/getstacktrace.h create mode 100644 libjava/testsuite/libjava.jvmti/interp/getstacktrace.jar create mode 100644 libjava/testsuite/libjava.jvmti/interp/getstacktrace.java create mode 100644 libjava/testsuite/libjava.jvmti/interp/getstacktrace.out create mode 100644 libjava/testsuite/libjava.jvmti/interp/natgetstacktrace.cc diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 20e91fdb1fd4..037b1bb650d8 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,26 @@ +2007-01-29 Kyle Galloway + + * include/java-interp.h: Added _Jv_Frame class and its two + subclasses _Jv_InterpFrame and _Jv_NativeFrame. Also moved + _Jv_FrameType from java-stack.h. + * include/java-stack.h: Removed _Jv_FrameType. + * java/lang/Thread.java: Added frame member to hold new + composite frame stack. + * java/lang/Thread.h: Regenerated. + * java/lang/Thread.class: Rebuilt. + * jni.cc (_Jv_JNIMethod::call): Push a frame onto the stack when + calling a JNI method. + * jvmti.cc (_Jv_JVMTI_GetStackTrace): New Method. + (_Jv_JVMTI_GetFrameCount): New method. + * stacktrace.cc (UnwindTraceFn): Modified to use new _Jv_Frame + classes. + * testsuite/libjava.jvmti/interp/getstacktrace.jar: New test. + * testsuite/libjava.jvmti/interp/natgetstacktrace.cc: New test. + * testsuite/libjava.jvmti/interp/getstacktrace.h: New test. + * testsuite/libjava.jvmti/interp/getstacktrace.jar: New test. + * testsuite/libjava.jvmti/interp/getstacktrace.out: Output file + for test. + 2007-01-29 Tom Tromey * interpret.cc (run_debug): Remove comment. diff --git a/libjava/classpath/lib/java/lang/Thread$State.class b/libjava/classpath/lib/java/lang/Thread$State.class index a7d5a333f22395a74b272ab11d3ed6608424990a..3ce018edd9c8b3d245b8578bcaff6d63be38e2de 100644 GIT binary patch delta 23 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 literal 9327 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 + thr->frame = (gnu::gcj::RawData *) this; + thread = thr; + } + + ~_Jv_Frame () + { + thread->frame = (gnu::gcj::RawData *) next; + } +}; + +// An interpreted frame in the call stack +class _Jv_InterpFrame : public _Jv_Frame +{ +public: + + // Keep the purely interpreted list around so as not to break backtraces + _Jv_InterpFrame *next_interp; + union { pc_t pc; jclass proxyClass; }; - - _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyClass = NULL) + + //Debug info for local variables. + _Jv_word *locals; + char *locals_type; + + _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyCls = NULL) + : _Jv_Frame (reinterpret_cast<_Jv_MethodBase *> (meth), thr, + frame_interpreter) { - this->meth = meth; - thread = thr; - next = (_Jv_InterpFrame *) thr->interp_frame; + next_interp = (_Jv_InterpFrame *) thr->interp_frame; + proxyClass = proxyCls; thr->interp_frame = (gnu::gcj::RawData *) this; - this->proxyClass = proxyClass; } ~_Jv_InterpFrame () { - thread->interp_frame = (gnu::gcj::RawData *) next; + thread->interp_frame = (gnu::gcj::RawData *) next_interp; + } +}; + +// A native frame in the call stack really just a placeholder +class _Jv_NativeFrame : public _Jv_Frame +{ +public: + + _Jv_NativeFrame (_Jv_JNIMethod *s, java::lang::Thread *thr) + : _Jv_Frame (s, thr, frame_native) + { } }; diff --git a/libjava/include/java-stack.h b/libjava/include/java-stack.h index d4d63d743420..49e68412be63 100644 --- a/libjava/include/java-stack.h +++ b/libjava/include/java-stack.h @@ -41,13 +41,6 @@ extern "Java" } } -enum _Jv_FrameType -{ - frame_native, - frame_interpreter, - frame_proxy -}; - #ifdef INTERPRETER struct _Jv_InterpFrameInfo { diff --git a/libjava/java/lang/Thread.h b/libjava/java/lang/Thread.h index 74e149030f76..d5fce8638771 100644 --- a/libjava/java/lang/Thread.h +++ b/libjava/java/lang/Thread.h @@ -144,7 +144,8 @@ public: // actually package-private static const jbyte THREAD_PARK_DEAD = 3; ::java::lang::Object * accessControlState; ::gnu::gcj::RawData * interp_frame; - jint volatile state; + ::gnu::gcj::RawData * frame; + volatile jint state; ::gnu::gcj::RawDataManaged * data; public: static ::java::lang::Class class$; diff --git a/libjava/java/lang/Thread.java b/libjava/java/lang/Thread.java index 9666482040af..7216512530df 100644 --- a/libjava/java/lang/Thread.java +++ b/libjava/java/lang/Thread.java @@ -182,6 +182,9 @@ public class Thread implements Runnable // This describes the top-most interpreter frame for this thread. RawData interp_frame; + + // This describes the top most frame in the composite (interp + JNI) stack + RawData frame; // Current state. volatile int state; diff --git a/libjava/jni.cc b/libjava/jni.cc index 59c1e5fd03e8..07ef71345409 100644 --- a/libjava/jni.cc +++ b/libjava/jni.cc @@ -2339,6 +2339,10 @@ _Jv_JNIMethod::call (ffi_cif *, void *ret, ffi_raw *args, void *__this) // Copy over passed-in arguments. memcpy (&real_args[offset], args, _this->args_raw_size); + + // Add a frame to the composite (interpreted + JNI) call stack + java::lang::Thread *thread = java::lang::Thread::currentThread(); + _Jv_NativeFrame nat_frame (_this, thread); // The actual call to the JNI function. #if FFI_NATIVE_RAW_API diff --git a/libjava/jvmti.cc b/libjava/jvmti.cc index 03eec74b4c1a..c9c7e7ba731a 100644 --- a/libjava/jvmti.cc +++ b/libjava/jvmti.cc @@ -236,6 +236,34 @@ _Jv_JVMTI_GetAllThreads(MAYBE_UNUSED jvmtiEnv *env, jint *thread_cnt, return JVMTI_ERROR_NONE; } +static jvmtiError JNICALL +_Jv_JVMTI_GetFrameCount (MAYBE_UNUSED jvmtiEnv *env, jthread thread, + jint* frame_count) +{ + REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); + + NULL_CHECK (frame_count); + + using namespace java::lang; + + THREAD_DEFAULT_TO_CURRENT (thread); + + Thread *thr = reinterpret_cast (thread); + THREAD_CHECK_VALID (thr); + THREAD_CHECK_IS_ALIVE (thr); + + _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thr->frame); + (*frame_count) = 0; + + while (frame != NULL) + { + (*frame_count)++; + frame = frame->next; + } + + return JVMTI_ERROR_NONE; +} + static jvmtiError JNICALL _Jv_JVMTI_CreateRawMonitor (MAYBE_UNUSED jvmtiEnv *env, const char *name, jrawMonitorID *result) @@ -747,6 +775,82 @@ _Jv_JVMTI_GetClassLoaderClasses (MAYBE_UNUSED jvmtiEnv *env, return JVMTI_ERROR_NONE; } +static jvmtiError JNICALL +_Jv_JVMTI_GetStackTrace (MAYBE_UNUSED jvmtiEnv *env, jthread thread, + jint start_depth, jint max_frames, + jvmtiFrameInfo *frames, jint *frame_count) +{ + REQUIRE_PHASE (env, JVMTI_PHASE_LIVE); + + ILLEGAL_ARGUMENT (max_frames < 0); + + NULL_CHECK (frames); + NULL_CHECK (frame_count); + + using namespace java::lang; + + THREAD_DEFAULT_TO_CURRENT (thread); + + Thread *thr = reinterpret_cast (thread); + THREAD_CHECK_VALID (thr); + THREAD_CHECK_IS_ALIVE (thr); + + jvmtiError jerr = env->GetFrameCount (thread, frame_count); + if (jerr != JVMTI_ERROR_NONE) + return jerr; + + // start_depth can be either a positive number, indicating the depth of the + // stack at which to begin the trace, or a negative number indicating the + // number of frames at the bottom of the stack to exclude. These checks + // ensure that it is a valid value in either case + + ILLEGAL_ARGUMENT (start_depth >= (*frame_count)); + ILLEGAL_ARGUMENT (start_depth < (-(*frame_count))); + + _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thr->frame); + + // If start_depth is negative use this to determine at what depth to start + // the trace by adding it to the length of the call stack. This allows the + // use of the same frame "discarding" mechanism as for a positive start_depth + if (start_depth < 0) + start_depth = *frame_count + start_depth; + + // If start_depth > 0 "remove" start_depth frames from the beginning + // of the stack before beginning the trace by moving along the frame list. + while (start_depth > 0) + { + frame = frame->next; + start_depth--; + (*frame_count)--; + } + + // Now check to see if the array supplied by the agent is large enough to + // hold frame_count frames, after adjustment for start_depth. + if ((*frame_count) > max_frames) + (*frame_count) = max_frames; + + for (int i = 0; i < (*frame_count); i++) + { + frames[i].method = frame->self->get_method (); + + // Set the location in the frame, native frames have location = -1 + if (frame->frame_type == frame_interpreter) + { + _Jv_InterpMethod *imeth + = static_cast<_Jv_InterpMethod *> (frame->self); + _Jv_InterpFrame *interp_frame + = static_cast<_Jv_InterpFrame *> (frame); + frames[i].location = imeth->insn_index (interp_frame->pc); + } + else + frames[i].location = -1; + + frame = frame->next; + } + + return JVMTI_ERROR_NONE; +} + static jvmtiError JNICALL _Jv_JVMTI_ForceGarbageCollection (MAYBE_UNUSED jvmtiEnv *env) { @@ -1484,7 +1588,7 @@ struct _Jv_jvmtiEnv _Jv_JVMTI_Interface = UNIMPLEMENTED, // GetTopThreadGroups UNIMPLEMENTED, // GetThreadGroupInfo UNIMPLEMENTED, // GetThreadGroupChildren - UNIMPLEMENTED, // GetFrameCount + _Jv_JVMTI_GetFrameCount, // GetFrameCount UNIMPLEMENTED, // GetThreadState RESERVED, // reserved18 UNIMPLEMENTED, // GetFrameLocation @@ -1572,7 +1676,7 @@ struct _Jv_jvmtiEnv _Jv_JVMTI_Interface = UNIMPLEMENTED, // GetThreadListStackTraces UNIMPLEMENTED, // GetThreadLocalStorage UNIMPLEMENTED, // SetThreadLocalStorage - UNIMPLEMENTED, // GetStackTrace + _Jv_JVMTI_GetStackTrace, // GetStackTrace RESERVED, // reserved105 UNIMPLEMENTED, // GetTag UNIMPLEMENTED, // SetTag diff --git a/libjava/stacktrace.cc b/libjava/stacktrace.cc index 5751e29b5f1e..c3fbdf4e6a43 100644 --- a/libjava/stacktrace.cc +++ b/libjava/stacktrace.cc @@ -131,9 +131,11 @@ _Jv_StackTrace::UnwindTraceFn (struct _Unwind_Context *context, void *state_ptr) if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run)) { state->frames[pos].type = frame_interpreter; - state->frames[pos].interp.meth = state->interp_frame->self; + _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame); + state->frames[pos].interp.meth + = static_cast<_Jv_InterpMethod *> (frame->self); state->frames[pos].interp.pc = state->interp_frame->pc; - state->interp_frame = state->interp_frame->next; + state->interp_frame = state->interp_frame->next_interp; } else #endif @@ -143,7 +145,7 @@ _Jv_StackTrace::UnwindTraceFn (struct _Unwind_Context *context, void *state_ptr) state->frames[pos].type = frame_proxy; state->frames[pos].proxyClass = state->interp_frame->proxyClass; state->frames[pos].proxyMethod = state->interp_frame->proxyMethod; - state->interp_frame = state->interp_frame->next; + state->interp_frame = state->interp_frame->next_interp; } else { diff --git a/libjava/testsuite/libjava.jvmti/interp/getstacktrace.h b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.h new file mode 100644 index 000000000000..6e5e8774e253 --- /dev/null +++ b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ + +#ifndef __getstacktrace__ +#define __getstacktrace__ + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +JNIEXPORT void JNICALL Java_getstacktrace_natPlaceholder (JNIEnv *env, jobject); +JNIEXPORT void JNICALL Java_getstacktrace_natRunner (JNIEnv *env, jobject); +JNIEXPORT jint JNICALL Java_getstacktrace_do_1getstacktrace_1tests (JNIEnv *env, jclass, jobjectArray); + +#ifdef __cplusplus +} +#endif + +#endif /* __getstacktrace__ */ diff --git a/libjava/testsuite/libjava.jvmti/interp/getstacktrace.jar b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.jar new file mode 100644 index 0000000000000000000000000000000000000000..14b084a4de11b88f063a3ecea605f2d7e8705be4 GIT binary patch literal 1237 zc-jl_W@h1H0D%K(wq^`SfD?#)T|*poJ^kGD15lLh(9KQM0kT0@1X-D{qo1dnYjB93 zubXdTUS?WqafxnNYEf}!ex8+rp`HPkb5UwyNotC&Q>B%Hfu5z2ZhCSu7Z=QQ4u)+& z)4NuGRPkqKV8~)+U=Rk1rl*z^mn0@STUkwuwt59Od;1<~wR_;O&SI8N#Ni`)_x=ihT`A9R6V4jB>lOct_!sA2 zIETl3eV=(HAtH9QarWKf=W~kB-%Fowz5nmuZ?+AWHI7_dcwuwWp{*BU>!jG;ZR$K6 z^rHTeUGef&>-HOk*2ze0Uz8B~YF}W$chQ{vfzdT0J4`pbxi|J1cttIVUl_f}m;G?( z%crZJS3gv3z47CS&Fh%8;XXoKwNhq6oHb4s_jzx7+>khsAoKgyj49WyI|W~sIAjpG zs&sqMmuXDq5#bUt`gK#p+2-w^B)(zaqUW<`_uiVsdFoxz)IYnIDVv!kNnHHF6SYF- z!V4F1NjBd2ea2FrDk+56?*s!2Z|S8ct- zV<{EMS-O7PZ~rWxuKn5>p_WT6d3IS{w+&u;&3Wptq}g)a3nRH#KD+Rv`O&?LPt+|K zS3j%zcdx>`L*?n8pvN|P8;(~gFG)CSvfi$=+fvcEH~O^tg!IMt&z+yjJu}i-|KsVV z`I!#-( z=;Q~iyvH%^Y^i_Rl&sgaK@0|`o=E7gbv+$fxID#ZqOY5o=5@_YoF&ee?;qB050krH z)p{@Fzgf_JmvpYgq@A@pv0>_+_G>%)UMzXL=U|=sw$3m2ibdw;f4+0@+RmsW z0y`e;ae3eLb;63-7EdhJ7iI`AHd%b_yw0xH!_pFB`OjZ)#P& z6W$x}O}HnxPMx!yPqMGLXXZ_@FXc;AFBqR|IuKI!(QTH)HGcUC{FmnZh-W%}W9}NW zKIK-ag%M=Hbd7bU%Kb+FXQGfY?;!L z-DmsEvPp(<+0;q%J3YPXOm8iT>C0I1TuFlQM<-MFpU?UqUA4BizO4Hlz9Q+(BeuS@ z%kLM6-Fx7rIoob?>-t$A?o2-L-MZfHeZb2%zvav8&gVV8Wovoy@QgFxoS*c^_F48x z?r^Kyd`I*L``rcKT)7O~J@bP4EH`OS_?vt0n~?E)qo_w!{i11=+nDeFVGi(SWa47L uT@0WCq(T8z8+x&T0O~jj34{sQvpxc}VlM~+yjj^m(#$}(3rMrFfOr6Dn(;6I literal 0 Hc-jL100001 diff --git a/libjava/testsuite/libjava.jvmti/interp/getstacktrace.java b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.java new file mode 100644 index 000000000000..21a21f0fbb10 --- /dev/null +++ b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.java @@ -0,0 +1,88 @@ +public class getstacktrace + extends Thread +{ + public boolean done = false; + + // num_frames is the number of frames > the original run () call so if + // num_frames = 1, the thread will have 2 frames, the original Thread.run + // call, plus one additional + public int num_frames, thread_num; + + public static int num_threads = 1; + + static + { + System.loadLibrary("natgetstacktrace"); + } + + public void run () + { + thread_num = num_threads++; + num_frames = thread_num; + + if (num_frames <= 1) + { + natRunner (); + } + else + { + if (thread_num % 2 == 0) + natPlaceholder (); + else + placeholder (); + } + } + + public void placeholder () + { + num_frames--; + if (num_frames <= 1) + { + if (thread_num % 2 == 1) + natRunner (); + else + runner (); + } + else + { + if (thread_num % 2 == 0) + natPlaceholder (); + else + placeholder (); + } + } + + public void runner () + { + done = true; + while (done) + yield (); + } + + public native void natPlaceholder (); + public native void natRunner (); + + public static native int do_getstacktrace_tests (Thread[] threads); + + public static void main (String[] args) + { + System.out.println ("JVMTI GetStackTrace Interpreted Test"); + + getstacktrace[] threads = new getstacktrace[10]; + + for (int i = 0; i < threads.length; i++) + { + threads[i] = new getstacktrace (); + threads[i].start (); + while (!threads[i].done) + yield (); + } + + do_getstacktrace_tests (threads); + + for (int i = 0; i < threads.length; i++) + { + threads[i].done = false; + } + } +} diff --git a/libjava/testsuite/libjava.jvmti/interp/getstacktrace.out b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.out new file mode 100644 index 000000000000..5134e6eab78e --- /dev/null +++ b/libjava/testsuite/libjava.jvmti/interp/getstacktrace.out @@ -0,0 +1,76 @@ +JVMTI GetStackTrace Interpreted Test +Thread has 2 frames +Frame 0 is native +Frame 1 is interpreted +Thread has 3 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is interpreted +Thread has 4 frames +Frame 0 is native +Frame 1 is interpreted +Frame 2 is interpreted +Frame 3 is interpreted +Thread has 5 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is native +Frame 3 is native +Frame 4 is interpreted +Thread has 6 frames +Frame 0 is native +Frame 1 is interpreted +Frame 2 is interpreted +Frame 3 is interpreted +Frame 4 is interpreted +Frame 5 is interpreted +Thread has 7 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is native +Frame 3 is native +Frame 4 is native +Frame 5 is native +Frame 6 is interpreted +Thread has 8 frames +Frame 0 is native +Frame 1 is interpreted +Frame 2 is interpreted +Frame 3 is interpreted +Frame 4 is interpreted +Frame 5 is interpreted +Frame 6 is interpreted +Frame 7 is interpreted +Thread has 9 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is native +Frame 3 is native +Frame 4 is native +Frame 5 is native +Frame 6 is native +Frame 7 is native +Frame 8 is interpreted +Thread has 10 frames +Frame 0 is native +Frame 1 is interpreted +Frame 2 is interpreted +Frame 3 is interpreted +Frame 4 is interpreted +Frame 5 is interpreted +Frame 6 is interpreted +Frame 7 is interpreted +Frame 8 is interpreted +Frame 9 is interpreted +Thread has 11 frames +Frame 0 is interpreted +Frame 1 is native +Frame 2 is native +Frame 3 is native +Frame 4 is native +Frame 5 is native +Frame 6 is native +Frame 7 is native +Frame 8 is native +Frame 9 is native +Frame 10 is interpreted diff --git a/libjava/testsuite/libjava.jvmti/interp/natgetstacktrace.cc b/libjava/testsuite/libjava.jvmti/interp/natgetstacktrace.cc new file mode 100644 index 000000000000..e2c88ada40c4 --- /dev/null +++ b/libjava/testsuite/libjava.jvmti/interp/natgetstacktrace.cc @@ -0,0 +1,144 @@ +#include + +#include +#include +#include + +#include + +#include "getstacktrace.h" + +void +printStackTrace (jvmtiFrameInfo *frames, jint frame_cnt) +{ + printf ("Thread has %d frames\n", static_cast (frame_cnt)); + + for (int i = 0; i < frame_cnt; i++) + { + jmethodID method = frames[i].method; + jlocation location = frames[i].location; + + if (location == -1) + { + printf ("Frame %d is native\n", i); + } + else + { + printf ("Frame %d is interpreted\n", i); + } + } +} + + +JNIEXPORT void JNICALL Java_getstacktrace_natPlaceholder (JNIEnv *env, jobject obj) +{ + jclass klass = env->GetObjectClass (obj); + jfieldID done_id = env->GetFieldID (klass, "done", "Z"); + jfieldID num_frames_id = env->GetFieldID (klass, "num_frames", "I"); + jfieldID thread_num_id = env->GetFieldID (klass, "thread_num", "I"); + + // num_frames-- + jint n_frames = env->GetIntField (obj, num_frames_id); + n_frames--; + env->SetIntField (obj, num_frames_id, n_frames); + + jint t_num = env->GetIntField (obj, thread_num_id); + + if (n_frames <= 1) + { + if (t_num % 2 == 1) + { + jmethodID natRunner_id = env->GetMethodID (klass, "natRunner", "()V"); + env->CallVoidMethod (obj, natRunner_id); + } + else + { + jmethodID runner_id = env->GetMethodID (klass, "runner", "()V"); + env->CallVoidMethod (obj, runner_id); + } + } + else + { + if (t_num % 2 == 0) + { + jmethodID natPlaceholder_id = env->GetMethodID (klass, + "natPlaceholder", + "()V"); + env->CallVoidMethod (obj, natPlaceholder_id); + } + else + { + jmethodID placeholder_id = env->GetMethodID (klass, "placeholder", + "()V"); + env->CallVoidMethod (obj, placeholder_id); + } + } +} + +JNIEXPORT void JNICALL Java_getstacktrace_natRunner (JNIEnv *env, jobject obj) +{ + jclass klass = env->GetObjectClass (obj); + jfieldID done_id = env->GetFieldID (klass, "done", "Z"); + + + jboolean done; + done = true; + env->SetBooleanField (obj, done_id, done); + + do + { + done = env->GetBooleanField (obj, done_id); + if (done == false) + break; + usleep (10); + } + while (done != false); +} + +JNIEXPORT jint JNICALL Java_getstacktrace_do_1getstacktrace_1tests +(JNIEnv *env, jclass klass, jobjectArray thr_arr) +{ + JavaVM *vm; + jint err = env->GetJavaVM (&vm); + if (err < 0) + { + fprintf (stderr, "error getting VM\n"); + exit (1); + } + + jvmtiEnv *jvmti = NULL; + vm->GetEnv ((void **) &jvmti, JVMTI_VERSION_1_0); + + if (jvmti == NULL) + { + fprintf (stderr, "error getting jvmti environment\n"); + exit (1); + } + + jint frame_cnt; + jvmtiFrameInfo frames[30]; + + jvmtiError jerr; + jthread thr; + + jsize num_threads = env->GetArrayLength (thr_arr); + + for (int i = 0; i < num_threads; i++) + { + thr = reinterpret_cast + (env->GetObjectArrayElement (thr_arr, static_cast (i))); + fflush (stdout); + jerr = jvmti->GetStackTrace (thr, 0, 30, frames, &frame_cnt); + if (jerr != JVMTI_ERROR_NONE) + { + char *error_name; + jvmti->GetErrorName (jerr, &error_name); + fprintf (stderr, "JVMTI Error: %s\n", error_name); + jvmti->Deallocate (reinterpret_cast (error_name)); + } + else + { + printStackTrace (frames, frame_cnt); + } + } +} -- 2.47.3