On May 27, 2011, at 8:04 AM, Charles Oliver Nutter wrote:

> There's substantially more code here. I don't see any jumps that would
> short-circuit this logic. Am I reading right?
> 
> Now the good news is that after the test is completed I don't see much
> additional logic on MLVM before it's back into the inlined recursive
> call. Both versions inline a single level of fib_ruby recursion and
> then callq the next level of recursion.
> 
> So what's up with that logic leading up to test? I assume that's the
> new GWT logic, but am I getting that it's a lot more heavyweight than
> the old version? Or is some intermediate handle doing extra work?

OK, I think I understand the source of the sand in the gears.

It's not GWT.  It's an intermediate handle.  Those extra checks are checkcasts 
introduced by code like this:

   static void doSomeRubyThing(org.jruby.runtime.builtin.IRubyObject x) { ... }
   MethodHandle doSomeRubyThing = lookup().lookupStatic(..., 
methodType(void.class, IRubyObject.class));
   MethodHandle gwrap = 
doSomeRubyThing.asType(doSomeRubyThing.type().generic());
   Object x = gwrap.invokeExact((Object)y);

The invokeExact call takes an undifferentiated Object and casts it to 
IRubyObject before jumping into doSomeRubyThing.  (It will also wait until the 
thing returns void and make a null to push toward x.)

Until recently, we specified that interface conversions in asType were no-ops.  
As you know, this is type-safe, and reflects the behavior of the JVM's 
verifier.  But it does not reflect the rules of the Java language.  The EG 
decided this was too surprising, so we made asType compatible with the Java 
language.  This means you get lots of redundant "x instanceof IRubyObject" 
code.  It adds no value.  It is also poorly optimized (note the redundant tests 
in your sample code!).

The cure is simple:  Get rid of the interface casts implied by your uses of 
asType.  To do this, use MHs.explicitCastArguments, which does the more 
performance-friendly no-op retyping of interfaces.  If you need to cast some 
arguments and safely widen others, do it in two steps:  Pick a middle type that 
adjusts the interface arguments to Object, explicitCastArguments to that middle 
type, and then use asType the rest of the way.  (The other order will work too. 
 Don't know if there's a performance difference, but if there is I suspect the 
best order is eCA first them asType to finish.)

How badly does this bollix up your carefully constructed code?

Suggestion:  Write an "eraseInterfaces(mh)" operator which will edit all the 
interfaces in mh.type(), and explicitCA to the edited type.  The result can 
then be asTyped, and you'll get (I hope) much more similar machine code.

-- John

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

Reply via email to