For Ashlar, I represent my closures as MethodHandle instances. (I
actually represent pretty much everything as MethodHandle instances at
this point, but that's a conversation for another time.)  Since I'm
statically typed, there's some work I can do at compile time in
certain cases (recognizing Pervasive#each calls and turning them into
loops, for instance). But let's set that aside and focus on runtime
optimizations.

Now, there's no way that I am aware of to go from a MethodHandle to a
java.lang.reflect.Method instance and an array of arguments, which
would then enable me to inline it at runtime. There are good reasons I
can imagine for not allowing that, starting first and foremost with
argument adapters (and pretty much all the mutations in the
MethodHandles class), which means that the MethodHandle has semantics
different from passing the given arguments to the given method.

So, if we're going to inline based on the MethodHandle, we need some
kind of wrapper which will tell us whether the MethodHandle is
inlinable, and which will tell us the method and arguments if it is
reversible. Note that the method and arguments need not correspond
directly to the underlying implementation—in theory, we could generate
some other code at runtime to represent adapters, etc. But for the
initial implementation, I'm considering a MethodHandle inlinable if it
corresponds directly to an API method, possibly with currying. That
solves half the problem: I can now go from MethodHandle to a
java.lang.reflect.Method, which allows me to inline it at runtime (at
least in the common case).

The other half the problem is the call site. I use a custom CallSite
which exposes MethodHandle#invokeGeneric so that it can track
arguments passed in. I'd use that to track MethodHandle arguments
passed in, and if the same inlinable MethodHandle is hit often enough,
it should generate the inlined code, and then update the MethodHandle
to check for this common case (MethodHandles#guardWithTest comes in
here). This is pretty much exactly the logic I would hope a JVM would
eventually implement, and I'm presuming that the JVM already has (or
will soon have) the ability to optimize the MethodHandle resulting
from MethodHandles#guardWithTest calls.

Now, this is a fair bit of infrastructure and additional obscuring of
the user's code path, which is where the question comes in about
whether or not it is worth it. There are also serious concurrency
issues: how do we balance performance with shared state? For instance,
consider the implied counter for MethodHandle arguments—do we really
want the overhead of synchronization on *every* invocation of this
method? Imagining a global lock on "fold" just makes me blanch. We
could go "volatile" and force memory flushes in all those cases, but
is that really better? What's the alternative? (Taking the overhead
and the loss of opportunities to track it per-thread? Is that really
better?) I'm hesitant to spend time implementing an optimization that
isn't (developing my language is a hobby, not my job, so there's very
limited time resources), but if the gain is huge, it's probably worth
it.

Of course, I'd really like to declare it's the JVM's problem and look
forward longingly to the day when it's resolved there.

~~ Robert.

On Sat, Apr 2, 2011 at 8:35 PM, Charles Oliver Nutter
<[email protected]> wrote:
> On Sat, Apr 2, 2011 at 7:34 PM, Charles Oliver Nutter
> <[email protected]> wrote:
>> I also want to make clear this affects all languages that pass
>> functions or closure around, including Groovy, JRuby, Scala, Clojure,
>> current Java with callbacks/anon classes, and upcoming Java 7 closure
>> support.
>
> Sent this a bit quickly...
>
> This may actually be a case where JRuby has a better chance of
> optimizing since we are already mixed-mode. It won't be very difficult
> for us to specialize a body of code to the point of use, allowing that
> body and a closure passed to it to inline. Assuming that's not
> possible for other languages, has anyone thought of other ways to make
> closures/callbacks optimize as well as normal inlined monomophic call
> paths?
>
> - Charlie
>
> --
> You received this message because you are subscribed to the Google Groups 
> "JVM Languages" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to 
> [email protected].
> For more options, visit this group at 
> http://groups.google.com/group/jvm-languages?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups "JVM 
Languages" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/jvm-languages?hl=en.

Reply via email to