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 _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev