Crash from "recursive" method handle chain

Tom Rodriguez tom.rodriguez at oracle.com
Wed Jul 27 14:27:08 PDT 2011


On Jul 27, 2011, at 2:50 AM, Charles Oliver Nutter wrote:

> I'm getting back into invokedynamic stuff (in between
> conferencing...whew!). Perf reports are coming soon, but in the
> interim....
> 
> I was playing with implementing "loops" using the trick Ola showed me
> of binding a call site in the chain and having it circle back to the
> top. Fun, cute, etc.
> 
> https://gist.github.com/1109021
> 
> (might be interesting for cookbook?)
> 
> However I realized while implementing it that it kinda blurs the lines
> between recursive and iterative. Logically, the rebound call site
> should act like a backward branch to another iteration. That's what

should is a little strong.  The current implementation of selectAlternative operates in a frameless way but the old implementation did not so this is very clearly recursion when run against that implementation.  Running your example against b143 gives this:

Exception in thread "main" java.lang.StackOverflowError
        at java.lang.Long.valueOf(Long.java:573)
        at sun.invoke.util.ValueConversions.boxLong(ValueConversions.java:248)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        at java.lang.invoke.MethodHandleImpl$GuardWithTest.invoke_L2(MethodHandleImpl.java:929)
        ....

Presumably that's a valid implementation of selectAlternative which seems to disallow these kinds of shenanigans at least until Java requires tail call elimination.

Running against b147 also gives StackOverflowError, at least sometimes, but it's more mysterious:

/java/re/jdk/1.7.0/promoted/all/b147/binaries/solaris-amd64/fastdebug/bin/java -server -XX:+PrintCompilation -Xint IndyLoop
Exception in thread "main" java.lang.StackOverflowError
        at IndyLoop.add(IndyLoop.java:64)
        at IndyLoop.main(IndyLoop.java:13)

In this case I believe that we're running out space in the frame because of how we are doing the argument swizzling for MH chains.  We often do expansion without cleaning up since we assume the amount of expansion is bounded.  Making a loop greatly extends the amount of expansion.  I believe the crashes are caused by this happening in I2C adapter code which isn't prepared to deal with the overflow.  In general it appears that the adapter code needs some stack overflow checking.  It may also need fixes to keep from over expanding the argument area.  That might allow this to run to completion in interpreted mode but compiles are a different story.

> I'd expect to happen if everything compiles and inlines together; the
> MH chain would see that the call site is bound to an
> already-encountered handle higher up in the chain and treat it as a
> branching operation.

The compile could conceivably do something like this but it certainly doesn't right now.  It also seems pretty far outside the design center of 292 to make it behave like this, or at least the spec should give some guidance on whether method handle cycles are required to behave as you describe.  Anyway, John would probably have the last word here.  I'm really just talking about what happens as opposed to what should happen.

Also note that this loop will never get compiled in a normal fashion since there are no invocation counters on method handles.

I filed 7071915 for this since we shouldn't simply crash, though a StackOverflowError seems permissible to me.

tom

> 
> It does seem to work fine for low values, but for high values I got a
> crash (on openjdk-osx-build probably equivalent to b146 or *maybe*
> b147): "Illegal instruction"
> 
> Here's the full session. What sayeth ye all?
> 
> https://gist.github.com/1109026
> 
> I've pushed the code here:
> 
> https://github.com/headius/indy-examples
> 
> - Charlie
> _______________________________________________
> mlvm-dev mailing list
> mlvm-dev at openjdk.java.net
> http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev



More information about the mlvm-dev mailing list