Busy week, finally circling back to this thread...

On Wed, Feb 25, 2015 at 8:29 PM, John Rose <john.r.r...@oracle.com> wrote:
>> * A loop handle :-)
>>
>> Given a body and a test, run the body until the test is false. I'm
>> guessing there's a good reason we don't have this already.
>
> A few reasons:   1. You can code your own easily.

I can't code one that will specialize for every call path, though,
unless I generate a new loop body for every call path.

> 2. There's no One True Loop the way there is a One True If.
> The "run until test is false" model assumes all the real work is
> done with side-effects, which are off-center from the MH model.

This I can appreciate. My mental model of MHs started to trend toward
a general-purpose IR, and I believe if I had some sort of backward
branch it could be that. But I understand if that's the wrong
conceptual model, and I realize now that MHs are basically call stack
adapters with a bit of forward branching thrown in.

It does feel like there's a need for better representation of
branch-joining or phi or whatever you want to call it, though.

> 3. A really clean looping mechanism probably needs a sprinkle
> of tail call optimization.
>
> I'm not saying that loops should never have side effects, but I
> am saying that a loop mechanism should not mandate them.
>
> Maybe this is general enough:
>
>     MHs.loop(init, predicate, body)(*a)
>     => { let i = init(*a); while (predicate(i, *a)) { i = body(i, *a); } 
> return i; }
>
> ...where the type of i depends on init, and if init returns void then you
> have a classic side-effect-only loop.

Ahh yes, this makes sense. If it were unrolled, it would simply be a
series of folds and drops as each iteration through the body modified
the condition in some way. So then we just need it to work without
unrolling.

My silly use case for this would be to emit simple expressions
entirely as a MH chain, so we'd get the benefit of MH optimizations
without generating our own bytecode (and with forced inlining and
perhaps a richer semantic representation than just bytecode). It's not
a very compelling case, of course, since I could just emit bytecode
too.

>> * try/finally as a core atom of MethodHandles API.
>>
>> Libraries like invokebinder provide a shortcut API To generating the
>> large tree of handles needed for try/finally, but the JVM may not be
>> able to optimize that tree as well as a purpose-built adapter.
>
> I agree there.  We should put this in.
>
>    MHs.tryFinally(target, cleanup)(*a)
>      => { try { return target(*a); } finally { cleanup(*a); } }
>
> (Even here there are non-universalities; what if the cleanup
> wants to see the return value and/or the thrown exception?
> Should it take those as one or two leading arguments?)

In InvokeBinder, the finally is expected to require no additional
arguments compared to the try body, since that was the use case I
needed. You bring up a good point...and perhaps the built-in JSR292
tryFinally should take *two* handles: one for the exceptional path
(with exception in hand) and one for the non-exceptional path (with
return value in hand)? The exceptional path would be expected to
return the same type as the try body or re-raise the exception. The
non-exceptional path would be expected to return void.

> We now have MHs.collectArguments.  Do you want MHs.spreadArguments
> to reverse the effect?  Or is there something else I'm missing?

I want to be able to group arguments at any position in the argument
list. Example:

Incoming signature: (String foo, int a1, int a2, int a3, Object obj)
Target signature: (String foo, int[] as, Object obj)

... without permuting arguments

> Idea of the day:  An ASM-like library for method handles.
> Make a MethodHandleReader which can run a visitor over the MH.
> The ops of the visitor would be a selection of public MH operations
> like filter, collect, spread, lookup, etc.
> Also ASM-like, the library would have a MethodHandleWriter
> would could be hooked up with the reader to make filters.

That would certainly cover it! I'd expect this to add:

* MethodHandleVisitor interface of some kind
* MethodHandle#accept(MethodHandleVisitor) or similar
* MethodHandleType enum with all the base MH types (so we're not
forcing all types into a static interface).

- Charlie
_______________________________________________
mlvm-dev mailing list
mlvm-dev@openjdk.java.net
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev

Reply via email to