Proposal: JDK-8148917 Enhanced-For Statement Should Allow Streams
Peter Levart
peter.levart at gmail.com
Tue Mar 12 10:29:22 UTC 2019
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?
Regards, Peter
More information about the core-libs-dev
mailing list