Proposal: JDK-8148917 Enhanced-For Statement Should Allow Streams

Remi Forax forax at univ-mlv.fr
Tue Mar 12 12:30:39 UTC 2019


----- Mail original -----
> De: "Peter Levart" <peter.levart at gmail.com>
> À: "John Rose" <john.r.rose at oracle.com>, "Tagir Valeev" <amaembo at gmail.com>
> Cc: "core-libs-dev" <core-libs-dev at 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


More information about the core-libs-dev mailing list