blob: 1dec2ab257f006280509ebfcc2d0070ff57b8a3a [file] [log] [blame]
//===---- ClasspathVMClass.cpp - GNU classpath java/lang/VMClass ----------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "types.h"
#include "Classpath.h"
#include "ClasspathReflect.h"
#include "JavaAccess.h"
#include "JavaArray.h"
#include "JavaClass.h"
#include "JavaObject.h"
#include "JavaString.h"
#include "JavaTypes.h"
#include "JavaThread.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
using namespace j3;
extern "C" {
// Never throws
JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isArray(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObjectClass* klass) {
llvm_gcroot(klass, 0);
UserCommonClass* cl = klass->getClass();
return cl->isArray();
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_forName(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaString* str,
jboolean clinit,
JavaObject* loader) {
JavaObject* res = 0;
llvm_gcroot(loader, 0);
llvm_gcroot(str, 0);
llvm_gcroot(res, 0);
BEGIN_NATIVE_EXCEPTION(0)
verifyNull(str);
Jnjvm* vm = JavaThread::get()->getJVM();
JnjvmClassLoader* JCL =
JnjvmClassLoader::getJnjvmLoaderFromJavaObject(loader, vm);
UserCommonClass* cl = JCL->loadClassFromJavaString(str, true, false);
if (cl != 0) {
if (clinit && cl->asClass()) {
cl->asClass()->initialiseClass(vm);
}
res =cl->getClassDelegatee(vm);
} else {
vm->classNotFoundException(str);
}
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl,
jboolean publicOnly) {
ArrayObject* ret = 0;
JavaObject* tmp = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(ret, 0);
llvm_gcroot(tmp, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
if (cl->isArray() || cl->isInterface() || cl->isPrimitive()) {
ret = (ArrayObject*)vm->upcalls->constructorArrayClass->doNew(0, vm);
} else {
UserClass* realCl = cl->asClass();;
JnjvmClassLoader* classLoader = cl->classLoader;
uint32 size = 0;
for (uint32 i = 0; i < realCl->nbVirtualMethods; ++i) {
JavaMethod* meth = &realCl->virtualMethods[i];
bool pub = isPublic(meth->access);
if (meth->name->equals(classLoader->bootstrapLoader->initName) &&
(!publicOnly || pub)) {
++size;
}
}
ret = (ArrayObject*)vm->upcalls->constructorArrayClass->doNew(size, vm);
sint32 index = 0;
for (uint32 i = 0; i < realCl->nbVirtualMethods; ++i) {
JavaMethod* meth = &realCl->virtualMethods[i];
bool pub = isPublic(meth->access);
if (meth->name->equals(classLoader->bootstrapLoader->initName) &&
(!publicOnly || pub)) {
UserClass* Cons = vm->upcalls->newConstructor;
tmp = Cons->doNew(vm);
vm->upcalls->initConstructor->invokeIntSpecial(vm, Cons, tmp, &Cl, i);
ret->elements[index++] = tmp;
}
}
}
END_NATIVE_EXCEPTION
return ret;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaredMethods(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl,
jboolean publicOnly) {
ArrayObject* ret = 0;
JavaObject* tmp = 0;
JavaString* str = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(ret, 0);
llvm_gcroot(tmp, 0);
llvm_gcroot(str, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
Classpath* upcalls = vm->upcalls;
if (cl->isArray() || cl->isPrimitive()) {
ret = (ArrayObject*)upcalls->methodArrayClass->doNew(0, vm);
} else {
UserClass* realCl = cl->asClass();
JnjvmClassLoader* classLoader = cl->classLoader;
uint32 size = 0;
for (uint32 i = 0; i < realCl->nbVirtualMethods + realCl->nbStaticMethods;
++i) {
JavaMethod* meth = &realCl->virtualMethods[i];
bool pub = isPublic(meth->access);
if (!(meth->name->equals(classLoader->bootstrapLoader->initName)) &&
(!publicOnly || pub)) {
++size;
}
}
ret = (ArrayObject*)upcalls->methodArrayClass->doNew(size, vm);
sint32 index = 0;
for (uint32 i = 0; i < realCl->nbVirtualMethods + realCl->nbStaticMethods;
++i) {
JavaMethod* meth = &realCl->virtualMethods[i];
bool pub = isPublic(meth->access);
if (!(meth->name->equals(classLoader->bootstrapLoader->initName)) &&
(!publicOnly || pub)) {
// TODO: check parameter types
UserClass* Meth = vm->upcalls->newMethod;
tmp = Meth->doNew(vm);
str = vm->internalUTF8ToStr(meth->name);
upcalls->initMethod->invokeIntSpecial(vm, Meth, tmp, &Cl, &str, i);
ret->elements[index++] = tmp;
}
}
}
END_NATIVE_EXCEPTION
return ret;
}
JNIEXPORT jint JNICALL Java_java_lang_VMClass_getModifiers(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl,
jboolean ignore) {
jint res = 0;
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
res = cl->getAccess();
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getName(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
JavaObject* result = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(result, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
const UTF8* iname = cl->getName();
result = JavaString::internalToJava(iname, vm);
END_NATIVE_EXCEPTION
return result;
}
JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isPrimitive(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
jboolean res = 0;
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
res = cl->isPrimitive();
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isInterface(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
jboolean res = 0;
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
res = cl->isInterface();
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getComponentType(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
JavaObject* res = 0;
llvm_gcroot(res, 0);
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
if (cl->isArray()) {
UserCommonClass* bc = cl->asArrayClass()->baseClass();
res = bc->getClassDelegatee(vm);
} else {
res = 0;
}
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getClassLoader(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
JavaObject* res = 0;
llvm_gcroot(res, 0);
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
res = cl->classLoader->getJavaClassLoader();
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isAssignableFrom(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl1, JavaObject* Cl2) {
jboolean res = 0;
llvm_gcroot(Cl1, 0);
llvm_gcroot(Cl2, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
if (!Cl2) vm->nullPointerException();
UserCommonClass* cl1 = UserCommonClass::resolvedImplClass(vm, Cl1, false);
UserCommonClass* cl2 = UserCommonClass::resolvedImplClass(vm, Cl2, false);
res = cl2->isAssignableFrom(cl1);
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getSuperclass(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
JavaObject* res = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(res, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
if (cl->isInterface()) res = 0;
else {
if (cl->getSuper()) res = cl->getSuper()->getClassDelegatee(vm);
else res = 0;
}
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT bool JNICALL Java_java_lang_VMClass_isInstance(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl, JavaObject* obj) {
bool res = false;
llvm_gcroot(Cl, 0);
llvm_gcroot(obj, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
res = obj->instanceOf(cl);
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaredFields(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl, jboolean publicOnly) {
ArrayObject* ret = 0;
JavaObject* tmp = 0;
JavaString* name = 0;
llvm_gcroot(Cl, 0);
llvm_gcroot(ret, 0);
llvm_gcroot(tmp, 0);
llvm_gcroot(name, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
if (!cl->isClass()) {
ret = (ArrayObject*)vm->upcalls->fieldArrayClass->doNew(0, vm);
} else {
UserClass* realCl = cl->asClass();
uint32 size = 0;
for (uint32 i = 0; i < realCl->nbVirtualFields + realCl->nbStaticFields;
++i) {
JavaField* field = &realCl->virtualFields[i];
if (!publicOnly || isPublic(field->access)) {
++size;
}
}
ret = (ArrayObject*)vm->upcalls->fieldArrayClass->doNew(size, vm);
sint32 index = 0;
for (uint32 i = 0; i < realCl->nbVirtualFields + realCl->nbStaticFields;
++i) {
JavaField* field = &realCl->virtualFields[i];
if (!publicOnly || isPublic(field->access)) {
// TODO: check parameter types
UserClass* Field = vm->upcalls->newField;
tmp = Field->doNew(vm);
name = vm->internalUTF8ToStr(field->name);
vm->upcalls->initField->invokeIntSpecial(vm, Field, tmp, &Cl, &name, i);
ret->elements[index++] = tmp;
}
}
}
END_NATIVE_EXCEPTION
return ret;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getInterfaces(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
ArrayObject* res = 0;
llvm_gcroot(res, 0);
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserCommonClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false);
res = (ArrayObject*)vm->upcalls->classArrayClass->doNew(cl->nbInterfaces, vm);
for (uint16 i = 0; i < cl->nbInterfaces; ++i) {
UserClass* klass = cl->interfaces[i];
res->elements[i] = klass->getClassDelegatee(vm);
}
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaringClass(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
JavaObject* res = 0;
llvm_gcroot(res, 0);
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false)->asClass();
if (cl) {
cl->resolveInnerOuterClasses();
UserClass* outer = cl->getOuterClass();
if (outer) {
res = outer->getClassDelegatee(vm);
}
}
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMClass_getDeclaredClasses(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl, bool publicOnly) {
ArrayObject* result = 0;
llvm_gcroot(result, 0);
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false)->asClass();
if (cl) {
cl->resolveInnerOuterClasses();
UserClassArray* array = vm->upcalls->constructorArrayClass;
uint16 sizeArray = 0;
if (publicOnly) {
for (uint16 i = 0; i < cl->nbInnerClasses; ++i) {
UserClass* klass = cl->innerClasses[i];
if (isPublic(klass->innerAccess)) ++sizeArray;
}
} else {
sizeArray = cl->nbInnerClasses;
}
result = (ArrayObject*)array->doNew(sizeArray, vm);
for (uint16 i = 0; i < cl->nbInnerClasses; ++i) {
UserClass* klass = cl->innerClasses[i];
if (!publicOnly || isPublic(klass->innerAccess))
result->elements[i] = klass->getClassDelegatee(vm);
}
}
END_NATIVE_EXCEPTION
return result;
}
// Only throws.
JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* throwable) {
llvm_gcroot(throwable, 0);
assert(throwable && "Using internal VM throw exception without exception");
JavaThread::get()->pendingException = (JavaObject*)throwable;
}
JNIEXPORT ArrayObject* Java_java_lang_VMClass_getDeclaredAnnotations(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
// TODO implement me
ArrayObject* res = 0;
llvm_gcroot(res, 0);
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserClassArray* array = vm->upcalls->constructorArrayAnnotation;
res = (ArrayObject*)array->doNew(0, vm);
END_NATIVE_EXCEPTION
return res;
}
JNIEXPORT jboolean Java_java_lang_VMClass_isAnonymousClass(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* Cl) {
jboolean res = false;
llvm_gcroot(Cl, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
UserClass* cl = UserCommonClass::resolvedImplClass(vm, Cl, false)->asClass();
if (cl) res = cl->isAnonymous;
END_NATIVE_EXCEPTION
return res;
}
}