2007-09-24 Keith Seitz * include/jvm.h (struct natThread): Add new field 'frame'. * include/java-interp.h (_Jv_Frame): Use _Jv_ThreadStackPeek, _Jv_ThreadStackPop, and _Jv_ThreadStackPush instead of java.lang.Thread.frame. (~_Jv_Frame): Use _Jv_ThreadStackPop. * java/lang/natThread.cc (_Jv_ThreadStackPeek): New function. (_Jv_ThreadStackPush): New function. (_Jv_ThreadStackPop): New function. * java/lang/Thread.java (frame): Remove field to restore C++ ABI compatibility. * gnu/classpath/jdwp/natVMVirtualMachine.cc (getFrames): Use _Jv_ThreadStackPeek. (getFrame): Likewise. * gnu/classpath/jdwp/natVMFrame.cc (getFrameDepth): Likewise. * jvmti.cc (getLocalFrame): Likewise. (_Jv_JVMTI_GetFrameCount): Likewise. (_Jv_JVMTI_GetThreadState): Likewise. (_Jv_JVMTI_GetStackTrace): Likewise. * interpret.cc (_Jv_ReportJVMTIExceptionThrow): Likewise. * headers.txt (java/lang/Thread.h): Prepend declarations for _Jv_ThreadStackPeek, _Jv_ThreadStackPush, and _Jv_ThreadStackPop. Add as friend functions. * jni.cc (_Jv_JNIMethod::call): Push a frame onto the stack when calling a JNI method. --- libjava/interpret.cc (revision 128603) +++ libjava/interpret.cc (working copy) @@ -1709,7 +1709,7 @@ _Jv_ReportJVMTIExceptionThrow (jthrowable ex) { jthread thread = ::java::lang::Thread::currentThread (); - _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); + _Jv_Frame *frame = _Jv_ThreadStackPeek (thread); jmethodID throw_meth = frame->self->get_method (); jlocation throw_loc = -1; if (frame->frame_type == frame_interpreter) --- libjava/include/java-interp.h (revision 128603) +++ libjava/include/java-interp.h (working copy) @@ -391,14 +391,14 @@ { self = s; frame_type = type; - next = (_Jv_Frame *) thr->frame; - thr->frame = (gnu::gcj::RawData *) this; + next = _Jv_ThreadStackPeek (thr); + _Jv_ThreadStackPush (thr, this); thread = thr; } ~_Jv_Frame () { - thread->frame = (gnu::gcj::RawData *) next; + _Jv_ThreadStackPop (thread); } int depth () --- libjava/include/jvm.h (revision 128603) +++ libjava/include/jvm.h (working copy) @@ -34,6 +34,8 @@ #include +class _Jv_Frame; + /* Macro for possible unused arguments. */ #define MAYBE_UNUSED __attribute__((__unused__)) @@ -767,6 +769,12 @@ // Each thread has its own JNI object. _Jv_JNIEnv *jni_env; + + // Describes the topmost frame in the thread's composite + // (interp + JNI) stack. Added here to maintain C++ ABI + // compatibility with previous versions. Newer versions + // of gcj put this in java/lang/Thread.java. + _Jv_Frame *frame; }; #endif /* __JAVA_JVM_H__ */ --- libjava/jni.cc (revision 128603) +++ libjava/jni.cc (working copy) @@ -2343,6 +2343,10 @@ // 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 ffi_raw_call (&_this->jni_cif, (void (*)()) _this->function, --- libjava/jvmti.cc (revision 128603) +++ libjava/jvmti.cc (working copy) @@ -228,7 +228,7 @@ THREAD_CHECK_VALID (thread); THREAD_CHECK_IS_ALIVE (thread); - _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); + _Jv_Frame *frame = _Jv_ThreadStackPeek (thread); for (int i = 0; i < depth; i++) { @@ -516,7 +516,7 @@ THREAD_CHECK_VALID (thread); THREAD_CHECK_IS_ALIVE (thread); - _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); + _Jv_Frame *frame = _Jv_ThreadStackPeek (thread); (*frame_count) = frame->depth (); return JVMTI_ERROR_NONE; } @@ -543,7 +543,7 @@ if (thread->isInterrupted ()) state |= JVMTI_THREAD_STATE_INTERRUPTED; - _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); + _Jv_Frame *frame = _Jv_ThreadStackPeek (thread); if (frame != NULL && frame->frame_type == frame_native) state |= JVMTI_THREAD_STATE_IN_NATIVE; @@ -1273,7 +1273,7 @@ ILLEGAL_ARGUMENT (start_depth >= (*frame_count)); ILLEGAL_ARGUMENT (start_depth < (-(*frame_count))); - _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (thread->frame); + _Jv_Frame *frame = _Jv_ThreadStackPeek (thread); // 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 --- libjava/headers.txt (revision 128603) +++ libjava/headers.txt (working copy) @@ -6,6 +6,7 @@ class java/lang/Thread prepend class _Jv_JNIEnv; +prepend class _Jv_Frame; prepend #define _JV_NOT_OWNER 1 prepend #define _JV_INTERRUPTED 2 prepend _Jv_JNIEnv * _Jv_GetCurrentJNIEnv (); @@ -17,6 +18,9 @@ prepend jint _Jv_DetachCurrentThread (); prepend struct _Jv_Thread_t; prepend _Jv_Thread_t* _Jv_ThreadGetData (java::lang::Thread* thread); +prepend _Jv_Frame *_Jv_ThreadStackPeek (java::lang::Thread *thread); +prepend void _Jv_ThreadStackPush (java::lang::Thread *thread, _Jv_Frame *frame); +prepend void _Jv_ThreadStackPop (java::lang::Thread *thread); friend _Jv_JNIEnv * ::_Jv_GetCurrentJNIEnv (); friend void ::_Jv_SetCurrentJNIEnv (_Jv_JNIEnv *env); friend void ::_Jv_ThreadRun (java::lang::Thread* thread); @@ -24,6 +28,9 @@ friend java::lang::Thread* ::_Jv_AttachCurrentThread (jstring name, java::lang::ThreadGroup* group); friend java::lang::Thread* ::_Jv_AttachCurrentThreadAsDaemon (jstring name, java::lang::ThreadGroup* group); friend jint (::_Jv_DetachCurrentThread) (); +friend _Jv_Frame *::_Jv_ThreadStackPeek (java::lang::Thread *thread); +friend void ::_Jv_ThreadStackPush (java::lang::Thread *thread, _Jv_Frame *frame); +friend void ::_Jv_ThreadStackPop (java::lang::Thread *thread); class java/lang/String prepend jchar* _Jv_GetStringChars (jstring str); --- libjava/gnu/classpath/jdwp/natVMFrame.cc (revision 128603) +++ libjava/gnu/classpath/jdwp/natVMFrame.cc (working copy) @@ -181,7 +181,7 @@ getFrameDepth (_Jv_Frame *frame) { jint depth = 0; - _Jv_Frame *top_frame = (_Jv_Frame *) frame->thread->frame; + _Jv_Frame *top_frame = _Jv_ThreadStackPeek (frame->thread); jint num_frames = VMVirtualMachine::getFrameCount (frame->thread); while (frame != top_frame) --- libjava/gnu/classpath/jdwp/natVMVirtualMachine.cc (revision 128603) +++ libjava/gnu/classpath/jdwp/natVMVirtualMachine.cc (working copy) @@ -553,7 +553,7 @@ frame_list = new ::java::util::ArrayList (num_frames); - _Jv_Frame *vm_frame = reinterpret_cast<_Jv_Frame *> (thread->frame); + _Jv_Frame *vm_frame = _Jv_ThreadStackPeek (thread); // Take start frames off the top of the stack while (vm_frame != NULL && start > 0) @@ -584,7 +584,7 @@ { using namespace gnu::classpath::jdwp::exception; - _Jv_Frame *vm_frame = (_Jv_Frame *) thread->frame; + _Jv_Frame *vm_frame = _Jv_ThreadStackPeek (thread); jint depth = 0; _Jv_Frame *frame = reinterpret_cast<_Jv_Frame *> (frameID); --- libjava/java/lang/Thread.java (revision 128603) +++ libjava/java/lang/Thread.java (working copy) @@ -186,9 +186,6 @@ // 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; --- libjava/java/lang/natThread.cc (revision 128603) +++ libjava/java/lang/natThread.cc (working copy) @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -525,3 +526,25 @@ return 0; } + +_Jv_Frame * +_Jv_ThreadStackPeek (java::lang::Thread *thread) +{ + struct natThread *nt = (natThread *) thread->data; + return nt->frame; +} + +void +_Jv_ThreadStackPush (java::lang::Thread *thread, _Jv_Frame *frame) +{ + struct natThread *nt = (natThread *) thread->data; + nt->frame = frame; +} + +void +_Jv_ThreadStackPop (java::lang::Thread *thread) +{ + struct natThread *nt = (natThread *) thread->data; + _Jv_Frame *next = nt->frame->next; + nt->frame = next; +}