Thursday, September 17, 2009

Unconstructable Token Spotted at JVM Language Summit

I've been attending the JVM Language Summit at Sun's campus in Santa Clara, not because I'm implementing a programming language on the JVM, but in my capacity as programming-language-junkie-at-large. The big fuss this year is over the invokedynamic bytecode instruction, which (unlike the other ways Java bytecode provides for invoking a method) can be retargeted at runtime.

This is (at least potentially) a great efficiency gain for implementors of dynamically dispatched languages. Such languages choose the target of a method invocation based on the runtime rather than the compiletime types of their arguments (or even on the arguments' values), and may choose methods to invoke based on method arguments other than the first (the receiver). Often they also let you modify an object's class at runtime to add or remove methods, which requires a dispatch algorithm that not only differs from Java's, but that can change over time.

The infrastructure around invokedynamic is the java.dyn package proposed for Java 7. Since I hadn't been paying much attention to invokedynamic, it took me all day yesterday to wrap my head around the magic that not only allows it to work, but often to do so very efficiently (if you're lucky enough to have the JVM inline everything that it could).

That magic derives from two sources:
  • MethodHandles, which, in their simplest form, are direct references to method bodies, and which the JVM is smart enough to inline; and
  • MethodHandles.guardWithTest, which composes a new MethdHandle from a test and two alternatives, the result of which the JVM is also smart enough to inline.

In effect, at each call site, you can inline a bunch of code (which you can change later, if you need to) that chooses an invocation target. This code will often look as if it's making a choice based on the runtime types of the method arguments originally given, but in practice, if enough gets inlined, those types will be known to the JVM when it's compiling your target-choosing code—so that the target is known at compiletime, meaning no invocation overhead at all if the target is also inlined.

Ever so sweet, if the JVM is aggressive enough about inlining. Which it sometimes isn't, but that's another topic, perhaps best left to people who know more about how the inlining decisions are made.

Anyway, what I really meant this post to be about was a spotting of the Unconstructable Token pattern in the java.dyn API, specifically in the MethodHandle constructor: this constructor is protected, because you may need to make language-specific subclasses of MethodHandle to keep track of whatever your language needs to keep track of—but you obviously can't let people construct a method handle just anywhere. Hence the Magic Token argument (currently of type sun.dyn.Access, but I assume they'll change the name to something less Sun-specific before release), which ensures that only The Authorities can can create a method handle.

I hadn't originally thought of Unconstructable Token in terms of restricting where user-supplied subclasses of framework classes can be allocated, but this is a fine use of it, and Java modules will do nothing to make this use of the pattern obsolete.

No comments:

Post a Comment