Reference favoring primitive class heap allocations

Remi Forax forax at univ-mlv.fr
Wed Sep 1 21:06:50 UTC 2021


----- 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