Inlining heuristic trouble
Christian Thalinger
christian.thalinger at oracle.com
Fri Jun 17 01:58:14 PDT 2011
On Jun 15, 2011, at 5:26 PM, Rémi Forax wrote:
> // with the optimization
> [forax at localhost binary-operation]$ time java -cp .:classes PerfOpt
> real 0m0.954s
> user 0m1.030s
> sys 0m0.087s
>
> // without
> [forax at localhost binary-operation]$ time java -cp .:classes Perf
> real 0m0.378s
> user 0m0.407s
> sys 0m0.081s
>
> Knowing that the double xor trick does 4 comparisons and
> the constant trick only two, the problem comes from either
> my code or the way the VM inlines the method handles.
>
> I've found no problem in my code so ... :)
> Playing with the VM logs, the method containing (j != MAXINT) is not inlined
> because it hits the maximum depth (as far as I remember this problem
> is new, the older algorithm, the one that didn't propagate MDO, didn't
> exhibit this problem).
I fixed a small bug in printing the inlining tree with nested MHs (we're getting flat trees in this case). Anyway, the inlining for PerfOpt looks actually good. Here are the inlining trees of Perf and PerfOpt:
888 1 % Perf::main @ 17 (47 bytes)
@ 19 Perf::less (50 bytes) already compiled into a big method
@ 27 java.lang.Integer::valueOf (54 bytes) inline (hot)
@ 30 java.lang.invoke.MethodHandle::invokeExact (8 bytes) inline (hot)
@ 4 java.lang.invoke.MethodHandleImpl$GuardWithTest::invoke_L2 (32 bytes) inline (hot)
@ 6 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot)
@ 1 jsr292.cookbook.binop.RT::integerCheck (16 bytes) inline (hot)
@ 1 java.lang.Object::getClass (0 bytes) (intrinsic)
@ 18 java.lang.invoke.MethodHandle::invokeExact (8 bytes) inline (hot)
@ 4 java.lang.invoke.MethodHandleImpl$GuardWithTest::invoke_L2 (32 bytes) inline (hot)
@ 6 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot)
@ 1 jsr292.cookbook.binop.RT::integerCheck (16 bytes) inline (hot)
@ 1 java.lang.Object::getClass (0 bytes) (intrinsic)
@ 18 java.lang.invoke.MethodHandle::invokeExact (57 bytes) inline (hot)
@ 31 java.lang.Integer::intValue (5 bytes) inline (hot)
@ 44 java.lang.Integer::intValue (5 bytes) inline (hot)
@ 53 jsr292.cookbook.binop.RT::safeAdd (35 bytes) inline (hot)
@ 18 java.math.BigInteger::valueOf (62 bytes) already compiled into a medium method
@ 23 java.math.BigInteger::valueOf (62 bytes) already compiled into a medium method
@ 26 java.math.BigInteger::add (123 bytes) too big
@ 31 java.lang.Integer::valueOf (54 bytes) inline (hot)
@ 50 java.lang.Integer::<init> (10 bytes) inline (hot)
@ 1 java.lang.Number::<init> (5 bytes) inline (hot)
@ 1 java.lang.Object::<init> (1 bytes) inline (hot)
@ 19 Perf::less (50 bytes) already compiled into a big method
854 1 % PerfOpt::main @ 17 (43 bytes)
@ 19 PerfOpt::less (50 bytes) already compiled into a big method
@ 26 java.lang.invoke.MethodHandle::invokeExact (7 bytes) inline (hot)
@ 3 java.lang.invoke.MethodHandleImpl$GuardWithTest::invoke_L1 (29 bytes) inline (hot)
@ 5 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot)
@ 1 jsr292.cookbook.binop.RT::integerCheck (16 bytes) inline (hot)
@ 1 java.lang.Object::getClass (0 bytes) (intrinsic)
@ 16 java.lang.invoke.MethodHandle::invokeExact (84 bytes) inline (hot)
@ 11 java.lang.Integer::intValue (5 bytes) inline (hot)
@ 20 java.lang.invoke.MethodHandle::invokeExact (5 bytes) inline (hot)
@ 1 jsr292.cookbook.binop.RT::maxIntCheck (12 bytes) inline (hot)
@ 27 java.lang.Integer::valueOf (54 bytes) inline (hot)
@ 50 java.lang.Integer::<init> (10 bytes) inline (hot)
@ 1 java.lang.Number::<init> (5 bytes) inline (hot)
@ 1 java.lang.Object::<init> (1 bytes) inline (hot)
@ 34 java.lang.Boolean::valueOf (14 bytes) inline (hot)
@ 43 java.lang.invoke.MethodHandle::invokeExact (26 bytes) inline (hot)
@ 11 java.lang.Boolean::booleanValue (5 bytes) inline (hot)
@ 22 java.lang.invoke.MethodHandleImpl::selectAlternative (10 bytes) inline (hot)
@ 64 java.lang.Integer::intValue (5 bytes) inline (hot)
@ 80 java.lang.invoke.MethodHandle::invokeExact (12 bytes) inline (hot)
@ 80 java.lang.invoke.MethodHandle::invokeExact (18 bytes) inline (hot)
@ 4 java.lang.invoke.MethodHandle::invokeExact (6 bytes) inline (hot)
@ 2 jsr292.cookbook.binop.RT::add (4 bytes) inline (hot)
@ 9 java.lang.Integer::valueOf (54 bytes) inline (hot)
@ 50 java.lang.Integer::<init> (10 bytes) inline (hot)
@ 1 java.lang.Number::<init> (5 bytes) inline (hot)
@ 1 java.lang.Object::<init> (1 bytes) inline (hot)
@ 14 sun.invoke.util.ValueConversions::identity (2 bytes) inline (hot)
@ 1 java.lang.Integer::valueOf (54 bytes) inline (hot)
@ 50 java.lang.Integer::<init> (10 bytes) inline (hot)
@ 1 java.lang.Number::<init> (5 bytes) inline (hot)
@ 1 java.lang.Object::<init> (1 bytes) inline (hot)
@ 8 jsr292.cookbook.binop.RT::fallbackOpLeft (115 bytes) inline (hot)
@ 5 java.math.BigInteger::valueOf (62 bytes) already compiled into a medium method
@ 10 java.lang.Object::getClass (0 bytes) (intrinsic)
@ 33 java.lang.Integer::intValue (5 bytes) inline (hot)
@ 37 java.math.BigInteger::valueOf (62 bytes) already compiled into a medium method
@ 45 java.lang.invoke.MethodHandle::invokeWithArguments (61 bytes) too big
@ 19 PerfOpt::less (50 bytes) already compiled into a big method
> Moreover, the VM tries to inline some parts of the fallback method
> (twice :( )
> even if this code never called.
Hmm. I'm a little curious about how fallbackOpLeft becomes the fallback path. Usually this is/was done with a guardWithTest. Is selectAlternative doing this?
I think what's happening here is, we propagate the call site count from the hot MH call site to all its callees through the MH chain and since fallbackOpLeft is in there it gets the same call site count making it hot, while actually it isn't.
-- Christian
More information about the mlvm-dev
mailing list