blob: 9981385afcbdefd0904a8bdeddb997e161aae6ee [file] [log] [blame]
//===----------- 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