diff --git a/classpath/avian/Callback.java b/classpath/avian/Callback.java new file mode 100644 index 0000000000..25889f3b2c --- /dev/null +++ b/classpath/avian/Callback.java @@ -0,0 +1,16 @@ +/* Copyright (c) 2009, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public interface Callback { + public void handleResult(T result); + public void handleException(Throwable exception); +} diff --git a/classpath/avian/CallbackReceiver.java b/classpath/avian/CallbackReceiver.java new file mode 100644 index 0000000000..c36b1416bd --- /dev/null +++ b/classpath/avian/CallbackReceiver.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2009, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public interface CallbackReceiver { + public T receive(Callback callback) throws Exception; +} diff --git a/classpath/avian/Continuations.java b/classpath/avian/Continuations.java new file mode 100644 index 0000000000..948b8b0bec --- /dev/null +++ b/classpath/avian/Continuations.java @@ -0,0 +1,27 @@ +/* Copyright (c) 2009, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +import java.util.concurrent.Callable; + +public abstract class Continuations { + public static native T callWithCurrentContinuation + (CallbackReceiver receiver) throws Exception; + + public static native T dynamicWind(Runnable before, + Callable thunk, + Runnable after) throws Exception; + + private static class Continuation implements Callback { + public native void handleResult(T result); + public native void handleException(Throwable exception); + } +} diff --git a/classpath/java/util/concurrent/Callable.java b/classpath/java/util/concurrent/Callable.java new file mode 100644 index 0000000000..f0ad3be39e --- /dev/null +++ b/classpath/java/util/concurrent/Callable.java @@ -0,0 +1,15 @@ +/* Copyright (c) 2009, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package java.util.concurrent; + +public interface Callable { + public T call() throws Exception; +} diff --git a/src/builtin.cpp b/src/builtin.cpp index cf48ee58ef..9d45707a94 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -847,3 +847,38 @@ Java_java_net_URL_00024ResourceInputStream_close(Thread*, jclass, jlong peer) { reinterpret_cast(peer)->dispose(); } + +extern "C" JNIEXPORT void JNICALL +Avian_avian_Continuations_callWithCurrentContinuation(Thread* t, + object, + uintptr_t* arguments) +{ + t->m->processor->callWithCurrentContinuation + (t, reinterpret_cast(*arguments)); + + abort(t); +} + +extern "C" JNIEXPORT void JNICALL +Avian_avian_Continuation_handleResult(Thread* t, + object, + uintptr_t* arguments) +{ + t->m->processor->feedResultToContinuation + (t, reinterpret_cast(arguments[0]), + reinterpret_cast(arguments[1])); + + abort(t); +} + +extern "C" JNIEXPORT void JNICALL +Avian_avian_Continuation_handleException(Thread* t, + object, + uintptr_t* arguments) +{ + t->m->processor->feedExceptionToContinuation + (t, reinterpret_cast(arguments[0]), + reinterpret_cast(arguments[1])); + + abort(t); +} diff --git a/src/compile.cpp b/src/compile.cpp index 13ad7ee73b..b142d23bd3 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -5553,6 +5553,7 @@ class MyProcessor: public Processor { objectPools(0), staticTableArray(0), virtualThunks(0), + receiveMethod(0), codeAllocator(s, 0, 0) { } @@ -5952,33 +5953,52 @@ class MyProcessor: public Processor { (t->m->system->handleSegFault(&segFaultHandler))); } - virtual void callWithCurrentContinuation(Thread* vmt, object method, - object this_) - { + virtual void callWithCurrentContinuation(Thread* vmt, object receiver) { MyThread* t = static_cast(vmt); + object method; object continuation; void* base; void* stack; - { PROTECT(t, method); - PROTECT(t, this_); + { PROTECT(t, receiver); - compile(t, ::codeAllocator(t), 0, method); + if (receiveMethod == 0) { + const char* const className = "avian/CallbackReceiver"; + const char* const methodName = "receive"; + const char* const methodSpec = "(Lavian/Callback;)Ljava/lang/Object;"; + + receiveMethod = resolveMethod(t, className, methodName, methodSpec); + + if (receiveMethod == 0) { + object message = makeString + (t, "%s %s not found in %s", methodName, methodSpec, className); + t->exception = makeNoSuchMethodError(t, message); + } + } if (LIKELY(t->exception == 0)) { - void* ip; - continuation = makeCurrentContinuation(t, &ip, &base, &stack); + method = findInterfaceMethod + (t, receiveMethod, objectClass(t, receiver)); + PROTECT(t, method); + + compile(t, ::codeAllocator(t), 0, method); + if (LIKELY(t->exception == 0)) { + void* ip; + continuation = makeCurrentContinuation(t, &ip, &base, &stack); + } } } if (LIKELY(t->exception == 0)) { - callWithContinuation(t, method, this_, continuation, base, stack); + callWithContinuation(t, method, receiver, continuation, base, stack); + } else { + unwind(t); } } - virtual void callContinuation(Thread* vmt, object continuation, - object result) + virtual void feedResultToContinuation(Thread* vmt, object continuation, + object result) { MyThread* t = static_cast(vmt); @@ -5997,6 +6017,30 @@ class MyProcessor: public Processor { vmJump(ip, base, stack, t, reinterpret_cast(result), 0); } + virtual void feedExceptionToContinuation(Thread* vmt, object continuation, + object exception) + { + MyThread* t = static_cast(vmt); + + assert(t, t->exception == 0); + + void* ip; + void* base; + void* stack; + findUnwindTarget(t, &ip, &base, &stack); + + t->trace->nativeMethod = 0; + t->trace->targetMethod = 0; + + t->continuation = continuation; + + t->exception = exception; + + findUnwindTarget(t, &ip, &base, &stack); + + vmJump(ip, base, stack, t, 0, 0); + } + virtual void walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start) { @@ -6018,6 +6062,7 @@ class MyProcessor: public Processor { object objectPools; object staticTableArray; object virtualThunks; + object receiveMethod; SegFaultHandler segFaultHandler; FixedAllocator codeAllocator; }; diff --git a/src/processor.h b/src/processor.h index a24a6197d0..7777953580 100644 --- a/src/processor.h +++ b/src/processor.h @@ -134,10 +134,14 @@ class Processor { boot(Thread* t, BootImage* image) = 0; virtual void - callWithCurrentContinuation(Thread* t, object method, object this_) = 0; + callWithCurrentContinuation(Thread* t, object receiver) = 0; virtual void - callContinuation(Thread* t, object continuation, object result) = 0; + feedResultToContinuation(Thread* t, object continuation, object result) = 0; + + virtual void + feedExceptionToContinuation(Thread* t, object continuation, + object exception) = 0; virtual void walkContinuationBody(Thread* t, Heap::Walker* w, object o, unsigned start) diff --git a/src/type-generator.cpp b/src/type-generator.cpp index fbb0db7452..a98c046531 100644 --- a/src/type-generator.cpp +++ b/src/type-generator.cpp @@ -1323,12 +1323,6 @@ parseJavaClass(Object* type, Stream* s, Object* declarations) } } - if (equal(typeJavaName(type), "java/lang/Class")) { - // add inline vtable - addMember(type, Array::make - (type, 0, "void*", "vtable", sizeOf("void*", 0))); - } - if (typeSuper(type)) { for (Object* p = typeMethods(typeSuper(type)); p; p = cdr(p)) { addMethod(type, car(p)); @@ -1372,23 +1366,25 @@ parseType(Object::ObjectType type, Object* p, Object* declarations, Type* t = Type::make(type, name, javaName); - if (javaName and *javaName != '[') { - assert(cdr(p) == 0); + bool isJavaType = javaName and *javaName != '['; + if (isJavaType) { const char* file = append(javaClassDirectory, "/", javaName, ".class"); Stream s(fopen(file, "rb"), true); parseJavaClass(t, &s, declarations); - } else { - for (p = cdr(p); p; p = cdr(p)) { - if (type == Object::Type) { - parseSubdeclaration(t, car(p), declarations); - } else { - Object* member = parseMember(t, car(p), declarations); - assert(member->type == Object::Scalar); - addMember(t, member); - } - } + } + for (p = cdr(p); p; p = cdr(p)) { + if (type == Object::Type) { + parseSubdeclaration(t, car(p), declarations); + } else { + Object* member = parseMember(t, car(p), declarations); + assert(member->type == Object::Scalar); + addMember(t, member); + } + } + + if (not isJavaType) { if (type == Object::Type and typeSuper(t)) { for (Object* p = typeMethods(typeSuper(t)); p; p = cdr(p)) { addMethod(t, car(p)); diff --git a/src/types.def b/src/types.def index c242a9b86c..9039dde46f 100644 --- a/src/types.def +++ b/src/types.def @@ -1,6 +1,7 @@ (type jobject java/lang/Object) -(type class java/lang/Class) +(type class java/lang/Class + (array void* vtable)) (type singleton (array uintptr_t body)) @@ -103,7 +104,7 @@ (type array (noassert array object body)) -(type continuation +(type continuation avian/Continuations$Continuation (object next) (object method) (void* address) @@ -111,6 +112,8 @@ (uintptr_t framePointerOffset) (array uintptr_t body)) +(type callbackReceiver avian/CallbackReceiver) + (type string java/lang/String) (type thread java/lang/Thread)