working reflection

This commit is contained in:
Joel Dice 2007-07-23 21:16:59 -06:00
parent 5f3bf175e0
commit 823d764998
8 changed files with 116 additions and 80 deletions

View File

@ -101,7 +101,8 @@ public final class String implements Comparable<String> {
return new String(data, offset + start, end - start, false); return new String(data, offset + start, end - start, false);
} }
} else { } else {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException
(start + " not in (0, " + end + ") or " + end + " > " + length);
} }
} }

View File

@ -53,15 +53,20 @@ public class Method<T> extends AccessibleObject implements Member {
for (int i = 0; i < spec.length(); ++i) { for (int i = 0; i < spec.length(); ++i) {
char c = spec.charAt(i); char c = spec.charAt(i);
if (c == 'L') { if (c == ')') {
String name = spec.substring(i + 1, next(';', spec, i + 1)); break;
} else if (c == 'L') {
int start = i + 1;
i = next(';', spec, start);
String name = spec.substring(start, i);
types[index++] = Class.forName(name); types[index++] = Class.forName(name);
} else if (c == '[') { } else if (c == '[') {
int start = i; int start = i;
while (spec.charAt(i) == '[') ++i; while (spec.charAt(i) == '[') ++i;
if (spec.charAt(i) == 'L') { if (spec.charAt(i) == 'L') {
String name = spec.substring(start, next(';', spec, i + 1)); i = next(';', spec, i + 1);
String name = spec.substring(start, i);
types[index++] = Class.forName(name); types[index++] = Class.forName(name);
} else { } else {
String name = spec.substring(start, i + 1); String name = spec.substring(start, i + 1);

View File

@ -169,23 +169,29 @@ get(Thread* t, jobject this_, jobject instancep)
} }
jobject jobject
invoke(Thread* t, jobject this_, jobject instance, jobjectArray arguments) invoke(Thread* t, jobject this_, jobject instancep, jobjectArray argumentsp)
{ {
object method = *this_; object method = *this_;
if (arguments) { if (argumentsp) {
object arguments = *argumentsp;
if (methodFlags(t, method) & ACC_STATIC) { if (methodFlags(t, method) & ACC_STATIC) {
if (objectArrayLength(t, arguments) == methodParameterCount(t, method)) { if (objectArrayLength(t, arguments)
return pushReference(t, doInvoke(t, method, 0, *arguments)); == methodParameterCount(t, method))
{
return pushReference(t, doInvoke(t, method, 0, arguments));
} else { } else {
t->exception = makeArrayIndexOutOfBoundsException(t, 0); t->exception = makeArrayIndexOutOfBoundsException(t, 0);
} }
} else if (instance) { } else if (instancep) {
object instance = *instancep;
if (instanceOf(t, methodClass(t, method), instance)) { if (instanceOf(t, methodClass(t, method), instance)) {
if (objectArrayLength(t, arguments) if (objectArrayLength(t, arguments)
== static_cast<unsigned>(methodParameterCount(t, method) - 1)) == static_cast<unsigned>(methodParameterCount(t, method) - 1))
{ {
return pushReference(t, doInvoke(t, method, *instance, *arguments)); return pushReference(t, doInvoke(t, method, instance, arguments));
} else { } else {
t->exception = makeArrayIndexOutOfBoundsException(t, 0); t->exception = makeArrayIndexOutOfBoundsException(t, 0);
} }
@ -382,6 +388,10 @@ start(Thread* t, jobject this_)
vm::run(t, "java/lang/Thread", "run", "()V", t->javaThread); vm::run(t, "java/lang/Thread", "run", "()V", t->javaThread);
if (t->exception) {
printTrace(t, t->exception);
}
t->exit(); t->exit();
} }
@ -412,12 +422,8 @@ populate(Thread* t, object map)
} builtins[] = { } builtins[] = {
{ "Java_java_lang_Class_forName", { "Java_java_lang_Class_forName",
reinterpret_cast<void*>(forName) }, reinterpret_cast<void*>(forName) },
{ "Java_java_lang_Class_isAssignableFrom",
{ "Java_java_lang_Field_get", reinterpret_cast<void*>(isAssignableFrom) },
reinterpret_cast<void*>(get) },
{ "Java_java_lang_Method_invoke",
reinterpret_cast<void*>(invoke) },
{ "Java_java_lang_System_arraycopy", { "Java_java_lang_System_arraycopy",
reinterpret_cast<void*>(arraycopy) }, reinterpret_cast<void*>(arraycopy) },
@ -452,6 +458,12 @@ populate(Thread* t, object map)
{ "Java_java_lang_Object_wait", { "Java_java_lang_Object_wait",
reinterpret_cast<void*>(wait) }, reinterpret_cast<void*>(wait) },
{ "Java_java_lang_reflect_Field_get",
reinterpret_cast<void*>(get) },
{ "Java_java_lang_reflect_Method_invoke",
reinterpret_cast<void*>(invoke) },
{ 0, 0 } { 0, 0 }
}; };

View File

@ -99,7 +99,7 @@ enum OpCode {
i2s = 0x93, i2s = 0x93,
iadd = 0x60, iadd = 0x60,
iaload = 0x2e, iaload = 0x2e,
iand = 0x73, iand = 0x7e,
iastore = 0x4f, iastore = 0x4f,
iconst_m1 = 0x02, iconst_m1 = 0x02,
iconst_0 = 0x03, iconst_0 = 0x03,
@ -113,9 +113,9 @@ enum OpCode {
if_acmpne = 0xa6, if_acmpne = 0xa6,
if_icmpeq = 0x9f, if_icmpeq = 0x9f,
if_icmpne = 0xa0, if_icmpne = 0xa0,
if_icmpgt = 0xa1, if_icmplt = 0xa1,
if_icmpge = 0xa2, if_icmpge = 0xa2,
if_icmplt = 0xa3, if_icmpgt = 0xa3,
if_icmple = 0xa4, if_icmple = 0xa4,
ifeq = 0x99, ifeq = 0x99,
ifge = 0x9c, ifge = 0x9c,

View File

@ -1653,9 +1653,9 @@ instanceOf(Thread* t, object class_, object o)
{ {
if (o == 0) { if (o == 0) {
return false; return false;
} else {
return isAssignableFrom(t, class_, objectClass(t, o));
} }
return isAssignableFrom(t, class_, objectClass(t, o));
} }
unsigned unsigned
@ -2346,6 +2346,51 @@ collect(Thread* t, Heap::CollectionType type)
killZombies(t, m->rootThread); killZombies(t, m->rootThread);
} }
void
printTrace(Thread* t, object exception)
{
for (object e = exception; e; e = throwableCauseUnsafe(t, e)) {
if (e != exception) {
fprintf(stderr, "caused by: ");
}
fprintf(stderr, "%s", &byteArrayBody
(t, className(t, objectClass(t, e)), 0));
if (throwableMessageUnsafe(t, e)) {
object m = throwableMessageUnsafe(t, e);
char message[stringLength(t, m) + 1];
stringChars(t, m, message);
fprintf(stderr, ": %s\n", message);
} else {
fprintf(stderr, "\n");
}
object trace = throwableTraceUnsafe(t, e);
for (unsigned i = 0; i < arrayLength(t, trace); ++i) {
object e = arrayBody(t, trace, i);
const int8_t* class_ = &byteArrayBody
(t, className(t, methodClass(t, traceElementMethod(t, e))), 0);
const int8_t* method = &byteArrayBody
(t, methodName(t, traceElementMethod(t, e)), 0);
int line = lineNumber(t, traceElementMethod(t, e), traceElementIp(t, e));
fprintf(stderr, " at %s.%s ", class_, method);
switch (line) {
case NativeLine:
fprintf(stderr, "(native)\n");
break;
case UnknownLine:
fprintf(stderr, "(unknown line)\n");
break;
default:
fprintf(stderr, "(line %d)\n", line);
}
}
}
}
void void
noop() noop()
{ } { }

View File

@ -22,7 +22,7 @@
namespace vm { namespace vm {
const bool Verbose = false; const bool Verbose = false;
const bool DebugRun = true; const bool DebugRun = false;
const bool DebugStack = false; const bool DebugStack = false;
const bool DebugMonitors = false; const bool DebugMonitors = false;
@ -2079,6 +2079,9 @@ vmNotifyAll(Thread* t, object o)
notifyAll(t, o); notifyAll(t, o);
} }
void
printTrace(Thread* t, object exception);
void void
exit(Thread* t); exit(Thread* t);

View File

@ -91,8 +91,7 @@ make(Thread* t, object class_)
ACQUIRE(t, t->vm->referenceLock); ACQUIRE(t, t->vm->referenceLock);
// jreferenceNext(t, instance) jreferenceNextUnsafe(t, instance) = t->vm->weakReferences;
cast<object>(instance, BytesPerWord) = t->vm->weakReferences;
t->vm->weakReferences = instance; t->vm->weakReferences = instance;
} }
@ -301,6 +300,16 @@ makeNativeMethodData(Thread* t, object method, void* function, bool builtin)
case '[': case '[':
argumentTableSize += BytesPerWord; argumentTableSize += BytesPerWord;
while (*s == '[') ++ s; while (*s == '[') ++ s;
switch (*s) {
case 'L':
while (*s and *s != ';') ++ s;
++ s;
break;
default:
++ s;
break;
}
break; break;
default: default:
@ -1601,16 +1610,16 @@ run(Thread* t)
if (objectClass(t, v) == arrayBody(t, t->vm->types, Machine::IntType)) { if (objectClass(t, v) == arrayBody(t, t->vm->types, Machine::IntType)) {
pushInt(t, intValue(t, v)); pushInt(t, intValue(t, v));
} else if (objectClass(t, v)
== arrayBody(t, t->vm->types, Machine::StringType))
{
pushObject(t, v);
} else if (objectClass(t, v) } else if (objectClass(t, v)
== arrayBody(t, t->vm->types, Machine::FloatType)) == arrayBody(t, t->vm->types, Machine::FloatType))
{ {
pushInt(t, floatValue(t, v)); pushInt(t, floatValue(t, v));
} else if (objectClass(t, v)
== arrayBody(t, t->vm->types, Machine::StringType))
{
pushObject(t, v);
} else { } else {
abort(t); pushObject(t, resolveClass(t, v));
} }
} goto loop; } goto loop;
@ -2123,7 +2132,7 @@ run(Thread* t)
pokeInt(t, t->frame + FrameIpOffset, t->ip); pokeInt(t, t->frame + FrameIpOffset, t->ip);
for (; frame >= 0; frame = frameNext(t, frame)) { for (; frame >= 0; frame = frameNext(t, frame)) {
if (methodFlags(t, frameMethod(t, frame)) & ACC_NATIVE) { if (frame <= base) {
return 0; return 0;
} }
@ -2160,49 +2169,6 @@ run(Thread* t)
} }
} }
for (object e = exception; e; e = throwableCause(t, e)) {
if (e == exception) {
fprintf(stderr, "uncaught exception: ");
} else {
fprintf(stderr, "caused by: ");
}
fprintf(stderr, "%s", &byteArrayBody
(t, className(t, objectClass(t, exception)), 0));
if (throwableMessage(t, exception)) {
object m = throwableMessage(t, exception);
char message[stringLength(t, m) + 1];
stringChars(t, m, message);
fprintf(stderr, ": %s\n", message);
} else {
fprintf(stderr, "\n");
}
object trace = throwableTrace(t, e);
for (unsigned i = 0; i < arrayLength(t, trace); ++i) {
object e = arrayBody(t, trace, i);
const int8_t* class_ = &byteArrayBody
(t, className(t, methodClass(t, traceElementMethod(t, e))), 0);
const int8_t* method = &byteArrayBody
(t, methodName(t, traceElementMethod(t, e)), 0);
int line = lineNumber(t, traceElementMethod(t, e), traceElementIp(t, e));
fprintf(stderr, " at %s.%s ", class_, method);
switch (line) {
case NativeLine:
fprintf(stderr, "(native)\n");
break;
case UnknownLine:
fprintf(stderr, "(unknown line)\n");
break;
default:
fprintf(stderr, "(line %d)\n", line);
}
}
}
return 0; return 0;
} }
@ -2354,8 +2320,9 @@ invoke(Thread* t, object method)
if (LIKELY(t->exception == 0)) { if (LIKELY(t->exception == 0)) {
pushFrame(t, method); pushFrame(t, method);
result = ::run(t); result = ::run(t);
popFrame(t); if (LIKELY(t->exception == 0)) {
popFrame(t);
}
} }
} }
@ -2469,7 +2436,10 @@ run(System* system, Heap* heap, ClassFinder* classFinder,
::run(t, className, argc, argv); ::run(t, className, argc, argv);
int exitCode = 0; int exitCode = 0;
if (t->exception) exitCode = -1; if (t->exception) {
exitCode = -1;
printTrace(t, t->exception);
}
exit(t); exit(t);

View File

@ -139,9 +139,9 @@
(type throwable java/lang/Throwable (type throwable java/lang/Throwable
(extends jobject) (extends jobject)
(object message) (noassert object message)
(object trace) (noassert object trace)
(object cause)) (noassert object cause))
(type exception java/lang/Exception (type exception java/lang/Exception
(extends throwable)) (extends throwable))
@ -237,7 +237,7 @@
(type jreference java/lang/ref/Reference (type jreference java/lang/ref/Reference
(extends jobject) (extends jobject)
(void* next) (noassert void* next)
(void* target) (void* target)
(void* queue) (void* queue)
(object jnext)) (object jnext))