On 06/17/2011 10:58 AM, Christian Thalinger wrote: > On Jun 15, 2011, at 5:26 PM, Rémi Forax wrote: >> // with the optimization >> [forax@localhost binary-operation]$ time java -cp .:classes PerfOpt >> real 0m0.954s >> user 0m1.030s >> sys 0m0.087s >> >> // without >> [forax@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.
It's far more readable, now :) I wonder if I haven't introduce a bug in my logic, there is a the boxing/unboxing of the return value of the test that should not occur. Question, does EA is also disable when MH.invokeExact is called ? @ 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) I will check my code. > 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? isSelectAlternative is the internal method called when you create a guardWithTest with ricochet frame enabled. > I think what's happening here is, we propagate the call site count from the > hIot 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. Yes, one solution is to always set the fallback as cold. A better solution is to record the usage of each branch when interpreted. > -- Christian Rémi _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev