blob: bc27c914ec857b9f9d0bee7c40904af55201ad6b [file] [log] [blame]
//===- ClasspathVMClassLoader.cpp - GNU classpath java/lang/VMClassLoader -===//
//
// 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 "JavaAccess.h"
#include "JavaArray.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaObject.h"
#include "JavaString.h"
#include "JavaThread.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "Reader.h"
using namespace j3;
extern "C" {
JavaObject* internalFillInStackTrace(JavaObject* throwable) {
JavaObject* vmThrowable = 0;
ArrayPtr* result = 0;
llvm_gcroot(throwable, 0);
llvm_gcroot(vmThrowable, 0);
llvm_gcroot(result, 0);
JavaThread* th = JavaThread::get();
Jnjvm* vm = th->getJVM();
uint32 length = th->getFrameContextLength();
if (sizeof(void*) == 4) {
ClassArray* cl = vm->upcalls->ArrayOfInt;
result = (ArrayPtr*) cl->doNew(length, vm);
} else {
ClassArray* cl = vm->upcalls->ArrayOfLong;
result = (ArrayPtr*) cl->doNew(length, vm);
}
// 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;
}
// Set the tempory data in the new VMThrowable object.
vmThrowable = vm->upcalls->newVMThrowable->doNew(vm);
vm->upcalls->vmDataVMThrowable->setInstanceObjectField(vmThrowable, result);
return vmThrowable;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
JavaObject* throwable) {
JavaObject* res = 0;
llvm_gcroot(res, 0);
llvm_gcroot(throwable, 0);
BEGIN_NATIVE_EXCEPTION(0)
res = internalFillInStackTrace(throwable);
END_NATIVE_EXCEPTION
return res;
}
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);
// We don't have the bytes if the class was vmjc'ed.
if (sourceAtt && cl->getBytes()) {
Reader reader(sourceAtt, cl->bytes);
uint16 index = reader.readU2();
sourceName = vm->internalUTF8ToStr(cl->getConstantPool()->UTF8At(index));
}
bool native = isNative(meth->access);
uint16 lineNumber = meth->lookupLineNumber(FI);
UserClass* newS = vm->upcalls->newStackTraceElement;
res = newS->doNew(vm);
vm->upcalls->initStackTraceElement->invokeIntSpecial(vm, newS, res,
&sourceName,
lineNumber,
&className,
&methodName, native);
return res;
}
JNIEXPORT JavaObject* JNICALL Java_java_lang_VMThrowable_getStackTrace(
#ifdef NATIVE_JNI
JNIEnv *env,
#endif
JavaObject* vmthrow, JavaObject* throwable) {
ArrayObject* result = NULL;
JavaObject* stack = NULL;
llvm_gcroot(vmthrow, 0);
llvm_gcroot(throwable, 0);
llvm_gcroot(result, 0);
llvm_gcroot(stack, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
JavaField* field = vm->upcalls->vmDataVMThrowable;
stack = field->getInstanceObjectField(vmthrow);
// remove the VMThrowable.fillInStackTrace method and the last method
// on the stack.
sint32 index = 2;;
while (index != JavaArray::getSize(stack)) {
vmkit::FrameInfo* FI = vm->IPToFrameInfo(ArrayPtr::getElement((ArrayPtr*)stack, index));
if (FI->Metadata == NULL) ++index;
else {
JavaMethod* meth = (JavaMethod*)FI->Metadata;
assert(meth && "Wrong stack trace");
if (meth->classDef->isSubclassOf(vm->upcalls->newThrowable)) {
++index;
} else break;
}
}
sint32 size = 0;
sint32 cur = index;
while (cur < JavaArray::getSize(stack)) {
vmkit::FrameInfo* FI = vm->IPToFrameInfo(ArrayPtr::getElement((ArrayPtr*)stack, cur));
++cur;
if (FI->Metadata != NULL) ++size;
}
result = (ArrayObject*)
vm->upcalls->stackTraceArray->doNew(size, vm);
cur = 0;
for (sint32 i = index; i < JavaArray::getSize(stack); ++i) {
vmkit::FrameInfo* FI = vm->IPToFrameInfo(ArrayPtr::getElement((ArrayPtr*)stack, i));
if (FI->Metadata != NULL) {
ArrayObject::setElement(result, consStackElement(FI, ArrayPtr::getElement((ArrayPtr*)stack, i)), cur);
cur++;
}
}
END_NATIVE_EXCEPTION
return result;
}
}