blob: 53231220ee84d46d4453018a20e5a42a3b8758b8 [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;
llvm_gcroot(throwable, 0);
llvm_gcroot(vmThrowable, 0);
JavaThread* th = JavaThread::get();
Jnjvm* vm = th->getJVM();
uint32 length = th->getFrameContextLength();
ClassArray* cl = sizeof(void*) == 4 ? vm->upcalls->ArrayOfInt :
vm->upcalls->ArrayOfLong;
JavaArray* result = (JavaArray*) cl->doNew(length, vm);
void** tab = (void**)result->elements;
// Get the frame context.
th->getFrameContext(tab);
// Set the tempory data in the new VMThrowable object.
vmThrowable = vm->upcalls->newVMThrowable->doNew(vm);
uint64 ptr = (uint64)vmThrowable + vm->upcalls->vmDataVMThrowable->ptrOffset;
((JavaObject**)ptr)[0] = 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;
}
static JavaObject* consStackElement(JavaMethod* meth, void* 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();
methodName = vm->internalUTF8ToStr(meth->name);
Class* cl = meth->classDef;
className = JavaString::internalToJava(cl->name, vm);
Attribut* sourceAtt = cl->lookupAttribut(Attribut::sourceFileAttribut);
// We don't have the bytes if the class was vmjc'ed.
if (sourceAtt && cl->getBytes()) {
Reader reader(sourceAtt, cl->getBytesPtr());
uint16 index = reader.readU2();
sourceName = vm->internalUTF8ToStr(cl->getConstantPool()->UTF8At(index));
}
bool native = isNative(meth->access);
uint16 lineNumber = meth->lookupLineNumber(reinterpret_cast<uintptr_t>(ip));
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 = 0;
llvm_gcroot(vmthrow, 0);
llvm_gcroot(throwable, 0);
llvm_gcroot(result, 0);
BEGIN_NATIVE_EXCEPTION(0)
Jnjvm* vm = JavaThread::get()->getJVM();
JavaField* field = vm->upcalls->vmDataVMThrowable;
JavaArray* stack = (JavaArray*)field->getObjectField(vmthrow);
// remove the VMThrowable.fillInStackTrace method and the last method
// on the stack.
sint32 index = 2;;
while (index != stack->size) {
mvm::MethodInfo* MI = vm->IPToMethodInfo(stack->elements[index]);
if (MI->MethodType != 1) ++index;
else {
JavaMethod* meth = (JavaMethod*)MI->getMetaInfo();
assert(meth && "Wrong stack trace");
if (meth->classDef->isAssignableFrom(vm->upcalls->newThrowable)) {
++index;
} else break;
}
}
sint32 size = 0;
sint32 cur = index;
while (cur < stack->size) {
mvm::MethodInfo* MI = vm->IPToMethodInfo(stack->elements[cur]);
++cur;
if (MI->MethodType == 1) ++size;
}
result = (ArrayObject*)
vm->upcalls->stackTraceArray->doNew(size, vm);
cur = 0;
for (sint32 i = index; i < stack->size; ++i) {
mvm::MethodInfo* MI = vm->IPToMethodInfo(stack->elements[i]);
if (MI->MethodType == 1) {
JavaMethod* meth = (JavaMethod*)MI->getMetaInfo();
result->elements[cur] = consStackElement(meth, stack->elements[i]);
cur++;
}
}
END_NATIVE_EXCEPTION
return result;
}
}