On Sat, Jan 9, 2010 at 12:28 AM, Axel Rauschmayer axel@rauschma.de wrote:
I hope this is not a stupid question, but: Why does jcall use reflection?
Doesn't ABCL compile lisp to byte code? If one could statically declare to the compiler the intended Java class, couldn't method invocations be compiled instead of being performed via reflection?
OTOH, I don't know how ABCL handles interpretation versus compilation, so that might be an issue.
I had a talk today with Erik about this topic, so I suppose I'm informed enough to speak ;)
To make it short: reflection could be eliminated in some cases, but it's quite costly in terms of development effort.
The long explanation: there are several reasons. Keep in mind that ABCL has both an interpreter and a compiler.
- In interpreted code, reflection is the only possibility. - In compiled code: - some method invocations through jcall cannot be resolved at compile time - extreme example: (jcall (read) nil). - others could be resolved. How many depends on the effort we can put into the compiler: it could recognize only calls to a method which literally appears in source code - (jcall (jmethod "foo" "bar") baz) - or, by doing type inference, more cases could be discovered. The compiler currently does nothing in that regard, except caching the method metaobjects per call-site when possible. So in the foo-bar-baz example above, method "bar" of class "foo" is only resolved once, at load time, and then reused - for that particular call site.
It is dubious whether enhancing the compiler to eliminate reflection for some jcall invocations would be worth the effort. Since Java objects are boxed in ABCL, the compiler would need to generate code to unbox the arguments and box the return value, and place appropriate exception handlers. This would likely increase the size and complexity of the generated code quite a lot. Also, I believe that to optimize a significant number of jcall invocations we need type inference, and that's not an easy task. Of course, the implementation of jcall has to do the very same boxing/unboxing, besides the reflective call itself; it is inevitably less efficient. But I think that, unless your code is made mostly of calls to Java methods, the difference is tolerable.
hth, Alessio