----- Mail original ----- > De: "Peter Levart" <peter.lev...@gmail.com> > À: "John Rose" <john.r.r...@oracle.com>, "Tagir Valeev" <amae...@gmail.com> > Cc: "core-libs-dev" <core-libs-dev@openjdk.java.net> > Envoyé: Mardi 12 Mars 2019 11:29:22 > Objet: Re: Proposal: JDK-8148917 Enhanced-For Statement Should Allow Streams
> Hi John, > > On 3/12/19 12:07 AM, John Rose wrote: >>> public static void main(String[] args) { >>> for(int i : range(0, 100)) { >>> System.out.println(i); >>> } >>> } >>> >>> It correctly compiles and prints numbers from 0 to 99. As IntStream >>> extends BaseStream<Integer, IntStream> and BaseStream<T, S extends >>> BaseStream<T, S>> defines Iterator<T> iterator(), it would be no >>> problem with using IntStream.range in such code pattern were >>> BaseStream extends IterableOnce<T>. >>> >>> Of course this produces unnecessary garbage, as I said. >> This is a relatively simple kind of garbage to remove, because >> it is made (by calls to Integer.valueOf) at the adapted boundaries >> of the iterator, which are readily inlined into the loop. The deeper >> internal logic of the range function is box-free, as is the loop itself, >> so the garbage is relatively easy to remove. >> >> That said, "out of the box" there is lots of garbage created unless >> -XX:+AggressiveUnboxing is turned on. I assume Graal does a good >> job on it, even without this switch. >> >> If we ever succeed in suppressing the identity of java.lang.Integer, >> and/or after making functions like range into reified generics, the >> boxing will go away even more directly and simply. >> >> So, from the JIT engineering point of view, I would classify this >> particular boxing problem as relatively short-lived. >> >> — John > > What I have observed (some time ago) is that Integer instances obtained > by Integer.valueOf() are never found to "not escape" the JIT compilation > unit and are therefore never scalarized by JIT because of the "feature" > that was designed to actually prevent the continuous allocation of some > "values" of Integer(s) - namely the caching of Integer instances in the > Integer.IntegerCache.cache array for values in range [-128, 127]. So the > feature designed to prevent continuous allocation is actually working > against the desired goal. The code of Integer.valueOf is: > > public static Integer valueOf(int i) { > if (i >= IntegerCache.low && i <= IntegerCache.high) > return IntegerCache.cache[i + (-IntegerCache.low)]; > return new Integer(i); > } > > ...so JIT would have to create two specializations of code: one for > cached Integer instances which are always real objects and the other for > scalarized Integer(s) created by constructor. Last time I experimented > with this was in JDK 8. Is HotSpot in JDK 12+ smarter now and can do > this? Perhaps the @HotSpotIntrinsicCandidate annotation on this method > is a clue that it is treated in a special way by the JIT? this has been fixed very recently https://bugs.openjdk.java.net/browse/JDK-8075052 > > > Regards, Peter regards, Rémi