Small static method marked not entrant, inlining reversed?
Tom Rodriguez
tom.rodriguez at oracle.com
Tue Sep 7 17:04:43 PDT 2010
Did you run with -XX:+PrintInlining? That will report why we didn't inline.
tom
On Sep 7, 2010, at 2:44 PM, Charles Oliver Nutter wrote:
> I've been working on JRuby performance lately and ran into a peculiar situation.
>
> I have a static utility method in JRuby that checks whether a given
> object's class is the same as the when the compiler optimized it. So
> for a snippit of code like this:
>
> def foo
> bar
> end
>
> def bar
> # whatever
> end
>
> After running for some time, the "foo" call will be compiled, the
> compiler will see that the "bar" call has a cached method handle, and
> it will emit both a dynamic call and a static-typed call plus guard.
> The static-typed call looks like this:
>
> ALOAD 8
> LDC 446
> INVOKESTATIC
> org/jruby/javasupport/util/RuntimeHelpers.isGenerationEqual
> (Lorg/jruby/runtime/builtin/IRubyObject;I)Z
> IFNE L2
> ALOAD 8
> CHECKCAST org/jruby/RubyFixnum
> ALOAD 1
> LDC 1
> INVOKEVIRTUAL org/jruby/RubyFixnum.op_plus
> (Lorg/jruby/runtime/ThreadContext;J)Lorg/jruby/runtime/builtin/IRubyObject;
>
> And the isGenerationEqual method looks like this:
>
> public static boolean isGenerationEqual(IRubyObject object, int
> generation) {
> return object.getMetaClass().getCacheToken() == generation;
> }
>
> While running benchmarks, I noticed a peculiar thing happening. For
> "fib", the method JITs in JRuby very quickly and is soon after JITed
> by Hotspot. But later compiles cause "fib" to get deoptimized and
> marked not-entrant. Around the same time, isGenerationEqual gets
> marked not entrant. Unfortunately, when fib re-optimizes, it does so
> without inlining the isGenerationEqual call, and I can see that where
> it was inlined before, it now actually does a CALL in assembly.
>
> Manually inlining the same bytecode everywhere isGenerationEqual would
> be called does not seem to be subject to the same effect.
>
> Any thoughts? The only theory I have is that early in optimization
> Hotspot sees that the target object type (IRubyObject object in the
> method def) is the same, and so it optimizes based on that. Later, as
> other compiled methods start to hit this code, the tyoe of "object"
> changes. But the logic behind the scenes should be identical in every
> case... IRubyObject.getMetaClass() only has one final implementation
> on org.jruby.RubyBasicObject, and getCacheToken() has only one final
> implementation on org.jruby.RubyModule, which simply returns an int
> field.
>
> So I'm stumped why at least isGenerationEqual would not inline in all cases.
>
> - Charlie
More information about the hotspot-compiler-dev
mailing list