blob: 51d76fb63bd01fd828eea7a996a5a96bfa48984f [file] [log] [blame]
//===---------- OpenJDK.inc - OpenJDK JVM Interface Definition ------------===//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "jvm.h"
#include "JavaConstantPool.h"
#include "Reader.h"
#include "ArrayCopy.inc"
#include "ClassContext.inc"
#include "DefineClass.inc"
#include "SetProperties.inc"
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#define NYI() \
do{ assert(0 && "Not yet implemented!"); abort(); } while(0)
// Convenience wrapper for returning a JNI ref to something
#define RETURN_REF_FROM_JNI(a,type) {\
type __jni_ret_val = (type)th->pushJNIRef(a); \
RETURN_FROM_JNI(__jni_ret_val); \
}
JavaObject* internalFillInStackTrace(JavaObject* throwable) {
ArrayPtr* result = 0;
llvm_gcroot(throwable, 0);
llvm_gcroot(result, 0);
JavaThread* th = JavaThread::get();
Jnjvm* vm = th->getJVM();
assert(th);
assert(vm);
uint32 length = th->getFrameContextLength();
#ifndef ARCH_64
ClassArray* cl = vm->upcalls->ArrayOfInt;
result = (ArrayPtr*) cl->doNew(length, vm);
#else
ClassArray* cl = vm->upcalls->ArrayOfLong;
result = (ArrayPtr*) cl->doNew(length, vm);
#endif
// Don't call th->getFrameContext because it is not GC-safe.
vmkit::StackWalker Walker(th);
uint32_t i = 0;
while (intptr_t ip = *Walker) {
ArrayPtr::setElement(result, ip, i);
++i;
++Walker;
}
return result;
}
JavaObject* consStackElement(vmkit::FrameInfo* FI, intptr_t ip) {
JavaString* methodName = 0;
JavaString* className = 0;
JavaString* sourceName = 0;
JavaObject* res = 0;
llvm_gcroot(methodName, 0);
llvm_gcroot(className, 0);
llvm_gcroot(sourceName, 0);
llvm_gcroot(res, 0);
Jnjvm* vm = JavaThread::get()->getJVM();
JavaMethod* meth = (JavaMethod*)FI->Metadata;
methodName = vm->internalUTF8ToStr(meth->name);
Class* cl = meth->classDef;
className = JavaString::internalToJava(cl->name, vm);
JavaAttribute* sourceAtt = cl->lookupAttribute(JavaAttribute::sourceFileAttribute);
if (sourceAtt) {
Reader reader(sourceAtt, cl->bytes);
uint16 index = reader.readU2();
sourceName = vm->internalUTF8ToStr(cl->getConstantPool()->UTF8At(index));
}
uint16 lineNumber = meth->lookupLineNumber(FI);
UserClass* newS = vm->upcalls->newStackTraceElement;
res = newS->doNew(vm);
vm->upcalls->initStackTraceElement->invokeIntSpecial(vm, newS, res,
&className,
&methodName,
&sourceName,
lineNumber);
return res;
}
JNIEXPORT jint JNICALL
JVM_GetInterfaceVersion(void) {
return JVM_INTERFACE_VERSION;
}
jint JVM_CreateJavaVM(JavaVM **pvm, void **penv, void *args) {
NYI();
}
JNIEXPORT jint JNICALL
JVM_IHashCode(JNIEnv *env, jobject _obj) {
JavaObject * obj = _obj ? *(JavaObject**)_obj : 0;
llvm_gcroot(obj, 0);
jint hash = (obj == NULL) ? 0 : JavaObject::hashCode(obj);
return hash;
}
JNIEXPORT void JNICALL
JVM_MonitorWait(JNIEnv *env, jobject obj, jlong ms) {
BEGIN_JNI_EXCEPTION
JavaObject::wait(*(JavaObject**)obj, ms, 0);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT void JNICALL
JVM_MonitorNotify(JNIEnv *env, jobject obj) {
BEGIN_JNI_EXCEPTION
JavaObject::notify(*(JavaObject**)obj);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT void JNICALL
JVM_MonitorNotifyAll(JNIEnv *env, jobject obj) {
BEGIN_JNI_EXCEPTION
JavaObject::notifyAll(*(JavaObject**)obj);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT jobject JNICALL
JVM_Clone(JNIEnv *env, jobject obj) {
JavaObject* src = 0;
JavaObject * clone = 0;
llvm_gcroot(clone, 0);
llvm_gcroot(src, 0);
BEGIN_JNI_EXCEPTION
clone = JavaObject::clone(src = *(JavaObject**)obj);
RETURN_REF_FROM_JNI(clone, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.lang.String
*/
JNIEXPORT jstring JNICALL
JVM_InternString(JNIEnv *env, jstring _str) {
JavaString * str = *(JavaString**)_str;
const ArrayUInt16* array = 0;
JavaString * res = 0;
llvm_gcroot(str, 0);
llvm_gcroot(array, 0);
llvm_gcroot(res, 0);
BEGIN_JNI_EXCEPTION
Jnjvm* vm = JavaThread::get()->getJVM();
//vmkit::Collector::collect();
array = JavaString::strToArray(str, vm);
res = vm->constructString(array);
RETURN_REF_FROM_JNI(res, jstring);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.lang.System
*/
uint64 CurrentTimeMillis() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000LL) + (tv.tv_usec / 1000LL);
}
JNIEXPORT jlong JNICALL
JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored) {
return CurrentTimeMillis();
}
JNIEXPORT jlong JNICALL
JVM_NanoTime(JNIEnv *env, jclass ignored) {
// TODO: Impl with more accurate clock?
struct timeval tv;
gettimeofday(&tv, NULL);
jlong time = tv.tv_sec * 1000000000LL + tv.tv_usec * 1000LL;
return time;
}
JNIEXPORT void JNICALL
JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject jsrc, jint sstart,
jobject jdst, jint dstart, jint len) {
JavaObject *src = 0;
JavaObject *dst = 0;
JavaObject* cur = 0;
llvm_gcroot(src, 0);
llvm_gcroot(dst, 0);
llvm_gcroot(cur, 0);
BEGIN_JNI_EXCEPTION
src = jsrc ? *(JavaObject**)jsrc : 0;
dst = jdst ? *(JavaObject**)jdst : 0;
ArrayCopy(src, sstart, dst, dstart, len);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT jobject JNICALL
JVM_InitProperties(JNIEnv *env, jobject p) {
BEGIN_JNI_EXCEPTION
JavaObject * prop = *(JavaObject**)p;
llvm_gcroot(prop, 0);
setProperties(prop);
setCommandLineProperties(prop);
Jnjvm* vm = JavaThread::get()->getJVM();
const char * tmp = getenv("JAVA_COMPILER");
if (tmp)
setProperty(vm, prop, "java.compiler", tmp);
// Override properties to indicate java version 1.6
setProperty(vm, prop, "java.specification.version", "1.6");
setProperty(vm, prop, "java.version", "1.6");
setProperty(vm, prop, "java.runtime.version", "1.6");
// Set additional path properties
// For now, ignore JAVA_HOME. We don't want to be using a location
// other than the one we precompiled against anyway.
setProperty(vm, prop, "java.home", OpenJDKJRE);
setProperty(vm, prop, "java.ext.dirs", OpenJDKExtDirs);
RETURN_FROM_JNI(p);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.io.File
*/
JNIEXPORT void JNICALL
JVM_OnExit(void (*func)(void)) {
NYI();
}
/*
* java.lang.Runtime
*/
JNIEXPORT void JNICALL
JVM_Exit(jint code) {
vmkit::System::Exit(code);
}
JNIEXPORT void JNICALL
JVM_Halt(jint code) {
vmkit::System::Exit(code);
}
JNIEXPORT void JNICALL
JVM_GC(void) {
BEGIN_JNI_EXCEPTION
vmkit::Collector::collect();
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI;
}
/* Returns the number of real-time milliseconds that have elapsed since the
* least-recently-inspected heap object was last inspected by the garbage
* collector.
*
* For simple stop-the-world collectors this value is just the time
* since the most recent collection. For generational collectors it is the
* time since the oldest generation was most recently collected. Other
* collectors are free to return a pessimistic estimate of the elapsed time, or
* simply the time since the last full collection was performed.
*
* Note that in the presence of reference objects, a given object that is no
* longer strongly reachable may have to be inspected multiple times before it
* can be reclaimed.
*/
JNIEXPORT jlong JNICALL
JVM_MaxObjectInspectionAge(void) {
NYI();
}
JNIEXPORT void JNICALL
JVM_TraceInstructions(jboolean on) {
NYI();
}
JNIEXPORT void JNICALL
JVM_TraceMethodCalls(jboolean on) {
NYI();
}
JNIEXPORT jlong JNICALL
JVM_TotalMemory(void) {
return (jlong)vmkit::Collector::getTotalMemory();
}
JNIEXPORT jlong JNICALL
JVM_FreeMemory(void) {
return (jlong)vmkit::Collector::getFreeMemory();
}
JNIEXPORT jlong JNICALL
JVM_MaxMemory(void) {
return (jlong)vmkit::Collector::getMaxMemory();
}
JNIEXPORT jint JNICALL
JVM_ActiveProcessorCount(void) {
return vmkit::System::GetNumberOfProcessors();
}
JNIEXPORT void * JNICALL
JVM_LoadLibrary(const char *name) {
BEGIN_JNI_EXCEPTION
Jnjvm* vm = JavaThread::get()->getJVM();
void * res = (void*)vm->bootstrapLoader->loadLib(name);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT void JNICALL
JVM_UnloadLibrary(void * handle) {
NYI();
}
JNIEXPORT void * JNICALL
JVM_FindLibraryEntry(void *handle, const char *name) {
BEGIN_JNI_EXCEPTION
Jnjvm* vm = JavaThread::get()->getJVM();
void* res = (void *)vm->bootstrapLoader->loadInLib(name, handle);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jboolean JNICALL
JVM_IsSupportedJNIVersion(jint version) {
return version == JNI_VERSION_1_1 ||
version == JNI_VERSION_1_2 ||
version == JNI_VERSION_1_4 ||
version == JNI_VERSION_1_6;
}
/*
* java.lang.Float and java.lang.Double
*/
JNIEXPORT jboolean JNICALL
JVM_IsNaN(jdouble d) {
NYI();
}
/*
* java.lang.Throwable
*/
JNIEXPORT void JNICALL
JVM_FillInStackTrace(JNIEnv *env, jobject throwable) {
JavaObjectThrowable * T = 0;
llvm_gcroot(T, 0);
BEGIN_JNI_EXCEPTION
T = *(JavaObjectThrowable**)throwable;
JavaObjectThrowable::fillInStackTrace(T);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI;
}
JNIEXPORT void JNICALL
JVM_PrintStackTrace(JNIEnv *env, jobject throwable, jobject printable) {
NYI();
}
JNIEXPORT jint JNICALL
JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable) {
JavaObjectThrowable * T = 0;
llvm_gcroot(T, 0);
jint res = -1;
BEGIN_JNI_EXCEPTION
T = *(JavaObjectThrowable**)throwable;
res = JavaObjectThrowable::getStackTraceDepth(T);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jobject JNICALL
JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index) {
JavaObjectThrowable * T = 0;
JavaObject * result = 0;
JavaObject * stack = 0;
llvm_gcroot(T, 0);
llvm_gcroot(result, 0);
llvm_gcroot(stack, 0);
BEGIN_JNI_EXCEPTION
T = *(JavaObjectThrowable**)throwable;
Jnjvm* vm = JavaThread::get()->getJVM();
stack = vm->upcalls->backtrace->getInstanceObjectField(T);
verifyNull(stack);
sint32 base = JavaObjectThrowable::getStackTraceBase(T);
sint32 cur = 0;
for (sint32 i = base; i < JavaArray::getSize(stack); ++i) {
intptr_t ip = ArrayPtr::getElement((ArrayPtr*)stack, i);
vmkit::FrameInfo* FI = vm->IPToFrameInfo(ip);
if (FI->Metadata != NULL) {
if (cur == index) {
result = consStackElement(FI, ip);
break;
}
cur++;
}
}
assert(result && "No stack element found");
RETURN_REF_FROM_JNI(result, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.lang.Compiler
*/
JNIEXPORT void JNICALL
JVM_InitializeCompiler (JNIEnv *env, jclass compCls) {
NYI();
}
JNIEXPORT jboolean JNICALL
JVM_IsSilentCompiler(JNIEnv *env, jclass compCls) {
NYI();
}
JNIEXPORT jboolean JNICALL
JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls) {
// Unsupported.
return false;
}
JNIEXPORT jboolean JNICALL
JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname) {
// Unsupported.
return false;
}
JNIEXPORT jobject JNICALL
JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg) {
NYI();
}
JNIEXPORT void JNICALL
JVM_EnableCompiler(JNIEnv *env, jclass compCls) {
// Ignore.
}
JNIEXPORT void JNICALL
JVM_DisableCompiler(JNIEnv *env, jclass compCls) {
// Ignore.
}
void start(JavaThread* thread) {
JavaObject* javaThread = NULL;
JavaObject* handler = NULL;
JavaObject* exc = NULL;
llvm_gcroot(javaThread, 0);
llvm_gcroot(exc, 0);
llvm_gcroot(handler, 0);
Jnjvm* vm = thread->getJVM();
// Wait some time to let the creator initialise the fields
while (thread->javaThread == NULL || thread->sleepObject == NULL) {
vmkit::Thread::yield();
}
javaThread = thread->javaThread;
assert(javaThread && "Didn't fix the javaThread of a j3 thread");
assert(javaThread->getVirtualTable());
// Get the class for this Thread
UserClass* thClass = JavaObject::getClass(javaThread)->asClass();
assert(thClass);
assert(thClass->isResolved());
// Lookup the correct run() method to call...
const UTF8 * runName = thClass->classLoader->hashUTF8->lookupAsciiz("run");
const UTF8 * runType = thClass->classLoader->hashUTF8->lookupAsciiz("()V");
JavaMethod * meth = thClass->lookupMethodDontThrow(runName, runType, false, true, 0);
assert(meth);
// Sanity check
assert(JavaThread::get() == thread);
// Run the thread...
TRY {
meth->invokeIntSpecial(vm, thClass, javaThread);
} CATCH {
exc = thread->pendingException;
} END_CATCH;
// Sanity check
assert(JavaThread::get() == thread);
if (exc != NULL) {
thread->clearException();
TRY {
handler = vm->upcalls->getUncaughtExceptionHandler->invokeJavaObjectVirtual(vm, thClass, javaThread);
verifyNull(handler);
vm->upcalls->uncaughtException->invokeIntVirtual(vm, thClass, handler, &javaThread, &exc);
} CATCH {
fprintf(stderr, "Exception in thread \"(unknown)\": "
"Can not print stack trace.\n");
} END_CATCH;
}
// Call Thread.exit()
vm->upcalls->threadExit->invokeIntVirtual(vm, thClass, javaThread);
JavaObject::acquire(javaThread);
// Indicate that the thread is done by clearing the eetop field.
vm->upcalls->eetop->setInstanceLongField(javaThread, 0);
// Notify all waiting threads
JavaObject::notifyAll(javaThread);
JavaObject::release(javaThread);
// Remove the thread from the list.
bool isDaemon = vm->upcalls->daemon->getInstanceInt8Field(javaThread);
if (!isDaemon) {
vm->threadSystem.leave();
}
}
/*
* java.lang.Thread
*/
JNIEXPORT void JNICALL
JVM_StartThread(JNIEnv *env, jobject _thread) {
JavaObject * sleepObject = 0;
JavaObject * thread = 0;
llvm_gcroot(thread, 0);
llvm_gcroot(sleepObject, 0);
BEGIN_JNI_EXCEPTION
thread = *(JavaObject**)_thread;
assert(thread);
assert(thread->getVirtualTable());
Jnjvm* vm = JavaThread::get()->getJVM();
// Create a placeholder 'sleepObject' that
// we track in same field as Classpath's VMThread,
// used solely for sleeping.
sleepObject = vm->upcalls->OfObject->doNew(vm);
JavaThread * newTh = new JavaThread(vm);
if (!newTh) vm->outOfMemoryError();
// Set the eetop field
vm->upcalls->eetop->setInstanceLongField(thread, (long)newTh);
// If the thread is not a daemon, it is added to the list of threads to
// wait until exit.
//bool isDaemon = vm->upcalls->daemon->getInstanceInt8Field(thread);
bool isDaemon = vm->upcalls->daemon->getInstanceInt8Field(thread);
if (!isDaemon) {
vm->threadSystem.enter();
}
newTh->start((void (*)(vmkit::Thread*))start);
newTh->initialise(thread, sleepObject);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT void JNICALL
JVM_StopThread(JNIEnv *env, jobject thread, jobject exception) {
NYI();
}
JNIEXPORT jboolean JNICALL
JVM_IsThreadAlive(JNIEnv *env, jobject _thread) {
BEGIN_JNI_EXCEPTION
JavaObject * thread = *(JavaObject**)_thread;
llvm_gcroot(thread, 0);
assert(thread);
Jnjvm* vm = JavaThread::get()->getJVM();
jlong InternalThread =vm->upcalls->eetop->getInstanceLongField(thread);
RETURN_FROM_JNI(InternalThread != 0);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT void JNICALL
JVM_SuspendThread(JNIEnv *env, jobject thread) {
NYI();
}
JNIEXPORT void JNICALL
JVM_ResumeThread(JNIEnv *env, jobject thread) {
NYI();
}
JNIEXPORT void JNICALL
JVM_SetThreadPriority(JNIEnv *env, jobject thread, jint prio) {
JavaObject * T;
llvm_gcroot(T, 0);
BEGIN_JNI_EXCEPTION
Jnjvm * vm = th->getJVM();
T = *(JavaObject**)thread;
vm->upcalls->priority->setInstanceInt32Field(T, prio);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT void JNICALL
JVM_Yield(JNIEnv *env, jclass threadClass) {
vmkit::Thread::yield();
}
static struct timeval getTimeVal(long long ms) {
struct timeval ret;
long long seconds = ms / 1000LL;
ret.tv_usec = 1000LL * (ms % 1000LL);
ret.tv_sec = seconds > LONG_MAX ? LONG_MAX : seconds;
return ret;
}
JNIEXPORT void JNICALL
JVM_Sleep(JNIEnv *env, jclass threadClass, jlong _millis) {
BEGIN_JNI_EXCEPTION
Jnjvm * vm = th->getJVM();
// Check for invalid sleep time
if (_millis < 0)
th->getJVM()->illegalArgumentException("Negative sleep value");
uint64 millis = _millis;
// If Thread is interrupted, throw exception
if (th->lockingThread.interruptFlag != 0) {
th->lockingThread.interruptFlag = 0;
vm->interruptedException(NULL);
UNREACHABLE();
}
// Treat sleep(0) as yield.
if (millis == 0) {
vmkit::Thread::yield();
RETURN_VOID_FROM_JNI
}
// See the Classpath sleep() implementation for inspiration here.
// We use a dummy per-thread 'sleepObject' to wait on instead of using
// a VMThread, but otherwise same implementation.
assert(th->sleepObject && "Missing sleep object!");
uint64 now = CurrentTimeMillis();
JavaObject::acquire(th->sleepObject);
while(true) {
struct timeval tv = getTimeVal(millis);
JavaObject::timedWait(th->sleepObject, tv);
uint64 then = now;
now = CurrentTimeMillis();
uint64 timePassed = now - then;
if (timePassed >= millis) break;
millis -= timePassed;
}
JavaObject::release(th->sleepObject);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT jobject JNICALL
JVM_CurrentThread(JNIEnv *env, jclass threadClass) {
BEGIN_JNI_EXCEPTION
JavaThread* th = JavaThread::get();
RETURN_REF_FROM_JNI(th->currentThread(), jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jint JNICALL
JVM_CountStackFrames(JNIEnv *env, jobject thread) {
NYI();
}
JNIEXPORT void JNICALL
JVM_Interrupt(JNIEnv *env, jobject _thread) {
gc* obj = NULL;
JavaObject * thread = 0;
llvm_gcroot(obj, 0);
llvm_gcroot(thread, 0);
BEGIN_JNI_EXCEPTION
thread = *(JavaObject**)_thread;
Jnjvm* vm = JavaThread::get()->getJVM();
JavaField * field = vm->upcalls->eetop;
// It's possible that the thread to be interrupted has not finished
// its initialization. Wait until the initialization is done.
while (field->getInstanceLongField(thread) == 0)
vmkit::Thread::yield();
JavaThread* jth = (JavaThread*)field->getInstanceLongField(thread);
jth->lockingThread.interruptFlag = 1;
//jth->parkLock.unpark();
jth->parkLock.interrupt();
vmkit::FatLock* lock = jth->lockingThread.waitsOn;
// If the thread is blocked on a wait. We also verify nextWaiting in case
// the thread has been notified.
if (lock && jth->lockingThread.nextWaiting) {
jth->lockingThread.state = vmkit::LockingThread::StateInterrupted;
// Make sure the thread is waiting.
uint32 locked = 0;
while (true) {
locked = (lock->tryAcquire() == 0);
if (locked || (lock->getOwner() != jth && lock->getOwner() != 0))
break;
else vmkit::Thread::yield();
}
// Interrupt the thread.
jth->lockingThread.varcond.signal();
// Release the lock if we acquired it.
if (locked) lock->release(obj = lock->getAssociatedObject(), vm->lockSystem);
}
// Here we could also raise a signal for interrupting I/O
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT jboolean JNICALL
JVM_IsInterrupted(JNIEnv *env, jobject _thread, jboolean clearInterrupted) {
JavaObject * thread = 0;
llvm_gcroot(thread, 0);
bool interrupt = false;
BEGIN_JNI_EXCEPTION
thread = *(JavaObject**)_thread;
Jnjvm* vm = JavaThread::get()->getJVM();
JavaField * field = vm->upcalls->eetop;
JavaThread* jth = (JavaThread*)field->getInstanceLongField(thread);
interrupt = (jboolean)jth->lockingThread.interruptFlag;
if (clearInterrupted)
jth->lockingThread.interruptFlag = 0;
RETURN_FROM_JNI(interrupt);
END_JNI_EXCEPTION
RETURN_FROM_JNI(JNI_FALSE);
}
JNIEXPORT jboolean JNICALL
JVM_HoldsLock(JNIEnv *env, jclass threadClass, jobject obj) {
BEGIN_JNI_EXCEPTION
jboolean res = JavaObject::owner(*(JavaObject**)obj);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(JNI_FALSE);
}
JNIEXPORT void JNICALL
JVM_DumpAllStacks(JNIEnv *env, jclass unused) {
NYI();
}
JNIEXPORT jobjectArray JNICALL
JVM_GetAllThreads(JNIEnv *env, jclass dummy) {
NYI();
}
/* getStackTrace() and getAllStackTraces() method */
JNIEXPORT jobjectArray JNICALL
JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads) {
NYI();
}
/*
* java.lang.SecurityManager
*/
JNIEXPORT jclass JNICALL
JVM_CurrentLoadedClass(JNIEnv *env) {
NYI();
}
JNIEXPORT jobject JNICALL
JVM_CurrentClassLoader(JNIEnv *env) {
NYI();
}
JNIEXPORT jobjectArray JNICALL
JVM_GetClassContext(JNIEnv *env) {
ArrayObject * res = 0;
llvm_gcroot(res, 0);
BEGIN_JNI_EXCEPTION
res = GetClassContext(1);
RETURN_REF_FROM_JNI(res, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jint JNICALL
JVM_ClassDepth(JNIEnv *env, jstring name) {
NYI();
}
JNIEXPORT jint JNICALL
JVM_ClassLoaderDepth(JNIEnv *env) {
NYI();
}
/*
* java.lang.Package
*/
JNIEXPORT jstring JNICALL
JVM_GetSystemPackage(JNIEnv *env, jstring name) {
// TODO: Actually implement this
// Not doing so doesn't seem to hurt anything, yet.
return name;
}
JNIEXPORT jobjectArray JNICALL
JVM_GetSystemPackages(JNIEnv *env) {
ArrayObject * res = 0;
llvm_gcroot(res, 0);
BEGIN_JNI_EXCEPTION
Jnjvm* vm = JavaThread::get()->getJVM();
res = vm->bootstrapLoader->getBootPackages(vm);
RETURN_REF_FROM_JNI(res, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.io.ObjectInputStream
*/
JNIEXPORT jobject JNICALL
JVM_AllocateNewObject(JNIEnv *env, jobject obj, jclass currClass,
jclass initClass) {
NYI();
}
JNIEXPORT jobject JNICALL
JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass,
jint length) {
NYI();
}
JNIEXPORT jobject JNICALL
JVM_LatestUserDefinedLoader(JNIEnv *env) {
JavaObject* res = 0;
llvm_gcroot(res, 0);
BEGIN_JNI_EXCEPTION
JavaThread* th = JavaThread::get();
res = th->getNonNullClassLoader();
RETURN_REF_FROM_JNI(res, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* This function has been deprecated and should not be considered
* part of the specified JVM interface.
*/
JNIEXPORT jclass JNICALL
JVM_LoadClass0(JNIEnv *env, jobject obj, jclass currClass,
jstring currClassName) {
NYI();
}
/*
* java.lang.reflect.Array
*/
JNIEXPORT jint JNICALL
JVM_GetArrayLength(JNIEnv *env, jobject arr) {
ArrayObject* array = 0;
llvm_gcroot(array, 0);
BEGIN_JNI_EXCEPTION
array = *(ArrayObject**)arr;
jint size = ArrayObject::getSize(array);
RETURN_FROM_JNI(size);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jobject JNICALL
JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index) {
ArrayObject* array = 0;
JavaObject* element = 0;
llvm_gcroot(array, 0);
llvm_gcroot(element, 0);
BEGIN_JNI_EXCEPTION
array = *(ArrayObject**)arr;
element = ArrayObject::getElement(array, index);
RETURN_REF_FROM_JNI(element, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jvalue JNICALL
JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode) {
NYI();
}
JNIEXPORT void JNICALL
JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val) {
ArrayObject* array = 0;
JavaObject* element = 0;
llvm_gcroot(array, 0);
llvm_gcroot(element, 0);
BEGIN_JNI_EXCEPTION
verifyNull(arr);
array = *(ArrayObject**)arr;
element = val ? *(JavaObject**)val : NULL;
Jnjvm* vm = th->getJVM();
// Verify this is, in fact, an array
UserCommonClass * cl = JavaObject::getClass(array);
if (!cl || !cl->isArray())
vm->illegalArgumentException("Invalid object, expected array");
// Bounds check
if (index < 0 || index >= ArrayObject::getSize(array))
vm->indexOutOfBounds(array, index);
// Check the object is of the correct type
UserCommonClass * base = cl->asArrayClass()->baseClass();
if (element && !JavaObject::instanceOf(element, base))
vm->illegalArgumentException("Wrong object for array type");
ArrayObject::setElement(array, element, index);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
JNIEXPORT void JNICALL
JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v,
unsigned char vCode) {
NYI();
}
JNIEXPORT jobject JNICALL
JVM_NewArray(JNIEnv *env, jclass eltClass, jint length) {
JavaObject* res = 0;
JavaObject* eltClassObj = 0;
llvm_gcroot(res, 0);
llvm_gcroot(eltClassObj, 0);
BEGIN_JNI_EXCEPTION
Jnjvm* vm = th->getJVM();
if (length < 0) vm->negativeArraySizeException(length);
eltClassObj = *(JavaObject**)eltClass;
UserCommonClass* base =
UserCommonClass::resolvedImplClass(vm, eltClassObj, true);
JnjvmClassLoader* loader = base->classLoader;
const UTF8* name = base->getName();
const UTF8* arrayName = loader->constructArrayName(1, name);
if (base->isPrimitive()) {
UserClassArray *array = 0;
if (base == vm->upcalls->OfBool) {
array = vm->upcalls->ArrayOfBool;
} else if (base == vm->upcalls->OfByte) {
array = vm->upcalls->ArrayOfByte;
} else if (base == vm->upcalls->OfShort) {
array = vm->upcalls->ArrayOfShort;
} else if (base == vm->upcalls->OfChar) {
array = vm->upcalls->ArrayOfChar;
} else if (base == vm->upcalls->OfInt) {
array = vm->upcalls->ArrayOfInt;
} else if (base == vm->upcalls->OfFloat) {
array = vm->upcalls->ArrayOfFloat;
} else if (base == vm->upcalls->OfLong) {
array = vm->upcalls->ArrayOfLong;
} else if (base == vm->upcalls->OfDouble) {
array = vm->upcalls->ArrayOfDouble;
} else {
vm->illegalArgumentException("Invalid array primitive type!");
abort();
}
res = (JavaObject*)array->doNew(length, vm);
} else {
UserClassArray* array = loader->constructArray(arrayName, base);
res = (JavaObject*)array->doNew(length, vm);
}
RETURN_REF_FROM_JNI(res, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
extern JavaObject* multiCallNewIntern(UserClassArray* cl, uint32 len,
sint32* dims, Jnjvm* vm);
JNIEXPORT jobject JNICALL
JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray _dim) {
ArraySInt32* dim = 0;
JavaObjectClass * eltClassObj = 0;
JavaObject* array = 0;
llvm_gcroot(dim, 0);
llvm_gcroot(eltClassObj, 0);
llvm_gcroot(array, 0);
BEGIN_JNI_EXCEPTION
Jnjvm* vm = th->getJVM();
verifyNull(eltClass);
verifyNull(_dim);
eltClassObj = *(JavaObjectClass**)eltClass;
dim = *(ArraySInt32**)_dim;
int dim_len = ArraySInt32::getSize(dim);
if(dim_len <= 0 || dim_len > 255) {
vm->illegalArgumentException("Too many dimensions for array");
UNREACHABLE();
}
UserCommonClass* base = JavaObjectClass::getClass(eltClassObj);
JnjvmClassLoader* loader = base->classLoader;
// Build array name
vmkit::ThreadAllocator allocator;
const UTF8* arrayName;
if (base->isPrimitive()) {
char baseChar;
if (base == vm->upcalls->OfBool) {
baseChar = I_BOOL;
} else if (base == vm->upcalls->OfByte) {
baseChar = I_BYTE;
} else if (base == vm->upcalls->OfShort) {
baseChar = I_SHORT;
} else if (base == vm->upcalls->OfChar) {
baseChar = I_CHAR;
} else if (base == vm->upcalls->OfInt) {
baseChar = I_INT;
} else if (base == vm->upcalls->OfFloat) {
baseChar = I_FLOAT;
} else if (base == vm->upcalls->OfLong) {
baseChar = I_LONG;
} else if (base == vm->upcalls->OfDouble) {
baseChar = I_DOUBLE;
} else {
vm->illegalArgumentException("Invalid array primitive type!");
UNREACHABLE();
}
char* buf = (char*)allocator.Allocate(dim_len+2);
for(int i = 0; i < dim_len; ++i) buf[i] = I_TAB;
buf[dim_len] = baseChar;
buf[dim_len+1] = '\0';
arrayName = loader->asciizConstructUTF8(buf);
}
else {
const UTF8* baseName = base->getName();
arrayName = loader->constructArrayName(dim_len, baseName);
}
// Get class corresponding to array name
UserClassArray* arrayCl =
(UserClassArray*)loader->loadClassFromUserUTF8(arrayName, true, false, NULL);
// Convert dimensions array to internal representation
sint32* dims = (sint32*)allocator.Allocate(sizeof(sint32) * dim_len);
for (sint32 i = 0; i < dim_len; ++i){
dims[i] = ArraySInt32::getElement(dim, i);
}
// Invoke recursive helper to create this array
array = multiCallNewIntern(arrayCl, dim_len, dims, vm);
RETURN_REF_FROM_JNI(array, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.lang.Class and java.lang.ClassLoader
*/
/*
* Returns the class in which the code invoking the native method
* belongs.
*
* Note that in JDK 1.1, native methods did not create a frame.
* In 1.2, they do. Therefore native methods like Class.forName
* can no longer look at the current frame for the caller class.
*/
JNIEXPORT jclass JNICALL
JVM_GetCallerClass(JNIEnv *env, int n) {
BEGIN_JNI_EXCEPTION
JavaThread* th = JavaThread::get();
Jnjvm* vm = th->getJVM();
// Find the requested frame
JavaMethod * meth = th->getCallingMethodLevel(n);
// Grab the next frame up if the frame requested is Method.invoke()
// TODO: Better integrate this throughout the reflection API?
// Note that this isn't necessary in the Classpath port only because
// it doesn't enforce any language access control for reflection
if (meth == vm->upcalls->ReflectInvokeMethod)
meth = th->getCallingMethodLevel(n+1);
UserClass *cl = meth->classDef;
assert(cl);
JavaObject * const * res = cl->getClassDelegateePtr(vm);
RETURN_FROM_JNI((jclass)res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Find primitive classes
* utf: class name
*/
const struct {
const char * name;
char id;
} static PrimMap[] = {
{ "boolean", 'Z' },
{ "byte" , 'B' },
{ "char" , 'C' },
{ "short" , 'S' },
{ "int" , 'I' },
{ "long" , 'J' },
{ "float" , 'F' },
{ "double" , 'D' },
{ "void" , 'V' }
};
const static unsigned PrimMapSize = sizeof(PrimMap)/sizeof(PrimMap[0]);
JNIEXPORT jclass JNICALL
JVM_FindPrimitiveClass(JNIEnv *env, const char *utf) {
JavaObject* res = 0;
llvm_gcroot(res, 0);
BEGIN_JNI_EXCEPTION
Jnjvm* vm = JavaThread::get()->getJVM();
UserClassPrimitive * prim = 0;
for(unsigned i = 0; i < PrimMapSize; ++i) {
if(!strcmp(PrimMap[i].name, utf)) {
prim = UserClassPrimitive::byteIdToPrimitive(PrimMap[i].id, vm->upcalls);
break;
}
}
if (!prim) {
fprintf(stderr, "Unsupported primitive \"%s\"! Missing table entry?\n", utf);
}
assert(prim && "Invalid Primitive in JVM_FindPrimitiveClass");
res = (JavaObject*)prim->getClassDelegateePtr(vm);
RETURN_FROM_JNI((jclass)res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Link the class
*/
JNIEXPORT void JNICALL
JVM_ResolveClass(JNIEnv *env, jclass cls) {
JavaObjectClass * Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = *(JavaObjectClass**)cls;
UserCommonClass * C = JavaObjectClass::getClass(Cl);
assert(C && C->isClass());
C->asClass()->resolveClass();
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI
}
/*
* Find a class from a given class loader. Throw ClassNotFoundException
* or NoClassDefFoundError depending on the value of the last
* argument.
*/
JNIEXPORT jclass JNICALL
JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init,
jobject _loader, jboolean throwError) {
BEGIN_JNI_EXCEPTION
JavaObject * loader = _loader ? *(JavaObject**)_loader : 0;
llvm_gcroot(loader, 0);
jclass res;
Jnjvm* vm = JavaThread::get()->getJVM();
JnjvmClassLoader* JCL =
JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, vm);
CommonClass * Cl = JCL->loadClassFromAsciiz(name, true, throwError);
if (Cl) {
if (init && Cl->asClass())
Cl->asClass()->initialiseClass(vm);
res = (jclass)Cl->getClassDelegateePtr(vm);
}
else {
vm->classNotFoundException(vm->asciizToStr(name));
res = NULL;
}
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jclass JNICALL
JVM_FindClassFromBootLoader(JNIEnv *env, const char *name) {
BEGIN_JNI_EXCEPTION
jclass res = 0;
Jnjvm* vm = JavaThread::get()->getJVM();
JnjvmClassLoader* JCL = vm->bootstrapLoader;
CommonClass * Cl = JCL->loadClassFromAsciiz(name, true, false);
if (Cl) {
res = (jclass)Cl->getClassDelegateePtr(vm);
}
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Find a class from a given class.
*/
JNIEXPORT jclass JNICALL
JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init,
jclass from) {
NYI();
}
/* Find a loaded class cached by the VM */
JNIEXPORT jclass JNICALL
JVM_FindLoadedClass(JNIEnv *env, jobject _loader, jstring name) {
JavaObject * loader = 0;
JavaString * str = 0;
llvm_gcroot(loader, 0);
llvm_gcroot(str, 0);
BEGIN_JNI_EXCEPTION
Jnjvm* vm = JavaThread::get()->getJVM();
JnjvmClassLoader* JCL = NULL;
loader = *(JavaObject**)_loader;
str = *(JavaString**)name;
CommonClass * Cl = 0;
JCL = JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, vm);
assert(JCL && "JnVMClassloader is null");
Cl = JCL->lookupClassFromJavaString(str);
jclass res = Cl ? (jclass)Cl->getClassDelegateePtr(vm) : 0;
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/* Define a class */
JNIEXPORT jclass JNICALL
JVM_DefineClass(JNIEnv *env, const char *name, jobject _loader, const jbyte *buf,
jsize len, jobject pd) {
JavaObject * loader = 0;
llvm_gcroot(loader, 0);
BEGIN_JNI_EXCEPTION
loader = _loader ? *(JavaObject**)_loader : 0;
jclass res = 0;
Jnjvm* vm = JavaThread::get()->getJVM();
JnjvmClassLoader* JCL = NULL;
JCL = JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, vm);
const UTF8* utfName = JCL->asciizConstructUTF8(name);
UserClass* cl = defineClass(JCL, utfName, (const char*)buf, len);
res = (jclass)cl->getClassDelegateePtr(vm, pd ? *(JavaObject**)pd : 0);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/* Define a class with a source (added in JDK1.5) */
JNIEXPORT jclass JNICALL
JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
const jbyte *buf, jsize len, jobject pd,
const char *source) {
// Discard source for now
return JVM_DefineClass(env, name, loader, buf, len, pd);
}
/* Define a class with a source with conditional verification (added HSX 14)
* -Xverify:all will verify anyway, -Xverify:none will not verify,
* -Xverify:remote (default) will obey this conditional
* i.e. true = should_verify_class
*/
JNIEXPORT jclass JNICALL
JVM_DefineClassWithSourceCond(JNIEnv *env, const char *name, jobject loader,
const jbyte *buf, jsize len, jobject pd,
const char *source, jboolean verify) {
// Discard source and verification
return JVM_DefineClass(env, name, loader, buf, len, pd);
}
/*
* Reflection support functions
*/
JNIEXPORT jstring JNICALL
JVM_GetClassName(JNIEnv *env, jclass cls) {
JavaObject * result = 0;
JavaObject * Cl = 0;
llvm_gcroot(result, 0);
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = *(JavaObject**)cls;
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
const UTF8* iname = cl->getName();
result = JavaString::internalToJava(iname, vm);
RETURN_REF_FROM_JNI(result, jstring);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jobjectArray JNICALL
JVM_GetClassInterfaces(JNIEnv *env, jclass cls) {
JavaObjectClass* cl = 0;
ArrayObject* ret = 0;
llvm_gcroot(ret, 0);
llvm_gcroot(cl, 0);
BEGIN_JNI_EXCEPTION
cl = *(JavaObjectClass**)cls;
ret = JavaObjectClass::getInterfaces(cl);
RETURN_REF_FROM_JNI(ret, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jobject JNICALL
JVM_GetClassLoader(JNIEnv *env, jclass cls) {
JavaObject * Cl = *(JavaObject**)cls;
JavaObject * res = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(res, 0);
BEGIN_JNI_EXCEPTION
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
res = cl->classLoader->getJavaClassLoader();
RETURN_REF_FROM_JNI(res, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jboolean JNICALL
JVM_IsInterface(JNIEnv *env, jclass cls) {
jboolean res = JNI_FALSE;
JavaObject * Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = *(JavaObject**)cls;
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
res = cl->isInterface();
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(JNI_FALSE);
}
JNIEXPORT jobjectArray JNICALL
JVM_GetClassSigners(JNIEnv *env, jclass cls) {
NYI();
}
JNIEXPORT void JNICALL
JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers) {
// Let them 'set' signers, since we don't implement this yet and
// don't allow them to 'get' the value back (above).
//NYI();
}
JNIEXPORT jobject JNICALL
JVM_GetProtectionDomain(JNIEnv *env, jclass cls) {
JavaObjectClass * JOC = 0;
JavaObject * pd = 0;
llvm_gcroot(JOC, 0);
llvm_gcroot(pd, 0);
BEGIN_JNI_EXCEPTION
JOC = *(JavaObjectClass**)cls;
pd = JavaObjectClass::getProtectionDomain(JOC);
RETURN_REF_FROM_JNI(pd, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT void JNICALL
JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain) {
NYI();
}
JNIEXPORT jboolean JNICALL
JVM_IsArrayClass(JNIEnv *env, jclass cls) {
JavaObject * Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = *(JavaObject**)cls;
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
jboolean ret = cl->isArray();
RETURN_FROM_JNI(ret);
END_JNI_EXCEPTION
RETURN_FROM_JNI(JNI_FALSE);
}
JNIEXPORT jboolean JNICALL
JVM_IsPrimitiveClass(JNIEnv *env, jclass cls) {
JavaObject * Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = *(JavaObject**)cls;
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
jboolean ret = cl->isPrimitive();
RETURN_FROM_JNI(ret);
END_JNI_EXCEPTION
RETURN_FROM_JNI(JNI_FALSE);
}
JNIEXPORT jclass JNICALL
JVM_GetComponentType(JNIEnv *env, jclass cls) {
JavaObject * Cl = 0;
JavaObject* res = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(res, 0);
BEGIN_JNI_EXCEPTION
Cl = *(JavaObject**)cls;
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
if (cl->isArray()) {
UserCommonClass* bc = cl->asArrayClass()->baseClass();
res = (JavaObject*)bc->getClassDelegateePtr(vm);
} else {
res = 0;
}
RETURN_FROM_JNI((jclass)res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jint JNICALL
JVM_GetClassModifiers(JNIEnv *env, jclass cls) {
JavaObjectClass * Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = *(JavaObjectClass**)cls;
jint res = JavaObjectClass::getModifiers(Cl);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jobjectArray JNICALL
JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass) {
JavaObjectClass* cl = 0;
ArrayObject* ret = 0;
llvm_gcroot(ret, 0);
llvm_gcroot(cl, 0);
BEGIN_JNI_EXCEPTION
// TODO: Verify boolean parameter here, assuming should default to true.
cl = *(JavaObjectClass**)ofClass;
ret = JavaObjectClass::getDeclaredClasses(cl, false);
RETURN_REF_FROM_JNI(ret, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jclass JNICALL
JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass) {
JavaObject* ret = 0;
llvm_gcroot(ret, 0);
BEGIN_JNI_EXCEPTION
ret = JavaObjectClass::getDeclaringClass(*(JavaObjectClass**)ofClass);
RETURN_REF_FROM_JNI(ret, jclass);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/* Generics support (JDK 1.5) */
JNIEXPORT jstring JNICALL
JVM_GetClassSignature(JNIEnv *env, jclass cls) {
JavaObjectClass * Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = cls ? *(JavaObjectClass**)cls : 0;
verifyNull(Cl);
Class* cl = JavaObjectClass::getClass(Cl)->asClass();
if (!cl) return 0;
JavaString** sig = JavaObjectClass::getSignature(cl);
RETURN_FROM_JNI((jstring)sig);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/* Annotations support (JDK 1.5) */
JNIEXPORT jbyteArray JNICALL
JVM_GetClassAnnotations(JNIEnv *env, jclass cls) {
ArraySInt8 * ret = 0;
JavaObjectClass* Cl = 0;
llvm_gcroot(ret, 0);
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = cls ? *(JavaObjectClass**)cls : 0;
verifyNull(Cl);
Class * cl = JavaObjectClass::getClass(Cl)->asClass();
if (cl)
ret = JavaObjectClass::getAnnotations(cl);
RETURN_REF_FROM_JNI(ret, jbyteArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* New (JDK 1.4) reflection implementation
*/
JNIEXPORT jobjectArray JNICALL
JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly) {
JavaObjectClass* cl = 0;
ArrayObject* ret = 0;
llvm_gcroot(ret, 0);
llvm_gcroot(cl, 0);
BEGIN_JNI_EXCEPTION
cl = *(JavaObjectClass**)ofClass;
ret = JavaObjectClass::getDeclaredMethods(cl, publicOnly);
RETURN_REF_FROM_JNI(ret, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jobjectArray JNICALL
JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly) {
JavaObjectClass* cl = 0;
ArrayObject* ret = 0;
llvm_gcroot(ret, 0);
llvm_gcroot(cl, 0);
BEGIN_JNI_EXCEPTION
cl = *(JavaObjectClass**)ofClass;
ret = JavaObjectClass::getDeclaredFields(cl, publicOnly);
RETURN_REF_FROM_JNI(ret, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jobjectArray JNICALL
JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly) {
JavaObjectClass* cl = 0;
ArrayObject* ret = 0;
llvm_gcroot(ret, 0);
llvm_gcroot(cl, 0);
BEGIN_JNI_EXCEPTION
cl = *(JavaObjectClass**)ofClass;
ret = JavaObjectClass::getDeclaredConstructors(cl, publicOnly);
RETURN_REF_FROM_JNI(ret, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/* Differs from JVM_GetClassModifiers in treatment of inner classes.
This returns the access flags for the class as specified in the
class file rather than searching the InnerClasses attribute (if
present) to find the source-level access flags. Only the values of
the low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
valid. */
JNIEXPORT jint JNICALL
JVM_GetClassAccessFlags(JNIEnv *env, jclass cls) {
JavaObject * Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = *(JavaObject**)cls;
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
assert(cl->isClass());
// TODO: Verify this is doing what this function is supposed to do
// (In particular regarding the comment block above)
jint res = cl->asClass()->access;
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/* The following two reflection routines are still needed due to startup time issues */
/*
* java.lang.reflect.Method
*/
JNIEXPORT jobject JNICALL
JVM_InvokeMethod(JNIEnv *env, jobject _m, jobject _obj, jobjectArray args0) {
JavaObject * ret = 0;
JavaObjectMethod * m = 0;
llvm_gcroot(ret, 0);
llvm_gcroot(m, 0);
BEGIN_JNI_EXCEPTION
m = *(JavaObjectMethod**)_m;
ret = proceedMethod(
m,
_obj ? *(JavaObject**)_obj : 0,
args0? *(ArrayObject**)args0 : 0,
JavaObjectMethod::getClass(m)->getDelegatee(),
0 /* unused */ );
RETURN_REF_FROM_JNI(ret, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.lang.reflect.Constructor
*/
JNIEXPORT jobject JNICALL
JVM_NewInstanceFromConstructor(JNIEnv *env, jobject _c, jobjectArray args0) {
JavaObject * ret = 0;
JavaObjectConstructor * c = 0;
llvm_gcroot(ret, 0);
llvm_gcroot(c, 0);
BEGIN_JNI_EXCEPTION
c = *(JavaObjectConstructor**)_c;
ret = proceedConstructor(
c,
args0? *(ArrayObject**)args0 : 0,
JavaObjectConstructor::getClass(c)->getDelegatee(),
0 /* unused */ );
RETURN_REF_FROM_JNI(ret, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Constant pool access; currently used to implement reflective access to annotations (JDK 1.5
*/
JNIEXPORT jobject JNICALL
JVM_GetClassConstantPool(JNIEnv *env, jclass cls) {
JavaObjectClass * Cl = 0;
JavaObject* CP = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(CP, 0);
BEGIN_JNI_EXCEPTION
Cl = cls ? *(JavaObjectClass**)cls : 0;
verifyNull(Cl);
Jnjvm* vm = th->getJVM();
CP = vm->upcalls->constantPoolClass->doNew(vm);
// Set the constantPoolOop field to point to the Class this
// ConstantPool object is supposed to represent the constant pool for.
vm->upcalls->constantPoolOop->setInstanceObjectField(CP, Cl);
RETURN_REF_FROM_JNI(CP, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jint JNICALL JVM_ConstantPoolGetSize
(JNIEnv *env, jobject unused, jobject jcpool) {
NYI();
}
JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAtIfLoaded
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAtIfLoaded
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAtIfLoaded
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetMemberRefInfoAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jint JNICALL JVM_ConstantPoolGetIntAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
JavaObjectClass* Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = jcpool ? *(JavaObjectClass**)jcpool : 0;
verifyNull(Cl);
Class* cl = JavaObjectClass::getClass(Cl)->asClass();
assert(cl);
sint32 ret = cl->getConstantPool()->IntegerAt(index);
RETURN_FROM_JNI(ret);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jlong JNICALL JVM_ConstantPoolGetLongAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jfloat JNICALL JVM_ConstantPoolGetFloatAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jdouble JNICALL JVM_ConstantPoolGetDoubleAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jstring JNICALL JVM_ConstantPoolGetStringAt
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
NYI();
}
JNIEXPORT jstring JNICALL JVM_ConstantPoolGetUTF8At
(JNIEnv *env, jobject unused, jobject jcpool, jint index) {
JavaObjectClass* Cl = 0;
llvm_gcroot(Cl, 0);
BEGIN_JNI_EXCEPTION
Cl = jcpool ? *(JavaObjectClass**)jcpool : 0;
verifyNull(Cl);
Class* cl = JavaObjectClass::getClass(Cl)->asClass();
assert(cl);
const UTF8* utf = cl->getConstantPool()->UTF8At(index);
assert(utf);
jstring str = (jstring)cl->classLoader->UTF8ToStr(utf);
RETURN_FROM_JNI(str);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.security.*
*/
JNIEXPORT jobject JNICALL
JVM_DoPrivileged(JNIEnv *env, jclass cls,
jobject action, jobject context, jboolean wrapException) {
JavaObject * obj = 0;
JavaObject * res = 0;
llvm_gcroot(obj, 0);
llvm_gcroot(res, 0);
BEGIN_JNI_EXCEPTION
verifyNull(action);
obj = *(JavaObject**)action;
Jnjvm* vm = th->getJVM();
// For now, we don't do anything special,
// just call the requested 'run()' method...
UserClass * cl = JavaObject::getClass(obj)->asClass();
const UTF8 * runName = cl->classLoader->hashUTF8->lookupAsciiz("run");
const UTF8 * runType = cl->classLoader->hashUTF8->lookupAsciiz("()Ljava/lang/Object;");
assert(cl); assert(runName); assert(runType);
JavaMethod * meth = cl->lookupMethodDontThrow(runName, runType, false, true, 0);
assert(meth);
res = meth->invokeJavaObjectVirtual(vm, cl, obj);
RETURN_REF_FROM_JNI(res, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT jobject JNICALL
JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls) {
// No AccessControlContext supported yet
return NULL;
}
JNIEXPORT jobject JNICALL
JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls) {
// No AccessControlContext supported yet
return NULL;
}
/*
* Signal support, used to implement the shutdown sequence. Every VM must
* support JVM_SIGINT and JVM_SIGTERM, raising the former for user interrupts
* (^C) and the latter for external termination (kill, system shutdown, etc.).
* Other platform-dependent signal values may also be supported.
*/
JNIEXPORT void * JNICALL
JVM_RegisterSignal(jint sig, void *handler) {
// Don't let signals be registered, yet.
return (void*)-1;
}
JNIEXPORT jboolean JNICALL
JVM_RaiseSignal(jint sig) {
NYI();
}
JNIEXPORT jint JNICALL
JVM_FindSignal(const char *name) {
// Map Signal name to integer...
static struct {
const char * name;
int num;
} SignalMap[] =
{
{ "TERM", SIGTERM },
{ "HUP", SIGHUP },
{ "INT", SIGINT }
};
static uint32 signal_count = sizeof(SignalMap)/sizeof(SignalMap[0]);
BEGIN_JNI_EXCEPTION
for(uint32 i = 0; i < signal_count; ++i) {
if (!strcmp(name, SignalMap[i].name))
RETURN_FROM_JNI(SignalMap[i].num);
}
fprintf(stderr, "Unknown Signal \"%s\", missing entry in table?\n", name);
UNIMPLEMENTED();
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Retrieve the assertion directives for the specified class.
*/
JNIEXPORT jboolean JNICALL
JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls) {
// TODO: Actually implement?
return JNI_FALSE;
}
/*
* Retrieve the assertion directives from the VM.
*/
JNIEXPORT jobject JNICALL
JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused) {
JavaObject* asdObj = 0;
JavaObject* emptyStringArr = 0;
llvm_gcroot(asdObj, 0);
llvm_gcroot(emptyStringArr, 0);
BEGIN_JNI_EXCEPTION
Jnjvm* vm = th->getJVM();
UserClass * asdCl = vm->upcalls->assertionStatusDirectivesClass;
asdObj = asdCl->doNew(vm);
emptyStringArr = vm->upcalls->ArrayOfString->doNew(0, vm);
const UTF8 * classesName = asdCl->classLoader->hashUTF8->lookupAsciiz("classes");
const UTF8 * packagesName = asdCl->classLoader->hashUTF8->lookupAsciiz("packages");
const UTF8 * stringArrType = asdCl->classLoader->hashUTF8->lookupAsciiz("[Ljava/lang/String;");
JavaField* classes = asdCl->lookupFieldDontThrow(classesName, stringArrType, false, true, 0);
JavaField* packages = asdCl->lookupFieldDontThrow(packagesName, stringArrType, false, true, 0);
assert(classes);
assert(packages);
classes->setInstanceObjectField(asdObj, emptyStringArr);
packages->setInstanceObjectField(asdObj, emptyStringArr);
RETURN_REF_FROM_JNI(asdObj, jobject);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* java.util.concurrent.AtomicLong
*/
JNIEXPORT jboolean JNICALL
JVM_SupportsCX8(void) {
return JNI_FALSE;
}
/*************************************************************************
PART 2: Support for the Verifier and Class File Format Checker
************************************************************************/
/*
* Return the class name in UTF format. The result is valid
* until JVM_ReleaseUTf is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetClassNameUTF(JNIEnv *env, jclass cb) {
NYI();
}
/*
* Returns the constant pool types in the buffer provided by "types."
*/
JNIEXPORT void JNICALL
JVM_GetClassCPTypes(JNIEnv *env, jclass cb, unsigned char *types) {
NYI();
}
/*
* Returns the number of Constant Pool entries.
*/
JNIEXPORT jint JNICALL
JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cb) {
NYI();
}
/*
* Returns the number of *declared* fields or methods.
*/
JNIEXPORT jint JNICALL
JVM_GetClassFieldsCount(JNIEnv *env, jclass cb) {
NYI();
}
JNIEXPORT jint JNICALL
JVM_GetClassMethodsCount(JNIEnv *env, jclass cb) {
NYI();
}
/*
* Returns the CP indexes of exceptions raised by a given method.
* Places the result in the given buffer.
*
* The method is identified by method_index.
*/
JNIEXPORT void JNICALL
JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cb, jint method_index,
unsigned short *exceptions) {
NYI();
}
/*
* Returns the number of exceptions raised by a given method.
* The method is identified by method_index.
*/
JNIEXPORT jint JNICALL
JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cb, jint method_index) {
NYI();
}
/*
* Returns the byte code sequence of a given method.
* Places the result in the given buffer.
*
* The method is identified by method_index.
*/
JNIEXPORT void JNICALL
JVM_GetMethodIxByteCode(JNIEnv *env, jclass cb, jint method_index,
unsigned char *code) {
NYI();
}
/*
* Returns the length of the byte code sequence of a given method.
* The method is identified by method_index.
*/
JNIEXPORT jint JNICALL
JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cb, jint method_index) {
NYI();
}
/*
* Returns the exception table entry at entry_index of a given method.
* Places the result in the given buffer.
*
* The method is identified by method_index.
*/
JNIEXPORT void JNICALL
JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cb, jint method_index,
jint entry_index,
JVM_ExceptionTableEntryType *entry) {
NYI();
}
/*
* Returns the length of the exception table of a given method.
* The method is identified by method_index.
*/
JNIEXPORT jint JNICALL
JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cb, int index) {
NYI();
}
/*
* Returns the modifiers of a given field.
* The field is identified by field_index.
*/
JNIEXPORT jint JNICALL
JVM_GetFieldIxModifiers(JNIEnv *env, jclass cb, int index) {
NYI();
}
/*
* Returns the modifiers of a given method.
* The method is identified by method_index.
*/
JNIEXPORT jint JNICALL
JVM_GetMethodIxModifiers(JNIEnv *env, jclass cb, int index) {
NYI();
}
/*
* Returns the number of local variables of a given method.
* The method is identified by method_index.
*/
JNIEXPORT jint JNICALL
JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cb, int index) {
NYI();
}
/*
* Returns the number of arguments (including this pointer) of a given method.
* The method is identified by method_index.
*/
JNIEXPORT jint JNICALL
JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cb, int index) {
NYI();
}
/*
* Returns the maximum amount of stack (in words) used by a given method.
* The method is identified by method_index.
*/
JNIEXPORT jint JNICALL
JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index) {
NYI();
}
/*
* Is a given method a constructor.
* The method is identified by method_index.
*/
JNIEXPORT jboolean JNICALL
JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index) {
NYI();
}
/*
* Returns the name of a given method in UTF format.
* The result remains valid until JVM_ReleaseUTF is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the signature of a given method in UTF format.
* The result remains valid until JVM_ReleaseUTF is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the name of the field refered to at a given constant pool
* index.
*
* The result is in UTF format and remains valid until JVM_ReleaseUTF
* is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the name of the method refered to at a given constant pool
* index.
*
* The result is in UTF format and remains valid until JVM_ReleaseUTF
* is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the signature of the method refered to at a given constant pool
* index.
*
* The result is in UTF format and remains valid until JVM_ReleaseUTF
* is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the signature of the field refered to at a given constant pool
* index.
*
* The result is in UTF format and remains valid until JVM_ReleaseUTF
* is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the class name refered to at a given constant pool index.
*
* The result is in UTF format and remains valid until JVM_ReleaseUTF
* is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetCPClassNameUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the class name refered to at a given constant pool index.
*
* The constant pool entry must refer to a CONSTANT_Fieldref.
*
* The result is in UTF format and remains valid until JVM_ReleaseUTF
* is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the class name refered to at a given constant pool index.
*
* The constant pool entry must refer to CONSTANT_Methodref or
* CONSTANT_InterfaceMethodref.
*
* The result is in UTF format and remains valid until JVM_ReleaseUTF
* is called.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*/
JNIEXPORT const char * JNICALL
JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cb, jint index) {
NYI();
}
/*
* Returns the modifiers of a field in calledClass. The field is
* referred to in class cb at constant pool entry index.
*
* The caller must treat the string as a constant and not modify it
* in any way.
*
* Returns -1 if the field does not exist in calledClass.
*/
JNIEXPORT jint JNICALL
JVM_GetCPFieldModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass) {
NYI();
}
/*
* Returns the modifiers of a method in calledClass. The method is
* referred to in class cb at constant pool entry index.
*
* Returns -1 if the method does not exist in calledClass.
*/
JNIEXPORT jint JNICALL
JVM_GetCPMethodModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass) {
NYI();
}
/*
* Releases the UTF string obtained from the VM.
*/
JNIEXPORT void JNICALL
JVM_ReleaseUTF(const char *utf) {
NYI();
}
/*
* Compare if two classes are in the same package.
*/
JNIEXPORT jboolean JNICALL
JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2) {
NYI();
}
/* Write a string into the given buffer, in the platform's local encoding,
* that describes the most recent system-level error to occur in this thread.
* Return the length of the string or zero if no error occurred.
*/
JNIEXPORT jint JNICALL
JVM_GetLastErrorString(char *buf, int len) {
BEGIN_JNI_EXCEPTION
char * err = strerror_r(errno, buf, len);
if (err != buf)
strncpy(buf, err, len);
jint len = strlen(buf);
RETURN_FROM_JNI(len);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Convert a pathname into native format. This function does syntactic
* cleanup, such as removing redundant separator characters. It modifies
* the given pathname string in place.
*/
JNIEXPORT char * JNICALL
JVM_NativePath(char * path) {
// TODO: Implement me?
return path;
}
/*
* Open a file descriptor. This function returns a negative error code
* on error, and a non-negative integer that is the file descriptor on
* success.
*/
JNIEXPORT jint JNICALL
JVM_Open(const char *fname, jint flags, jint mode) {
// Special flag the JVM uses
// means to delete the file after opening.
static const int O_DELETE = 0x10000;
BEGIN_JNI_EXCEPTION
int result = open(fname, flags & ~O_DELETE, mode);
// Map EEXIST to special JVM_EEXIST, otherwise all errors are -1
if (result < 0) {
if (errno == EEXIST) {
RETURN_FROM_JNI(JVM_EEXIST);
} else {
RETURN_FROM_JNI(-1);
}
}
// Handle O_DELETE flag, if specified
if (flags & O_DELETE)
unlink(fname);
RETURN_FROM_JNI(result);
END_JNI_EXCEPTION
RETURN_FROM_JNI(-1);
}
/*
* Close a file descriptor. This function returns -1 on error, and 0
* on success.
*
* fd the file descriptor to close.
*/
JNIEXPORT jint JNICALL
JVM_Close(jint fd) {
BEGIN_JNI_EXCEPTION
jint res = close(fd);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(-1);
}
/*
* Read data from a file decriptor into a char array.
*
* fd the file descriptor to read from.
* buf the buffer where to put the read data.
* nbytes the number of bytes to read.
*
* This function returns -1 on error, and 0 on success.
* (WDTZ: If I return '0' on success, things die. Returning
* number of bytes read instead for now)
*/
JNIEXPORT jint JNICALL
JVM_Read(jint fd, char *buf, jint nbytes) {
BEGIN_JNI_EXCEPTION
vmkit::Thread* th = vmkit::Thread::get();
jint res = 0;
//if (fd)
// res = read(fd, buf, nbytes);
//else {
th->enterUncooperativeCode();
res = read(fd, buf, nbytes);
th->leaveUncooperativeCode();
//}
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(-1);
}
/*
* Write data from a char array to a file decriptor.
*
* fd the file descriptor to read from.
* buf the buffer from which to fetch the data.
* nbytes the number of bytes to write.
*
* This function returns -1 on error, and 0 on success.
*/
JNIEXPORT jint JNICALL
JVM_Write(jint fd, char *buf, jint nbytes) {
BEGIN_JNI_EXCEPTION
jint res = write(fd, buf, nbytes);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(-1);
}
/*
* Returns the number of bytes available for reading from a given file
* descriptor
*/
JNIEXPORT jint JNICALL
JVM_Available(jint fd, jlong *pbytes) {
// From JamVM's JVM_Available implementation, GPLv2
BEGIN_JNI_EXCEPTION
struct stat sb;
if(fstat(fd, &sb) == -1)
RETURN_FROM_JNI(0);
switch(sb.st_mode & S_IFMT) {
case S_IFCHR:
case S_IFIFO:
case S_IFSOCK: {
int n;
if(ioctl(fd, TIOCINQ, &n) == -1)
RETURN_FROM_JNI(0);
*pbytes = n;
RETURN_FROM_JNI(1);
}
default: {
off64_t cur, end;
if((cur = lseek64(fd, 0, SEEK_CUR)) == -1)
RETURN_FROM_JNI(0);
if((end = lseek64(fd, 0, SEEK_END)) == -1)
RETURN_FROM_JNI(0);
if(lseek64(fd, cur, SEEK_SET) == -1)
RETURN_FROM_JNI(0);
*pbytes = end - cur;
RETURN_FROM_JNI(1);
}
}
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Move the file descriptor pointer from whence by offset.
*
* fd the file descriptor to move.
* offset the number of bytes to move it by.
* whence the start from where to move it.
*
* This function returns the resulting pointer location.
*/
JNIEXPORT jlong JNICALL
JVM_Lseek(jint fd, jlong offset, jint whence) {
BEGIN_JNI_EXCEPTION
jlong res = lseek64(fd, offset, whence);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Set the length of the file associated with the given descriptor to the given
* length. If the new length is longer than the current length then the file
* is extended; the contents of the extended portion are not defined. The
* value of the file pointer is undefined after this procedure returns.
*/
JNIEXPORT jint JNICALL
JVM_SetLength(jint fd, jlong length) {
int res = ftruncate64(fd, length);
return res != -1;
}
/*
* Synchronize the file descriptor's in memory state with that of the
* physical device. Return of -1 is an error, 0 is OK.
*/
JNIEXPORT jint JNICALL
JVM_Sync(jint fd) {
return fsync(fd);
}
/*
* Networking library support
*/
JNIEXPORT jint JNICALL
JVM_InitializeSocketLibrary(void) {
// Nothing to do here.
return 0;
}
JNIEXPORT jint JNICALL
JVM_Socket(jint domain, jint type, jint protocol) {
return socket(domain, type, protocol);
}
JNIEXPORT jint JNICALL
JVM_SocketClose(jint fd) {
return close(fd);
}
JNIEXPORT jint JNICALL
JVM_SocketShutdown(jint fd, jint howto) {
// Nothing to do here.
return true;
}
JNIEXPORT jint JNICALL
JVM_Recv(jint fd, char *buf, jint nBytes, jint flags) {
return recv(fd, buf, nBytes, flags);
}
JNIEXPORT jint JNICALL
JVM_Send(jint fd, char *buf, jint nBytes, jint flags) {
return send(fd, buf, nBytes, flags);
}
JNIEXPORT jint JNICALL
JVM_Timeout(int fd, long timeout) {
NYI();
}
JNIEXPORT jint JNICALL
JVM_Listen(jint fd, jint count) {
return listen(fd, count);
}
JNIEXPORT jint JNICALL
JVM_Connect(jint fd, struct sockaddr *him, jint len) {
return connect(fd, him, len);
}
JNIEXPORT jint JNICALL
JVM_Bind(jint fd, struct sockaddr *him, jint len) {
return bind(fd, him, len);
}
JNIEXPORT jint JNICALL
JVM_Accept(jint fd, struct sockaddr *him, jint *len) {
BEGIN_JNI_EXCEPTION
vmkit::Thread* th = vmkit::Thread::get();
th->enterUncooperativeCode();
jint res = accept(fd, him, (socklen_t*)len);
th->leaveUncooperativeCode();
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(-1);
}
JNIEXPORT jint JNICALL
JVM_RecvFrom(jint fd, char *buf, int nBytes,
int flags, struct sockaddr *from, int *fromlen) {
BEGIN_JNI_EXCEPTION
vmkit::Thread* th = vmkit::Thread::get();
th->enterUncooperativeCode();
jint res = recvfrom(fd, buf, nBytes, flags, from, (socklen_t*)fromlen);
th->leaveUncooperativeCode();
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(-1);
}
JNIEXPORT jint JNICALL
JVM_SendTo(jint fd, char *buf, int len,
int flags, struct sockaddr *to, int tolen) {
return sendto(fd, buf, len, flags, to, (socklen_t)tolen);
}
JNIEXPORT jint JNICALL
JVM_SocketAvailable(jint fd, jint *result) {
BEGIN_JNI_EXCEPTION
if(ioctl(fd, TIOCINQ, result) == -1)
RETURN_FROM_JNI(JNI_FALSE);
RETURN_FROM_JNI(JNI_TRUE);
END_JNI_EXCEPTION
RETURN_FROM_JNI(JNI_FALSE);
}
JNIEXPORT jint JNICALL
JVM_GetSockName(jint fd, struct sockaddr *him, int *len) {
return getsockname(fd, him, (socklen_t*)len);
}
JNIEXPORT jint JNICALL
JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen) {
return getsockopt(fd, level, optname, optval, (socklen_t*)optlen);
}
JNIEXPORT jint JNICALL
JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen) {
return setsockopt(fd, level, optname, optval, optlen);
}
/*
* These routines are only reentrant on Windows
*/
JNIEXPORT int JNICALL
JVM_GetHostName(char* name, int namelen) {
return gethostname(name, namelen);
}
/*
* The standard printing functions supported by the Java VM. (Should they
* be renamed to JVM_* in the future?
*/
/*
* BE CAREFUL! The following functions do not implement the
* full feature set of standard C printf formats.
*/
int
jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args) {
return vsnprintf(str, count, fmt, args);
}
int
jio_snprintf(char *str, size_t count, const char *fmt, ...) {
va_list args;
int res;
va_start(args, fmt);
res = vsnprintf(str, count, fmt, args);
va_end(args);
return res;
}
int
jio_fprintf(FILE *, const char *fmt, ...) {
NYI();
}
int
jio_vfprintf(FILE *, const char *fmt, va_list args) {
NYI();
}
JNIEXPORT void * JNICALL
JVM_RawMonitorCreate(void) {
BEGIN_JNI_EXCEPTION
pthread_mutex_t* L = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(L, NULL);
RETURN_FROM_JNI(L);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT void JNICALL
JVM_RawMonitorDestroy(void *mon) {
BEGIN_JNI_EXCEPTION
pthread_mutex_t* L = (pthread_mutex_t*)mon;
pthread_mutex_destroy(L);
free(L);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI;
}
JNIEXPORT jint JNICALL
JVM_RawMonitorEnter(void *mon) {
BEGIN_JNI_EXCEPTION
pthread_mutex_t* L = (pthread_mutex_t*)mon;
jint res = pthread_mutex_lock(L);
RETURN_FROM_JNI(res);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT void JNICALL
JVM_RawMonitorExit(void *mon) {
BEGIN_JNI_EXCEPTION
pthread_mutex_t* L = (pthread_mutex_t*)mon;
pthread_mutex_unlock(L);
END_JNI_EXCEPTION
RETURN_VOID_FROM_JNI;
}
/*
* java.lang.management support
*/
JNIEXPORT void* JNICALL
JVM_GetManagement(jint version) {
NYI();
}
/*
* com.sun.tools.attach.VirtualMachine support
*
* Initialize the agent properties with the properties maintained in the VM.
*/
JNIEXPORT jobject JNICALL
JVM_InitAgentProperties(JNIEnv *env, jobject agent_props) {
NYI();
}
/* Generics reflection support.
*
* Returns information about the given class's EnclosingMethod
* attribute, if present, or null if the class had no enclosing
* method.
*
* If non-null, the returned array contains three elements. Element 0
* is the java.lang.Class of which the enclosing method is a member,
* and elements 1 and 2 are the java.lang.Strings for the enclosing
* method's name and descriptor, respectively.
*/
JNIEXPORT jobjectArray JNICALL
JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass) {
JavaObjectClass * Cl = 0;
ArrayObject * arr = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(arr, 0);
BEGIN_JNI_EXCEPTION
Jnjvm * vm = th->getJVM();
Cl = ofClass ? *(JavaObjectClass**)ofClass : 0;
verifyNull(Cl);
CommonClass* CC =
UserCommonClass::resolvedImplClass(vm, Cl, false);
Class* cl = CC->asClass();
// Primitives arrays, interfaces...
if (!cl) RETURN_FROM_JNI(0);
JavaAttribute* emAtt = cl->lookupAttribute(JavaAttribute::enclosingMethodAttribute);
if (emAtt) {
Reader reader(emAtt, cl->bytes);
uint16 class_index = reader.readU2();
uint16 method_index = reader.readU2();
JavaConstantPool * cpl = cl->getConstantPool();
CommonClass * enclosingClass = cpl->loadClass(class_index, true);
assert(enclosingClass);
arr = (ArrayObject*)vm->upcalls->ArrayOfObject->doNew(3,vm);
ArrayObject::setElement(arr, enclosingClass->getClassDelegatee(vm), 0);
if (method_index) {
Signdef * sign = cl->getConstantPool()->resolveNameAndSign(method_index);
assert(sign);
const UTF8* methodName = cpl->UTF8At((cpl->ctpDef[method_index] >> 16) & 0xFFFF);
assert(methodName);
ArrayObject::setElement(arr, *cl->classLoader->UTF8ToStr(methodName), 1);
ArrayObject::setElement(arr, *cl->classLoader->UTF8ToStr(sign->keyName), 2);
}
}
RETURN_REF_FROM_JNI(arr, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Returns an array of the threadStatus values representing the
* given Java thread state. Returns NULL if the VM version is
* incompatible with the JDK or doesn't support the given
* Java thread state.
*/
JNIEXPORT jintArray JNICALL
JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState) {
ArraySInt32* res = 0;
jintArray result = 0;
llvm_gcroot(res, 0);
llvm_gcroot(result, 0);
BEGIN_JNI_EXCEPTION
/* If new thread states are added in future JDK and VM versions,
this should check if the JDK version is compatible with thread
states supported by the VM. Return NULL if not compatible.
This function must map the VM java_lang_Thread::ThreadStatus
to the Java thread state that the JDK supports. */
Jnjvm* vm = JavaThread::get()->getJVM();
Classpath* upcalls = vm->upcalls;
UserClassArray* array = upcalls->ArrayOfInt;
switch (javaThreadState) {
case vmkit::LockingThread::StateNew:
case vmkit::LockingThread::StateRunning:
case vmkit::LockingThread::StateBlocked:
case vmkit::LockingThread::StateTerminated:
{
res = (ArraySInt32*)array->doNew(1, vm);
ArraySInt32::setElement(res, javaThreadState , 0);
break;
}
case vmkit::LockingThread::StateWaiting:
{
res = (ArraySInt32*)array->doNew(2, vm);
ArraySInt32::setElement(res, vmkit::LockingThread::StateWaiting , 0);
ArraySInt32::setElement(res, vmkit::LockingThread::StateParked , 1);
break;
}
case vmkit::LockingThread::StateTimeWaiting:
{
res = (ArraySInt32*)array->doNew(2, vm);
ArraySInt32::setElement(res, vmkit::LockingThread::StateTimeWaiting , 0);
ArraySInt32::setElement(res, vmkit::LockingThread::StateTimeParked , 1);
break;
}
default:
/* Unknown state - probably incompatible JDK version */
break;
}
RETURN_REF_FROM_JNI(res, jintArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
/*
* Returns an array of the substate names representing the
* given Java thread state. Returns NULL if the VM version is
* incompatible with the JDK or the VM doesn't support
* the given Java thread state.
* values must be the jintArray returned from JVM_GetThreadStateValues
* and javaThreadState.
*/
JNIEXPORT jobjectArray JNICALL
JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArray values) {
BEGIN_JNI_EXCEPTION
ArrayObject* res = 0;
jobjectArray result = 0;
JavaObject* str = 0;
llvm_gcroot(res, 0);
llvm_gcroot(result, 0);
llvm_gcroot(str, 0);
llvm_gcroot(values, 0);
Jnjvm* vm = JavaThread::get()->getJVM();
Classpath* upcalls = vm->upcalls;
UserClassArray* array = upcalls->ArrayOfString;
JnjvmClassLoader* loader;
switch (javaThreadState) {
case vmkit::LockingThread::StateNew:
{
//assert(ia.get_length() == 1 && ia.get_element(0) == THREAD_STATE_NEW);
res = (ArrayObject*)array->doNew(1, vm);
str = (vm->asciizToStr("NEW"));
ArrayObject::setElement(res, str, 0);
break;
}
case vmkit::LockingThread::StateRunning:
{
res = (ArrayObject*)array->doNew(1, vm);
str = (vm->asciizToStr("RUNNABLE"));
ArrayObject::setElement(res, str, 0);
break;
}
case vmkit::LockingThread::StateBlocked:
{
res = (ArrayObject*)array->doNew(1, vm);
str = (vm->asciizToStr("BLOCKED"));
ArrayObject::setElement(res, str, 0);
break;
}
case vmkit::LockingThread::StateWaiting:
{
res = (ArrayObject*)array->doNew(2, vm);
str = (vm->asciizToStr("WAITING.OBJECT_WAIT"));
ArrayObject::setElement(res, str, 0);
str = (vm->asciizToStr("WAITING.PARKED"));
ArrayObject::setElement(res, str, 1);
break;
}
case vmkit::LockingThread::StateTimeWaiting:
{
res = (ArrayObject*)array->doNew(2, vm);
str = (vm->asciizToStr("TIMED_WAITING.OBJECT_WAIT"));
ArrayObject::setElement(res, str, 0);
str = (vm->asciizToStr("TIMED_WAITING.PARKED"));
ArrayObject::setElement(res, str, 1);
break;
}
case vmkit::LockingThread::StateTerminated:
{
res = (ArrayObject*)array->doNew(1, vm);
str = (vm->asciizToStr("TERMINATED"));
ArrayObject::setElement(res, str, 0);
break;
}
default:
/* Unknown state - probably incompatible JDK version */
break;
}
//th->leaveUncooperativeCode();
RETURN_REF_FROM_JNI(res, jobjectArray);
END_JNI_EXCEPTION
RETURN_FROM_JNI(0);
}
JNIEXPORT void JNICALL
JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size) {
NYI();
}
// vim: set ft=cpp: