| //===----------- JavaThread.h - Java thread description -------------------===// |
| // |
| // The VMKit project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef JNJVM_JAVA_THREAD_H |
| #define JNJVM_JAVA_THREAD_H |
| |
| #include <ostream> |
| |
| #include "vmkit/Cond.h" |
| #include "vmkit/Locks.h" |
| #include "vmkit/ObjectLocks.h" |
| #include "vmkit/Thread.h" |
| |
| #include "MutatorThread.h" |
| |
| #include "JavaObject.h" |
| #include "JNIReferences.h" |
| |
| namespace j3 { |
| |
| class Class; |
| class JavaMethod; |
| class JavaObject; |
| class Jnjvm; |
| |
| |
| #define BEGIN_NATIVE_EXCEPTION(level) |
| #define END_NATIVE_EXCEPTION |
| |
| |
| /* |
| * FIXME Have to find a solution for both implementations |
| */ |
| #ifdef USE_OPENJDK |
| #define BEGIN_JNI_EXCEPTION \ |
| JavaThread* th = JavaThread::get(); \ |
| word_t SP = th->getLastSP(); \ |
| th->leaveUncooperativeCode(); \ |
| vmkit::KnownFrame Frame; \ |
| th->startKnownFrame(Frame); \ |
| Frame.currentFP = vmkit::System::GetCallerAddress();\ |
| TRY { |
| #else |
| #define BEGIN_JNI_EXCEPTION \ |
| JavaThread* th = JavaThread::get(); \ |
| word_t SP = th->getLastSP(); \ |
| th->leaveUncooperativeCode(); \ |
| vmkit::KnownFrame Frame; \ |
| th->startKnownFrame(Frame); \ |
| TRY { |
| |
| #endif |
| |
| |
| #define END_JNI_EXCEPTION \ |
| } CATCH { \ |
| th->throwFromJNI(SP); \ |
| } END_CATCH; |
| |
| #define RETURN_FROM_JNI(a) {\ |
| th->endKnownFrame(); \ |
| th->enterUncooperativeCode(SP); \ |
| return (a); } \ |
| |
| #define RETURN_VOID_FROM_JNI {\ |
| th->endKnownFrame(); \ |
| th->enterUncooperativeCode(SP); \ |
| return; } \ |
| |
| /// This is used to implement park/unpark behavior. |
| /// The functionalities is the foundation for java.util.concurrency package |
| class ParkLock { |
| private: |
| vmkit::LockNormal lock; |
| vmkit::Cond cond; |
| bool permit; |
| |
| public: |
| ParkLock(); |
| ~ParkLock(); |
| |
| void park(bool isAbsolute, int64_t time, JavaThread* thread); |
| void unpark(); |
| void interrupt(); |
| }; |
| |
| /// JavaThread - This class is the internal representation of a Java thread. |
| /// It maintains thread-specific information such as its state, the current |
| /// exception if there is one, the layout of the stack, etc. |
| /// |
| class JavaThread : public vmkit::MutatorThread { |
| public: |
| |
| /// jniEnv - The JNI environment of the thread. |
| /// |
| void* jniEnv; |
| |
| /// pendingException - The Java exception currently pending. |
| /// |
| JavaObject* pendingException; |
| |
| /// javaThread - The Java representation of this thread. |
| /// |
| JavaObject* javaThread; |
| |
| /// vmThread - The VMThread object of this thread. (GNU Classpath) |
| /// sleepObject - Empty Object used to wait on for sleeping (OpenJDK) |
| /// |
| union { |
| JavaObject* vmThread; |
| JavaObject* sleepObject; |
| }; |
| |
| vmkit::LockingThread lockingThread; |
| |
| /// JNI implementation fields |
| /// |
| |
| /// currentAddedReferences - Current number of added local references. |
| /// |
| uint32_t* currentAddedReferences; |
| |
| /// localJNIRefs - List of local JNI references. |
| /// |
| JNILocalReferences* localJNIRefs; |
| |
| /// JNIlocalFrames - vector of JNI Frames |
| /// pair represents { oldAddedReferences, capacity } |
| /// |
| std::vector< std::pair<uint32_t*, int> > JNIlocalFrames; |
| |
| /// |
| /// |
| |
| // State of this Thread |
| int state; |
| |
| // Lock to implement park/unpark |
| ParkLock parkLock; |
| |
| |
| JavaObject** pushJNIRef(JavaObject* obj) { |
| llvm_gcroot(obj, 0); |
| if (!obj) return 0; |
| |
| ++(*currentAddedReferences); |
| return localJNIRefs->addJNIReference(this, obj); |
| |
| } |
| |
| /// tracer - Traces GC-objects pointed by this thread object. |
| /// |
| virtual void tracer(word_t closure); |
| |
| /// JavaThread - Empty constructor, used to get the VT. |
| /// |
| JavaThread() { |
| state = vmkit::LockingThread::StateRunning; |
| } |
| |
| /// ~JavaThread - Delete any potential malloc'ed objects used by this thread. |
| /// |
| ~JavaThread(); |
| |
| /// JavaThread - Creates a Java thread. |
| /// |
| JavaThread(vmkit::VirtualMachine* isolate); |
| |
| void initialise(JavaObject* thread, JavaObject* vmth); |
| |
| /// get - Get the current thread as a J3 object. |
| /// |
| static JavaThread* get() { |
| return (JavaThread*)vmkit::Thread::get(); |
| } |
| |
| /// getJVM - Get the Java VM in which this thread executes. |
| /// |
| Jnjvm* getJVM() const { |
| return (Jnjvm*)MyVM; |
| } |
| |
| /// currentThread - Return the current thread as a Java object. |
| /// |
| JavaObject* currentThread() const { |
| return javaThread; |
| } |
| |
| /// throwException - Throw the given exception in the current thread. |
| /// |
| void throwException(JavaObject* obj); |
| |
| /// throwPendingException - Throw a pending exception. |
| /// |
| void throwPendingException(); |
| |
| /// getJavaException - Return the pending exception. |
| /// |
| JavaObject* getJavaException() { |
| return pendingException; |
| } |
| |
| /// throwFromJNI - Throw an exception after executing JNI code. |
| /// |
| void throwFromJNI(word_t SP) { |
| // Nothing to do. The RETURN_FROM_JNI will take care of it. |
| } |
| |
| /// throwFromNative - Throw an exception after executing Native code. |
| /// |
| void throwFromNative() { |
| } |
| |
| /// throwFromJava - Throw an exception after executing Java code. |
| /// |
| void throwFromJava() { |
| throwPendingException(); |
| } |
| |
| /// startJava - Interesting, but actually does nothing :) |
| void startJava() {} |
| |
| /// endJava - Interesting, but actually does nothing :) |
| void endJava() {} |
| |
| /// startJNI - Record that we are entering native code. |
| /// |
| void startJNI(); |
| |
| void endJNI(); |
| |
| /// getCallingMethod - Get the Java method in the stack at the specified |
| /// level. |
| /// |
| JavaMethod* getCallingMethodLevel(uint32 level); |
| |
| /// getCallingClassLevel - Get the Java method in the stack at the |
| /// specified level. |
| /// |
| UserClass* getCallingClassLevel(uint32 level); |
| |
| /// getNonNullClassLoader - Get the first non-null class loader on the |
| /// stack. |
| /// |
| JavaObject* getNonNullClassLoader(); |
| |
| /// printJavaBacktrace - Prints the backtrace of this thread. Only prints |
| /// the Java methods on the stack. |
| /// |
| void printJavaBacktrace(); |
| |
| /// getJavaFrameContext - Fill the buffer with Java methods currently on |
| /// the stack. |
| /// |
| uint32 getJavaFrameContext(void** buffer); |
| |
| inline void setState(int a) { state= a; } |
| |
| private: |
| /// internalClearException - Clear the C++ and Java exceptions |
| /// currently pending. |
| /// |
| virtual void internalClearException() { |
| pendingException = NULL; |
| } |
| |
| public: |
| friend std::ostream& operator << (std::ostream&, const JavaThread&); |
| void dump() const __attribute__((noinline)); |
| |
| virtual void throwNullPointerException(word_t methodIP); |
| }; |
| |
| } // end namespace j3 |
| |
| #endif |