Reference favoring primitive class heap allocations

Stig Rohde Døssing stigdoessing at gmail.com
Thu Sep 2 09:25:56 UTC 2021


Thank you, that makes sense.

Den tor. 2. sep. 2021 kl. 10.52 skrev <forax at univ-mlv.fr>:

>
>
> ------------------------------
>
> *From: *"Stig Rohde Døssing" <stigdoessing at gmail.com>
> *To: *"Remi Forax" <forax at univ-mlv.fr>
> *Cc: *"valhalla-dev" <valhalla-dev at openjdk.java.net>
> *Sent: *Jeudi 2 Septembre 2021 00:23:29
> *Subject: *Re: Reference favoring primitive class heap allocations
>
> Thanks Rémi, I think it mostly does. I'll admit that the bit about
> optimizing local T.ref goes a bit over my head.
>
>
> My point was that T.ref declared as a local variable can be optimized by
> the JIT avoiding heap allocation.
>
> Just today Tobias submit a PR that shows how c2 try to avoid T.ref
> allocation on heap for local variables even when there is no inlining
> https://github.com/openjdk/valhalla/pull/543
>
>
> What about method return values? If I declare a method as
>
> T.val someMethod()
> vs
> T.ref someMethod()
>
> and do
>
> T.val someLocal = someMethod()
>
> would the two methods have different behavior for how the value is
> returned from the call (Return the value in registers/put it on the
> caller's stack vs.put the object on heap and return a pointer to that), or
> is this determined by whether "someLocal" is a val or a ref and doesn't
> have anything to do with the return type of "someMethod"?
>
>
> The two methods have almost the same behavior, apart from the fact that
> T.ref allows null while T.val does not.
> But they do not have the same "performance model". If you return T.val you
> ask to flatten T so it works even without inlining while if you return
> T.ref, the performance depend on the JIT being able to inline/optimize (so
> you may get the same performance or not).
>
> Rémi
>
>
>
> Den ons. 1. sep. 2021 kl. 23.06 skrev Remi Forax <forax at univ-mlv.fr>:
>
>> ----- Original Message -----
>> > From: "Stig Rohde Døssing" <stigdoessing at gmail.com>
>> > To: "valhalla-dev" <valhalla-dev at openjdk.java.net>
>> > Sent: Mercredi 1 Septembre 2021 12:43:46
>> > Subject: Reference favoring primitive class heap allocations
>>
>> > Hi,
>> >
>>
>> Hi,
>>
>> > JEP 401 describes that current value-based classes will be made
>> reference
>> > favoring to avoid breaking existing code. Optional is one of these. I'm
>> > trying to understand the impact this will have on existing APIs with
>> > respect to heap allocation.
>> >
>> > Please assume for the following code snippets that ordinary scalar
>> > replacement does not apply.
>> >
>> > As I understand it, code like
>> >
>> > Optional.val of(T item) { new Optional.val(item) }
>> > Optional.val<String> s = of("Hello")
>> >
>> > would tell the JVM that the Optional does not necessarily have to go on
>> the
>> > heap, but could maybe go on the stack or in registers instead.
>> >
>> > When "of" is instead defined with the reference type, as in
>> >
>> > Optional of(T item) { new Optional(item) }
>> > Optional.val<String> s = of("Hello")
>> >
>> > will the Optional always go on the heap?
>> >
>> > Also is the plan to be able to avoid the heap for return values, or will
>> > the return value of
>> >
>> > Optional.val of(T item)
>> >
>> > always go on the heap unless "of" happens to be inlined?
>> >
>> > Thanks for reading.
>>
>> Nope, there is only one way to create an object which is a primitive
>> class.
>>
>> Let's use an analogy, an ArrayList<String> at runtime can be typed as
>> List<?> or as List<String>, but it's the same ArrayList at runtime.
>>
>> With primitive classes, it works the same way, a primitive class is
>> always a primitive class at runtime,
>> there is no two different ways to create a primitive class, there is only
>> one way (to call the factory method named <new> of Optional).
>> What is different, is that a primitive class can be typed in two
>> different ways, as an Optional.val or as an Optional.ref,
>> those two types mean different things in term of storage for a field, an
>> array element or a local variable.
>>
>> T.val:
>>   For fields and array elements, all the fields (if there are not too
>> many) of T.val are stored in the container of the T.val (the class or the
>> array containing the T.val)
>>   For a local variable, T.val means that the VM will use registers (or
>> spill the values on stack due to the register allocator) independently of
>> the inlining algorithm.
>>
>> T.ref:
>>   For fields and array elements, a T.ref is stored as a reference (on
>> heap).
>>   For a local variable, T.ref means that inside the inlining horizon, the
>> VM can optimize the code using escape inlining with late rematerialization,
>> so better than a classical reference because a primitive class has no
>> identity (in practice it's a little more complicated because you don't want
>> to inflate/deflate the same object inside the inlining horizon).
>>
>> I hope it answers to your questions.
>>
>> regards,
>> Rémi
>>
>
>


More information about the valhalla-dev mailing list