Tuesday, May 27, 2008

jSuneido - implementing classes and methods

Reading Headius: The Power of the JVM got me thinking about how to implement Suneido classes and methods on the JVM.

Suneido is a little easier to implement in this respect than more dynamic languages. Suneido's classes are more like Java classes - defined in a single source unit and not modifiable at runtime. Unlike Ruby you can't add methods dynamically.

It sounds like one of the keys to performance might be call site caching of method lookup. What this means is that after you've done the method lookup you cache the result at the call site. Next time you just call the cached method. Of course, the cached method is only valid if the receiver is the same class as when you cached it. If the value class is different you have to fall back to the method lookup. But in practice it's a worthwhile optimization, and not too complex to use. It's an old idea that's been around since early Smalltalk days.

One way to implement this is would be to compile each call to something like:

if (cache == null || cache.class != receiver.class)
cache = receiver.method_lookup(...)
cache.call(...)

One of the problems is that there's no "good" way to reference a method. I think that's one of the reasons why jRuby compiles each Ruby method to a Java class - so it can use a class reference as a method reference.

One of the features being considered in JSR292 (JVM improvements for dynamic languages) is method "handles" which would avoid having to compile each method into a separate class.

Another JSR292 feature is "dynamic invoke". This would move some of this mechanism into the JVM. And "anonymous" classes will help as well.

I'm still trying to figure out what's possible/practical/reasonable with the JVM. Unfortunately, there's not a lot of documentation at this level. It would be nice to know more about how other JVM languages like jRuby and Groovy are implemented, but there doesn't seem to be much out there. I guess I could try to figure it out from their source code but I bet that wouldn't be easy.

One feature I think I should investigate is the Java Proxy system. It sounds like this is used by Scala (another JVM language). Apparently it doesn't work for native type arguments but I don't think that's a problem for Suneido.

Meanwhile I'm plugging away at porting the code. The record and memory mapped file code now seems to be working (at least at a basic level).

PS. I'm writing this (and checking code into Subversion) from the Vancouver airport on my way to RailsConf in Portland. Gotta love free wireless internet!

No comments: