value type hygiene
john.r.rose at oracle.com
Tue May 15 01:18:20 UTC 2018
On May 12, 2018, at 7:32 AM, Brian Goetz <brian.goetz at oracle.com> wrote:
> I want to drill into this point a bit. I know that you would prefer not to make heroic efforts to deal with cases where a random subset of a hierarchy was compiled with one polarity and the rest with the other, but I think there’s reasons to keep drilling on it. (Also, because I don’t think you’ll get away with it.)
When you say "polarity" it sounds like the two states are equally likely.
In fact, one state is clearly preferable, and one is locally incorrect and
tolerated—to some extent—by the rest of the system. This is true in
both Q-world and L-world. In Q-world, eventually the adapter spinners
will say, "you can't do that". In L-world, there are no adapter spinners,
but the same "laws of value physics" apply.
At some point legacy code can do something so bad that we must forbid it,
lest we inflict a performance hit on the entire system. What is the point at
which that occurs? I think the easiest way to find this point is make a fairly
restrictive JVM (plus lint modes in javac) and learn what bad code looks
like, and (more subtly) what not-quite-bad code looks like, that we want
to keep running.
An obvious example of bad code is something that calls monitorenter.
In the setting of null hygiene, bad code can use null as an out-of-band
value of a VBC, and expect the rest of the system to faithfully store
it in arbitrary containers, eventually returning it undamanged to the
bad actor. This can't work. Finding ways to sieve out the really bad
legacy code from workable stuff is an experimental process.
> I’ll note that this reminds me further of a related migration discussion in Burlington (DanH was there too) when we were exploring how to crowbar L/D primitives into one slot. Teaching the interpreter to do so in a consistent world was easy; the hard part was dealing with calling sequences / overrides across separately compiled files that had differentially gotten the memo about the new encoding. We talked about various adapters/fixups needed at the junction of a slot arity mismatch.
The thing that's different here is there are no explicit adapters across
different descriptors. The L-world JVM can spin them internally as needed,
as it already does, under the matched descriptors.
What's also different is everything runs under one slot; the J and
D descriptors are just hard to work with because of low-level stack
> While we didn’t solve it then either, I claim we want to solve it anyway, because this is how we get to primitives as values.
Based on our conversations about the matter, I'll be surprised if we
get to primitives as values and preserve the two-slot nature of
J and D, unless we introduce one-slot versions of those types.
The two-slot problem is hard all the way around, not just in L-world.
In any case, I think we don't need to solve primitives-as-values in
L-world, as long as we think L-world doesn't deprives us of important
> Just as the ValueTypes attribute lists the types known as of compile time to be values, we can similarly reify, on a per-class basis, whether the class is able to treat primitives as values. When class A calls / overrides a method in B with the same encoding, everything is great; when A and B differ on the value-ness of primitives, an adaptation, similar to the scalarize/bufferize adaptation, is needed at the junction. Over time, fewer classes will be out of date and the adapters will eventually be purged from the ecosystem.
That sounds plausible. We might be able to pull the trick of normalizing
old descriptors to new one, rewriting "I" to "Lint;" etc. Or we might choose
to let new and old descriptors co-exist. It does feel like the flattened calling
sequence problem we are talking about with L-world, but it is riskier, since
the classfiles must embody a tentative solution to a problem that might
change between compile time and run time, rather than having the JVM
come up with a solution on the fly, from final information.
I don't think we ever want to change J and D to single slot entities.
I think we will want to make new L-type descriptors like Llong; and
Ldouble; (or Q-type, in Q-world).
More information about the valhalla-spec-observers