blob: 361c9652e639afd666f8c69089e5f37d0dc9dcd3 [file] [log] [blame]
//===- ClasspathVMClassLoader.cpp - GNU classpath java/lang/VMClassLoader -===//
//
// JnJVM
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <string.h>
#include "types.h"
#include "mvm/JIT.h"
#include "JavaAccess.h"
#include "JavaArray.h"
#include "JavaClass.h"
#include "JavaConstantPool.h"
#include "JavaJIT.h"
#include "JavaObject.h"
#include "JavaString.h"
#include "JavaTypes.h"
#include "JavaThread.h"
#include "JavaUpcalls.h"
#include "Jnjvm.h"
#include "NativeUtil.h"
#include "Reader.h"
using namespace jnjvm;
extern "C" {
JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_fillInStackTrace(
#ifdef NATIVE_JNI
JNIEnv *env,
jclass clazz,
#endif
jobject throwable) {
Jnjvm* vm = JavaThread::get()->isolate;
int** stack = (int**)malloc(sizeof(int*) * 100);
int real_size = mvm::jit::getBacktrace((void**)stack, 100);
stack[real_size] = 0;
JavaObject* vmThrowable = vm->upcalls->newVMThrowable->doNew(vm);
((JavaObject**)((uint64)vmThrowable + vm->upcalls->vmDataVMThrowable->ptrOffset))[0] = (JavaObject*)stack;
return (jobject)vmThrowable;
}
JavaObject* consStackElement(JavaMethod* meth, int* ip) {
Jnjvm* vm = JavaThread::get()->isolate;
JavaObject* methodName = vm->UTF8ToStr(meth->name);
Class* cl = meth->classDef;
JavaObject* className = vm->UTF8ToStr(cl->name->internalToJava(cl->classLoader->hashUTF8, 0, cl->name->size));
JavaObject* sourceName = 0;
Attribut* sourceAtt = cl->lookupAttribut(Attribut::sourceFileAttribut);
if (sourceAtt) {
Reader reader(sourceAtt, cl->getBytes());
uint16 index = reader.readU2();
sourceName = vm->UTF8ToStr(cl->getConstantPool()->UTF8At(index));
}
bool native = isNative(meth->access);
UserClass* newS = vm->upcalls->newStackTraceElement;
JavaObject* res = newS->doNew(vm);
vm->upcalls->initStackTraceElement->invokeIntSpecial(vm, newS, res,
sourceName,
(uint32)ip, className,
methodName, native);
return res;
}
ArrayObject* recGetStackTrace(int** stack, uint32 first, uint32 rec) {
Jnjvm* vm = JavaThread::get()->isolate;
if (stack[first] != 0) {
JavaMethod* meth = JavaJIT::IPToJavaMethod(stack[first]);
if (meth) {
ArrayObject* res = recGetStackTrace(stack, first + 1, rec + 1);
res->elements[rec] = consStackElement(meth, stack[first]);
return res;
} else {
return recGetStackTrace(stack, first + 1, rec);
}
} else {
return (ArrayObject*)vm->upcalls->stackTraceArray->doNew(rec, vm);
}
}
JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_getStackTrace(
#ifdef NATIVE_JNI
JNIEnv *env,
#endif
jobject vmthrow, jobject throwable) {
Jnjvm* vm = JavaThread::get()->isolate;
int** stack = (int**)vm->upcalls->vmDataVMThrowable->getObjectField((JavaObject*)vmthrow);
uint32 first = 0;
sint32 i = 0;
while (stack[i] != 0) {
JavaMethod* meth = JavaJIT::IPToJavaMethod(stack[i++]);
#ifdef MULTIPLE_VM
if (meth) {
#else
if (meth && !meth->classDef->subclassOf(vm->upcalls->newThrowable)) {
#endif
first = i - 1;
break;
}
}
jobject res = (jobject)recGetStackTrace((int**)(uint32**)stack, first, 0);
free(stack);
return res;
}
}