classloading bugfixes and stack trace work

This commit is contained in:
Joel Dice 2007-06-29 19:37:45 -06:00
parent 60da97dfc8
commit c34ee64988
5 changed files with 201 additions and 68 deletions

View File

@ -2,6 +2,26 @@ package java.lang;
public class Throwable { public class Throwable {
private String message; private String message;
private Object trace; private StackTraceElement[] trace;
private Throwable cause; private Throwable cause;
public Throwable(String message, Throwable cause) {
this.message = message;
this.trace = trace(1);
this.cause = cause;
}
public Throwable(String message) {
this(message, null);
}
public Throwable(Throwable cause) {
this(null, cause);
}
public Throwable() {
this(null, null);
}
private static native StackTraceElement[] trace(int skipCount);
} }

View File

@ -122,10 +122,10 @@ fast-objects = \
fast-executable = $(bld)/fast-vm fast-executable = $(bld)/fast-vm
fast-cflags = $(fast) $(cflags) fast-cflags = $(fast) $(cflags)
input = $(bld)/classes/Hello.class input = $(bld)/classes/TestExceptions.class
input-depends = \ # input-depends = \
$(bld)/classes/java/lang/System.class \ # $(bld)/classes/java/lang/System.class \
$(jni-library) # $(jni-library)
gen-run-arg = $(shell echo $(1) | sed -e 's:$(bld)/classes/\(.*\)\.class:\1:') gen-run-arg = $(shell echo $(1) | sed -e 's:$(bld)/classes/\(.*\)\.class:\1:')
args = -cp $(bld)/classes -hs 67108864 $(call gen-run-arg,$(input)) args = -cp $(bld)/classes -hs 67108864 $(call gen-run-arg,$(input))

View File

@ -674,6 +674,9 @@ class MemberIterator {
offset_ += padding_; offset_ += padding_;
// printf("size: %d; padding: %d; alignment: %d; offset: %d;\n",
// size_, padding_, alignment_, offset_);
return member; return member;
} }
@ -1271,8 +1274,6 @@ writeConstructorDeclarations(Output* out, Object* declarations)
Object* o = car(p); Object* o = car(p);
switch (o->type) { switch (o->type) {
case Object::Type: { case Object::Type: {
if (typeMemberCount(o) == 0) continue;
out->write("object make"); out->write("object make");
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
if (typeHideConstructor(o)) out->write("0"); if (typeHideConstructor(o)) out->write("0");
@ -1295,8 +1296,6 @@ writeConstructors(Output* out, Object* declarations)
Object* o = car(p); Object* o = car(p);
switch (o->type) { switch (o->type) {
case Object::Type: { case Object::Type: {
if (typeMemberCount(o) == 0) continue;
out->write("object\nmake"); out->write("object\nmake");
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
if (typeHideConstructor(o)) out->write("0"); if (typeHideConstructor(o)) out->write("0");
@ -1343,7 +1342,6 @@ writeEnums(Output* out, Object* declarations)
Object* o = car(p); Object* o = car(p);
switch (o->type) { switch (o->type) {
case Object::Type: { case Object::Type: {
if (typeMemberCount(o)) {
if (wrote) { if (wrote) {
out->write(",\n"); out->write(",\n");
} else { } else {
@ -1351,7 +1349,6 @@ writeEnums(Output* out, Object* declarations)
} }
out->write(capitalize(typeName(o))); out->write(capitalize(typeName(o)));
out->write("Type"); out->write("Type");
}
} break; } break;
default: break; default: break;
@ -1387,7 +1384,7 @@ set(uint32_t* mask, unsigned index)
unsigned unsigned
typeFixedSize(Object* type) typeFixedSize(Object* type)
{ {
unsigned length = 0; unsigned length = sizeof(void*);
for (MemberIterator it(type); it.hasMore();) { for (MemberIterator it(type); it.hasMore();) {
Object* m = it.next(); Object* m = it.next();
switch (m->type) { switch (m->type) {
@ -1465,9 +1462,6 @@ typeObjectMask(Object* type)
void void
writeInitialization(Output* out, Object* type) writeInitialization(Output* out, Object* type)
{ {
unsigned memberCount = ::memberCount(type);
if (memberCount == 0) return;
out->write("{\n"); out->write("{\n");
if (typeObjectMask(type) != 1) { if (typeObjectMask(type) != 1) {
@ -1487,8 +1481,17 @@ writeInitialization(Output* out, Object* type)
out->write(" object name = makeByteArray(t, \""); out->write(" object name = makeByteArray(t, \"");
out->write(typeJavaName(type)); out->write(typeJavaName(type));
out->write("\");\n"); out->write("\");\n");
if (typeSuper(type)) {
out->write(" object super = arrayBody(t, t->vm->types, Machine::");
out->write(capitalize(typeName(typeSuper(type))));
out->write("Type);\n");
} else {
out->write(" object super = 0;\n");
}
} else { } else {
out->write(" object name = 0;\n"); out->write(" object name = 0;\n");
out->write(" object super = 0;\n");
} }
out->write(" object class_ = makeClass"); out->write(" object class_ = makeClass");
@ -1496,7 +1499,7 @@ writeInitialization(Output* out, Object* type)
out->write(typeFixedSize(type)); out->write(typeFixedSize(type));
out->write(", "); out->write(", ");
out->write(typeArrayElementSize(type)); out->write(typeArrayElementSize(type));
out->write(", mask, name, 0, 0, 0, 0, 0, 0, 0);\n"); out->write(", mask, name, super, 0, 0, 0, 0, 0, 0);\n");
out->write(" set(t, arrayBody(t, t->vm->types, Machine::"); out->write(" set(t, arrayBody(t, t->vm->types, Machine::");
out->write(capitalize(typeName(type))); out->write(capitalize(typeName(type)));
@ -1518,9 +1521,7 @@ typeCount(Object* declarations)
Object* o = car(p); Object* o = car(p);
switch (o->type) { switch (o->type) {
case Object::Type: { case Object::Type: {
if (typeMemberCount(o)) {
++ count; ++ count;
}
} break; } break;
default: break; default: break;

View File

@ -51,9 +51,17 @@
(type exceptionHandlerTable (type exceptionHandlerTable
(array exceptionHandler body)) (array exceptionHandler body))
(pod lineNumber
(uint16_t ip)
(uint16_t line))
(type lineNumberTable
(array lineNumber body))
(type code (type code
(object pool) (object pool)
(object exceptionHandlerTable) (object exceptionHandlerTable)
(object lineNumberTable)
(uint16_t maxStack) (uint16_t maxStack)
(uint16_t maxLocals) (uint16_t maxLocals)
(array uint8_t body)) (array uint8_t body))
@ -100,10 +108,9 @@
(object front) (object front)
(object rear)) (object rear))
(type trace (type stackTraceElement
(object method) (object method)
(uint32_t ip) (int32_t ip))
(object next))
(type array (type array
(noassert array object body)) (noassert array object body))

View File

@ -52,6 +52,9 @@ enum FieldCode {
ObjectField ObjectField
}; };
static const int NativeLine = -1;
static const int UnknownLine = -2;
class Machine { class Machine {
public: public:
enum { enum {
@ -808,19 +811,35 @@ makeString(Thread* t, const char* format, ...)
return makeString(t, s, 0, byteArrayLength(t, s), 0); return makeString(t, s, 0, byteArrayLength(t, s), 0);
} }
object
makeTrace(Thread* t, object frame)
{
PROTECT(t, frame);
unsigned count = 0;
for (object f = frame; f; f = frameNext(t, f)) {
++ count;
}
object trace = makeObjectArray
(t, arrayBody(t, t->vm->types, Machine::StackTraceElementType),
count, true);
PROTECT(t, trace);
unsigned index = 0;
for (object f = frame; f; f = frameNext(t, f)) {
object e = makeStackTraceElement(t, frameMethod(t, f), frameIp(t, f));
set(t, objectArrayBody(t, trace, index++), e);
}
return trace;
}
object object
makeTrace(Thread* t) makeTrace(Thread* t)
{ {
object trace = 0;
if (t->frame) {
PROTECT(t, trace);
frameIp(t, t->frame) = t->ip; frameIp(t, t->frame) = t->ip;
for (; t->frame; t->frame = frameNext(t, t->frame)) { return makeTrace(t, t->frame);
trace = makeTrace
(t, frameMethod(t, t->frame), frameIp(t, t->frame), trace);
}
}
return trace;
} }
object object
@ -1093,6 +1112,7 @@ setField(Thread* t, object o, object field, object value)
break; break;
case ObjectField: case ObjectField:
set(t, cast<object>(o, fieldOffset(t, field)), value); set(t, cast<object>(o, fieldOffset(t, field)), value);
break;
default: abort(t); default: abort(t);
} }
@ -1486,10 +1506,11 @@ parseFieldTable(Thread* t, Stream& s, object class_, object pool)
} }
} }
classFixedSize(t, class_) = divide(memberOffset, BytesPerWord); classFixedSize(t, class_) = pad(memberOffset);
object mask = makeIntArray object mask = makeIntArray
(t, divide(classFixedSize(t, class_), BitsPerWord), true); (t, divide(classFixedSize(t, class_), BitsPerWord), true);
intArrayBody(t, mask, 0) = 1;
bool sawReferenceField = false; bool sawReferenceField = false;
for (object c = class_; c; c = classSuper(t, c)) { for (object c = class_; c; c = classSuper(t, c)) {
@ -1518,7 +1539,7 @@ parseCode(Thread* t, Stream& s, object pool)
unsigned maxLocals = s.read2(); unsigned maxLocals = s.read2();
unsigned length = s.read4(); unsigned length = s.read4();
object code = makeCode(t, pool, 0, maxStack, maxLocals, length, false); object code = makeCode(t, pool, 0, 0, maxStack, maxLocals, length, false);
s.read(&codeBody(t, code, 0), length); s.read(&codeBody(t, code, 0), length);
unsigned ehtLength = s.read2(); unsigned ehtLength = s.read2();
@ -1539,8 +1560,24 @@ parseCode(Thread* t, Stream& s, object pool)
unsigned attributeCount = s.read2(); unsigned attributeCount = s.read2();
for (unsigned j = 0; j < attributeCount; ++j) { for (unsigned j = 0; j < attributeCount; ++j) {
s.read2(); object name = arrayBody(t, pool, s.read2() - 1);
s.skip(s.read4()); unsigned length = s.read4();
if (strcmp(reinterpret_cast<const int8_t*>("LineNumberTable"),
&byteArrayBody(t, name, 0)) == 0)
{
unsigned lntLength = s.read2();
object lnt = makeLineNumberTable(t, lntLength, false);
for (unsigned i = 0; i < lntLength; ++i) {
LineNumber* ln = lineNumberTableBody(t, lnt, i);
lineNumberIp(ln) = s.read2();
lineNumberLine(ln) = s.read2();
}
set(t, codeLineNumberTable(t, code), lnt);
} else {
s.skip(length);
}
} }
return code; return code;
@ -1574,6 +1611,30 @@ parameterCount(Thread* t, object spec)
return count; return count;
} }
int
lineNumber(Thread* t, object method, unsigned ip)
{
if (methodFlags(t, method) & ACC_NATIVE) {
return NativeLine;
}
object table = codeLineNumberTable(t, methodCode(t, method));
if (table) {
// todo: do a binary search:
int last = UnknownLine;
for (unsigned i = 0; i < lineNumberTableLength(t, table); ++i) {
if (ip <= lineNumberIp(lineNumberTableBody(t, table, i))) {
return last;
} else {
last = lineNumberLine(lineNumberTableBody(t, table, i));
}
}
return last;
} else {
return UnknownLine;
}
}
unsigned unsigned
mangledSize(int8_t c) mangledSize(int8_t c)
{ {
@ -2158,7 +2219,7 @@ invokeNative(Thread* t, object method)
args[offset++] = reinterpret_cast<uintptr_t>(t); args[offset++] = reinterpret_cast<uintptr_t>(t);
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
unsigned type = nativeMethodDataParameterTypes(t, data, i); unsigned type = nativeMethodDataParameterTypes(t, data, i + 1);
unsigned position = (t->sp - count) + i; unsigned position = (t->sp - count) + i;
object o = t->stack[position]; object o = t->stack[position];
@ -2222,8 +2283,10 @@ invokeNative(Thread* t, object method)
} }
} }
namespace builtin {
void void
builtinLoadLibrary(JNIEnv* e, jstring nameString) loadLibrary(JNIEnv* e, jstring nameString)
{ {
Thread* t = static_cast<Thread*>(e); Thread* t = static_cast<Thread*>(e);
@ -2250,7 +2313,7 @@ builtinLoadLibrary(JNIEnv* e, jstring nameString)
} }
jstring jstring
builtinToString(JNIEnv* e, jobject this_) toString(JNIEnv* e, jobject this_)
{ {
Thread* t = static_cast<Thread*>(e); Thread* t = static_cast<Thread*>(e);
@ -2263,6 +2326,34 @@ builtinToString(JNIEnv* e, jobject this_)
return t->stack + (t->sp - 1); return t->stack + (t->sp - 1);
} }
jarray
trace(JNIEnv* e, jint skipCount)
{
Thread* t = static_cast<Thread*>(e);
object frame = t->frame;
while (skipCount--) frame = frameNext(t, frame);
if (methodClass(t, frameMethod(t, frame))
== arrayBody(t, t->vm->types, Machine::ThrowableType))
{
// skip Throwable constructors
while (strcmp(reinterpret_cast<const int8_t*>("<init>"),
&byteArrayBody(t, methodName(t, frameMethod(t, frame)), 0))
== 0)
{
frame = frameNext(t, frame);
}
}
pushSafe(t, makeTrace(t, frame));
return t->stack + (t->sp - 1);
}
} // namespace builtin
namespace jni {
jsize jsize
GetStringUTFLength(JNIEnv* e, jstring s) GetStringUTFLength(JNIEnv* e, jstring s)
{ {
@ -2304,7 +2395,7 @@ GetStringUTFChars(JNIEnv* e, jstring s, jboolean* isCopy)
enter(t, Thread::IdleState); enter(t, Thread::IdleState);
*isCopy = true; if (isCopy) *isCopy = true;
return chars; return chars;
} }
@ -2314,6 +2405,8 @@ ReleaseStringUTFChars(JNIEnv* e, jstring, const char* chars)
static_cast<Thread*>(e)->vm->system->free(chars); static_cast<Thread*>(e)->vm->system->free(chars);
} }
} // namespace jni
Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder): Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
system(system), system(system),
heap(heap), heap(heap),
@ -2334,9 +2427,9 @@ Machine::Machine(System* system, Heap* heap, ClassFinder* classFinder):
{ {
memset(&jniEnvVTable, 0, sizeof(JNIEnvVTable)); memset(&jniEnvVTable, 0, sizeof(JNIEnvVTable));
jniEnvVTable.GetStringUTFLength = GetStringUTFLength; jniEnvVTable.GetStringUTFLength = jni::GetStringUTFLength;
jniEnvVTable.GetStringUTFChars = GetStringUTFChars; jniEnvVTable.GetStringUTFChars = jni::GetStringUTFChars;
jniEnvVTable.ReleaseStringUTFChars = ReleaseStringUTFChars; jniEnvVTable.ReleaseStringUTFChars = jni::ReleaseStringUTFChars;
if (not system->success(system->make(&stateLock)) or if (not system->success(system->make(&stateLock)) or
not system->success(system->make(&heapLock)) or not system->success(system->make(&heapLock)) or
@ -2408,9 +2501,11 @@ Thread::Thread(Machine* m):
void* value; void* value;
} builtins[] = { } builtins[] = {
{ "Java_java_lang_Object_toString", { "Java_java_lang_Object_toString",
reinterpret_cast<void*>(builtinToString) }, reinterpret_cast<void*>(builtin::toString) },
{ "Java_java_lang_System_loadLibrary", { "Java_java_lang_System_loadLibrary",
reinterpret_cast<void*>(builtinLoadLibrary) }, reinterpret_cast<void*>(builtin::loadLibrary) },
{ "Java_java_lang_Throwable_trace",
reinterpret_cast<void*>(builtin::trace) },
{ 0, 0 } { 0, 0 }
}; };
@ -3849,14 +3944,6 @@ run(Thread* t)
} }
} }
object p = 0;
object n = 0;
for (object trace = throwableTrace(t, exception); trace; trace = n) {
n = traceNext(t, trace);
set(t, traceNext(t, trace), p);
p = trace;
}
for (object e = exception; e; e = throwableCause(t, e)) { for (object e = exception; e; e = throwableCause(t, e)) {
if (e == exception) { if (e == exception) {
fprintf(stderr, "uncaught exception: "); fprintf(stderr, "uncaught exception: ");
@ -3870,14 +3957,32 @@ run(Thread* t)
if (throwableMessage(t, exception)) { if (throwableMessage(t, exception)) {
fprintf(stderr, ": %s\n", &byteArrayBody fprintf(stderr, ": %s\n", &byteArrayBody
(t, stringBytes(t, throwableMessage(t, exception)), 0)); (t, stringBytes(t, throwableMessage(t, exception)), 0));
} else {
fprintf(stderr, "\n");
} }
for (; p; p = traceNext(t, p)) { object trace = throwableTrace(t, e);
fprintf(stderr, " at %s.%s\n", for (unsigned i = 0; i < objectArrayLength(t, trace); ++i) {
&byteArrayBody object e = objectArrayBody(t, trace, i);
(t, className(t, methodClass(t, traceMethod(t, p))), 0), const int8_t* class_ = &byteArrayBody
&byteArrayBody (t, className(t, methodClass(t, stackTraceElementMethod(t, e))), 0);
(t, methodName(t, traceMethod(t, p)), 0)); const int8_t* method = &byteArrayBody
(t, methodName(t, stackTraceElementMethod(t, e)), 0);
int line = lineNumber
(t, stackTraceElementMethod(t, e), stackTraceElementIp(t, e));
fprintf(stderr, " at %s.%s", class_, method);
switch (line) {
case NativeLine:
fprintf(stderr, "(native)\n");
break;
case UnknownLine:
fprintf(stderr, "(unknown)\n");
break;
default:
fprintf(stderr, "(%d)\n", line);
}
} }
} }