value type hygiene
john.r.rose at oracle.com
Tue May 15 22:30:58 UTC 2018
On May 15, 2018, at 3:03 PM, forax at univ-mlv.fr wrote:
> …We could also play this move: An interface ValueRef<VT> could be defined
> such that, at the JVM level, the JVM enforces that (x instanceof ValueRef)
> if and only if (x.getClass().isValue()). The JVM would simply enforce the
> corresondence at class load time. It's a play I'm keeping in my pocket,
> which could add special runtime strength to a static typing story.
> so it's a way to resurect the Qjava/lang/Object; as super type of all value types, it's nullable like Ljava/lang/Object; but you can not put a reference type in it by construction.
Yes. Some small usefulness there, not a lot.
> I'm not sure it can solve our problem because at callsite of a method you know the value type and you know that you will call a method that takes a ValueRef so you can the calling convention of a value type but at callee side
At the receiving site the code would either treat it as a generic pointer
(if the code is generic) or else cast it to a particular VT. It depends
on whether the API point being called said ValueRef<T> for some
type parameter T or whether it said ValueRef<LocalDate> requesting
a nullable date. In neither case do we need to pass extra metadata.
Either it's a non-varying use case of ValueRef or a varying case,
where the varying case will be managed by casts or other type tests
> When you create an array, you can check if it has to be flatten or not using the ValueTypes attributes, if it's possible (see below).
Yep, that's a move we can do for anewarray, as I've already
mentioned. But that does't work for jlr.Array.newInstance,
which is a significant contributor of array instances. Best
to keep arrays monomorphic, if we can hold that line.
> Or you can for these specific type allow flattening by default and do heroic change if there is a code that try to put null in it by re-boxing all the elements as you said in the message to Maurizio.
> Usually doing heroic things like this in the VM is a stupid idea, here, we are talking about a corner case, how to retrofit value based class, so doing heroic things like this is two times stupid.
> (I wonder if Panama vector types would tolerate such a move: We mainly
> need in-loop optimizations, so nullability would be tolerable there, but having
> them boxed in arrays would be a non-starter.)
> I hope that If the panama vector API is published, it will be as an experimental API so no need to maintain a backward compatibility story here. They can be value types.
> 0. leave it alone, it's a VBC
> 1. make it a proper value type, get flattening on recompile, and deal with the null hygiene fallout
> 0.1 make it a value type but mark it @VBC, no sync or acmp, no flattening either
> but it's nullable, the semantics is simple and mostly backward compatible (== does not work, use equals instead, do not synchronize on it) and no allocation cost where it can be important like in loops.
> in my opinion, yes, it's a trade off, but it's closer to 0.5 than 0.1.
> OK, I see how it is worth the experiment. It's nice that (except for the
> array question) it's purely in the translation strategy: The existing proposed
> ValueTypes attribute would (as you say) simply never mention such a
> marked VT.
> It can be a pure translation strategy for array too, if the VM uses the attribute ValueTypes to know which kind of array should be created but in that case, it means that the array need to be tagged as flattened or not and i do not know if it's possible.
That's very possible, actually; remember that the JVM already hides
arrays which are supposed to be flattenable but for some reason have
failed to truly flatten. Also, T <: Object for all (non-primitive) T whether
T can really flatten or not. (This is one of the big moves in L-world!)
So, we could have the JVM look for that annotation at class-load time
and do two things: (1) throw the switch that secretly de-flattens a
nominally flattenable array, (2) allow nulls in, as a public promise.
That first step is a hidden thing that is easy to gate with an annotation
(if it's not too complicated in structure–type annotations *are* complex).
The second step is a somewhat non-annotation-like effect on semantics,
but maybe it can pass muster if the alternatives are all worse.
(Example of worse alternative: A new keyword in the language just
for migrating 3 legacy VBCs. Don't think that will fly. Second example:
Adding nullability and non-nullability modifiers on all sorts of type uses
and defs. That might fly, but it will take years to get off the ground.
If we do that, we might be able to retire the makeshift annotation.)
I'm not against doing such an annotation; it is cheap to do, and
doesn't harm any other parts of the system. All the downsides
would be inflicted on the class that opted into it.
More information about the valhalla-spec-observers