Hi guys,
I've found a case where assert is harmful because it doesn't
play well with Hotspot inlining heuristic.

I'm currently playing with a lambda modified implementation of java.util and
as you see below Integer.valueOf is considered as too big by Hotspot
to be inlined.

79 2 b lambda.perf.Iterables::filterMapReduce (72 bytes) @ 4 java.util.AbstractList::iterator (10 bytes) inline (hot) @ 6 java.util.AbstractList$Itr::<init> (6 bytes) unloaded signature classes @ 61 java.util.AbstractList$Itr::hasNext (20 bytes) inline (hot) @ 8 java.util.Arrays$ArrayList::size (6 bytes) inline (hot) ! @ 16 java.util.AbstractList$Itr::next (45 bytes) inline (hot) @ 1 java.util.AbstractList$Itr::checkForComodification (23 bytes) inline (hot) @ 14 java.util.Arrays$ArrayList::get (7 bytes) inline (hot) @ 29 lambda.perf.Test$1::accept (9 bytes) inline (hot) @ 5 lambda.perf.Test$1::accept (13 bytes) inline (hot) @ 1 java.lang.Integer::intValue (5 bytes) inline (hot) @ 45 lambda.perf.Test$2::map (9 bytes) inline (hot) @ 5 lambda.perf.Test$2::map (2 bytes) inline (hot) @ 52 lambda.perf.Test$3::apply (13 bytes) inline (hot) @ 9 lambda.perf.Test$3::apply (13 bytes) inline (hot) @ 1 java.lang.Integer::intValue (5 bytes) inline (hot) @ 5 java.lang.Integer::intValue (5 bytes) inline (hot) @ 9 java.lang.Integer::valueOf (54 bytes) too big @ 61 java.util.AbstractList$Itr::hasNext (20 bytes) inline (hot) @ 8 java.util.Arrays$ArrayList::size (6 bytes) inline (hot)

but the code of Integer.valueOf doesn't seem too big:
public static Integer valueOf(int i) {
        assert IntegerCache.high >= 127;
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

The issue is that Hotspot also count the bytecodes related to assert
in its inlining heuristic.
If the assert is commented, the inlining tree is good.

88    2    b        lambda.perf.Iterables::filterMapReduce (72 bytes)
@ 4 java.util.AbstractList::iterator (10 bytes) inline (hot) @ 6 java.util.AbstractList$Itr::<init> (6 bytes) unloaded signature classes @ 61 java.util.AbstractList$Itr::hasNext (20 bytes) inline (hot) @ 8 java.util.Arrays$ArrayList::size (6 bytes) inline (hot) ! @ 16 java.util.AbstractList$Itr::next (45 bytes) inline (hot) @ 1 java.util.AbstractList$Itr::checkForComodification (23 bytes) inline (hot) @ 14 java.util.Arrays$ArrayList::get (7 bytes) inline (hot) @ 29 lambda.perf.Test$1::accept (9 bytes) inline (hot) @ 5 lambda.perf.Test$1::accept (13 bytes) inline (hot) @ 1 java.lang.Integer::intValue (5 bytes) inline (hot) @ 45 lambda.perf.Test$2::map (9 bytes) inline (hot) @ 5 lambda.perf.Test$2::map (2 bytes) inline (hot) @ 52 lambda.perf.Test$3::apply (13 bytes) inline (hot) @ 9 lambda.perf.Test$3::apply (13 bytes) inline (hot) @ 1 java.lang.Integer::intValue (5 bytes) inline (hot) @ 5 java.lang.Integer::intValue (5 bytes) inline (hot) @ 9 java.lang.Integer::valueOf (32 bytes) inline (hot) @ 28 java.lang.Integer::<init> (10 bytes) call site not reached @ 61 java.util.AbstractList$Itr::hasNext (20 bytes) inline (hot) @ 8 java.util.Arrays$ArrayList::size (6 bytes) inline (hot)

Given that Integer.valueOf() is a method used very often and that if the inlining fails,
the escape analysis will not remove the allocation,
I think it's a good idea to comment this assert.

cheers,
Rémi



Reply via email to