Moving from VVT to the L-world value types (LWVT) (original) (raw)
Ali Ebrahimi ali.ebrahimi1781 at gmail.com
Wed Feb 21 05:13:40 UTC 2018
- Previous message (by thread): Moving from VVT to the L-world value types (LWVT)
- Next message (by thread): Moving from VVT to the L-world value types (LWVT)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hi, Why not have new NonNullable marker interface for marking (new/legacy) value types. We can have nullable and non-nullable types. New (true) value types can implements NonNullable interface by default. By this we can support non-nullable reference types later if want.
On Wed, Feb 21, 2018 at 6:18 AM, John Rose <john.r.rose at oracle.com> wrote:
On Feb 12, 2018, at 11:12 AM, John Rose <john.r.rose at oracle.com> wrote: > > On Feb 12, 2018, at 8:53 AM, Srikanth <srikanth.adayapalam at oracle.com> wrote: >> >> Hi Frederic, >> >> A couple of follow up questions below: >> >> On Monday 12 February 2018 10:02 PM, Frederic Parain wrote: >> >> [...] >>> The current design allows null references for value types, as long as they are not stored >>> in a container (field or array) declared as flattenable. This is a significant change from >>> previous design. So, casting null to a value class type is now legal. >> >> OK. This does not call for any change to the specification of checkcast in JVMS ? >> (I don't know that it does - Just double checking) > > There might be an option here: Maybe we could get away with having checkcast > throw NPE if the target class is a value type. After all, the checkcast instruction resolves > its class operand. Remember that we must allow polluting nulls in fields which > are not explicitly marked as flat, but only because of binary compatibility requirements. > We do not allow polluting nulls to be stored into arrays, because arrays must > resolve their element types before the first array is constructed. I think we could > put checkcast into either of these two categories: Allowing polluting nulls for > compatibility, or forbidding them (throwing NPE). > > Hmm… The more aggressive choice (throwing NPE on checkcast) would make would > prevent instances of generic code (such as List) from accepting > nulls: > > List xs = new ArrayList<>(); > xs.add(null); // to NPE or not to NPE? > > This is not really a JVM question, but a language question: Should > the above code throw NPE if freshly recompiled? Yes, probably. > What if it is inside a legacy classfile, and is not freshly recompiled? > It would break if it threw NPE. This argues for two slightly different > versions of checkcast. Argh: An option turns into a two-sided mandate. > The checkcast might need a flat-bit. (Stay away, you Q-types.) > Or the checkcast could throw NPE only in newer classfile versions. > > These considerations also apply to Class::cast.
I thought about this some more, and talked briefly with Brian, and here's where I think we should come out: In new source code it will always be illegal to cast a null to a value type. The rule for values is, "codes like a class, works like an int". If you cast a null to (int) you get an NPE. That's what the language needs to do. It doesn't matter what the JVM does. There are two exceptions to this reasoning: Explicit nullability, or legacy compilation. If we were to add a new feature which allowed a type to be nullable, then types which had this nullable aspect could be the target of a cast, without a null check, and the JVM would process the null appropriately. It would have to use an L-type descriptor for the value, of course. But we are not doing this at present. If javac is compiling for legacy code (say, with the experimental features turned off) then it should not "notice" class files which are defined as value types (or non-nullable types, if we add this feature at some point). In that case, no null checks should be inserted, since that would be incompatible with old code. To summarize: javac should arrange a null check when it emits a cast to a type which is statically known to be a value type, if it is compiling at a source level which recognizes value types as such. Since reflective calls are used by both old and new bytecodes, adding a null checks for value-types is not an option for Class::cast. Probably we need a new API point, Class::castValue, which senses a value type and adds a null check in that case. For reference types, the behavior of Class::castValue would be the same as Class::cast. At the JVM level, we should consider making checkcast incorporate a null check, in the case where (a) the class resolves to a value type, and (b) the classfile version supports value types. In this way, legacy classfile code will continue to be sloppy with nulls, but new code will not. Users who need to cast to a value type without the null check can use Class::cast or some other API point which guarantees to allow "polluting" nulls to pass through. To be clear: If a classfile contains a checkcast that refers to a value type, and if the classfile's version number (or other markings) allows it to process value types (say, withfield is also allowed), then the semanatics of the checkcast should include a null check, even though (for compatibility reasons in old code) the JVM would allow a null under the same descriptor. I admit that giving checkcast a different behavior in different classfile versions is odd, and as a temporary fallback it might be better to ask javac to insert explicit null checks before such checkcasts.
--
Best Regards, Ali Ebrahimi
- Previous message (by thread): Moving from VVT to the L-world value types (LWVT)
- Next message (by thread): Moving from VVT to the L-world value types (LWVT)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]