Trying to work newer indy into JRuby
Rémi Forax
forax at univ-mlv.fr
Mon May 18 14:18:17 PDT 2009
Charles Oliver Nutter a écrit :
> John Rose wrote:
>
>> The first two lines of GuardedRubyMethodHandle.invoke are your fast
>> path; that's where we need to get the maximum amount of inlining. The
>> JVM interpreter gets to those lines very quickly (without intervening
>> bytecodes) when it executes an invokedynamic instruction. Christian
>> Thalinger and I are working on making this true also in the compiled
>> code.
>>
>
> Ok...and I'll state it one more way just to be absolutely clear: I
> really, really want to avoid the situation that Cliff pointed out, and
> I'm worried about my Java-based MethodHandle getting in the way. I think
> I'm hearing that, but I obviously want to be certain :)
>
>
>> The call to entry.typeOk looks like it might be megamorphic; if so
>> that's a potential performance problem. There might be a way to
>> refactor this with method handles to avoid the megamorphism; that's
>> what guardWithTest is supposed to do. We'll get a better idea of what
>> to work on when we look at the disassemblies of compiled code, but
>> we'll need another round of compiler support to get this far.
>>
>
> typeOk is final/monomorphic and the methods it calls are all
> final/monomorphic. Here they are:
>
> http://gist.github.com/113687
>
> This is the token check I told you about previously. So far we've been
> able to guarantee that the token gets flipped if any related change
> event fires, so this should be ok.
>
>
>> The expression entry.method.call might also have a megamorphism (your
>> nemesis, of course). I think it wants to be entry.mh.invoke, or even
>> ((MethodHandle)entry).invoke, where entry is a JMH.
>>
>
> It most certainly is! There are several types of method (DynamicMethod,
> see the CacheEntry code above), encapsulating interpreter logic, wrapped
> methods (aliases) pre-compiled methods, and jit-compiled methods. And
> even if it's all the same type, we generate our own "handles" specific
> to the target method in many cases, in order to keep as much of the call
> path monomorphic as possible.
>
> In a totally free world, what I'd expect to do would be to have a
> generated MethodHandle for every method as well, with code that would
> only ever dispatch to that one DynamicMethod. Obviously that's
> infeasible, so I really need to work with you all to find a way to
> include our guard logic and invoke the eventual Ruby method objects, be
> they interpreted, compiled, or otherwise, and still get things to inline
> straight through.
>
> Now the simple way I thought to do this was to simply have our existing
> DynamicMethod supertype extend JavaMethodHandle. Is the implication that
> if we have all MHs straight from the call site to the target body of
> code, it can inline?
>
>
>> Minor nits: I suggest making bootstrap in registerBootstrap be a
>> private static final like DEFAULT. And you might consider naming
>> those statics after their methods (modulo Java naming conventions):
>> BOOTSTRAP, INVOKE.
>>
>
> Sure, good cleanup tips. I will spend some time the rest of the day
> wiring up the other-arity call paths, probably as individual
> GuardedMethodHandle subtypes (yes?) with their own invoke signatures.
>
I don't think you need different subtypes.
A JavaMethodHandle takes a MethodHandle as parameters so
you can have more than one variant of invoke() in GuardedMethodHandle
and select the good one depending on the type() of the CallSite.
> I must also remark how similar this feels to LLVM's method invocation
> APIs, where they toss "function" objects into the IR and it just
> optimizes the calling logic. It seems to me that the new indy stuff
> could be the underpinnings of a "JVM-LLVM" API that represents basic
> blocks as concrete code bodies and transitions as method handle
> invocations...
>
> - Charlie
>
Rémi
More information about the mlvm-dev
mailing list