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