From mcnepp02 at googlemail.com Thu Mar 2 14:21:54 2023 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Thu, 2 Mar 2023 15:21:54 +0100 Subject: Nullness markers to enable flattening Message-ID: The following two lines are quotes from Dan's list of "key ideas": - Nullness is an *optional* property of variables/expressions/etc., distinct from types. - Type variable types have nullness, too. To me, this looks a little contradictory. If we agree on the first statement (and I do agree with it), then Type-variables should not have an attached nullness-marker. Rather, each _use_ of a Type-variable in a generic class would have the attached nullness. Otherwise, a type-variable would again denote a "non-nullable" type, so you'd be back where you came from... Consider the following example. IMHO, adding @NonNull to the type-variable would be of no real advantage. class Holder { static Holder of(@NonNull T value) { } } -------------- next part -------------- An HTML attachment was scrubbed... URL: From anhmdq at gmail.com Thu Mar 2 14:35:47 2023 From: anhmdq at gmail.com (=?UTF-8?Q?Qu=C3=A2n_Anh_Mai?=) Date: Thu, 2 Mar 2023 22:35:47 +0800 Subject: Nullness markers to enable flattening In-Reply-To: References: Message-ID: But we want a List to be different from a List. Thanks. On Thu, 2 Mar 2023 at 22:22, Gernot Neppert wrote: > The following two lines are quotes from Dan's list of "key ideas": > > - Nullness is an *optional* property of variables/expressions/etc., distinct from types. > - Type variable types have nullness, too. > > To me, this looks a little contradictory. If we agree on the first statement (and I do agree with it), > > then Type-variables should not have an attached nullness-marker. > > Rather, each _use_ of a Type-variable in a generic class would have the attached nullness. > > Otherwise, a type-variable would again denote a "non-nullable" type, so you'd be back where you came from... > > > Consider the following example. IMHO, adding @NonNull to the type-variable would be of no real advantage. > > class Holder { > > static Holder of(@NonNull T value) { > } > } > > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From daniel.smith at oracle.com Thu Mar 2 19:01:48 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Thu, 2 Mar 2023 19:01:48 +0000 Subject: Nullness markers to enable flattening In-Reply-To: References: Message-ID: <45186788-6C88-4557-B9BD-D16D2D74606D@oracle.com> > On Mar 2, 2023, at 6:21 AM, Gernot Neppert wrote: > > The following two lines are quotes from Dan's list of "key ideas": - Nullness is an *optional* property of variables/expressions/etc., distinct from types. > - Type variable types have nullness, too. > > > To me, this looks a little contradictory. If we agree on the first statement (and I do agree with it), > > then Type-variables should not have an attached nullness-marker. > > Rather, each _use_ of a Type-variable in a generic class would have the attached nullness. That's the intent. By "type variable types", I mean type variable uses. From daniel.smith at oracle.com Wed Mar 8 00:57:43 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 8 Mar 2023 00:57:43 +0000 Subject: EG meeting *canceled*, 2023-03-08 Message-ID: Nothing new, sorry! We'll try for next time. > I'm putting together a JEP draft about nullness that may be ready for review next time, stay tuned for that. Still working through these details. Going to take a couple more weeks to work through the interactions with other Valhalla features and make sure we're happy internally with the direction. From daniel.smith at oracle.com Tue Mar 21 16:10:17 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Tue, 21 Mar 2023 16:10:17 +0000 Subject: Revised JEP: Null-Restricted Value Object Storage Message-ID: I've updated JEP 401, formerly "Primitive Classes", now titled "Null-Restricted Value Object Storage". The purpose of this JEP is to allow for flattening of value objects in fields and arrays. This update gets there via two key features: - "Optional" constructors, which express the capability of a value class to have instances created outside the normal construction process. - Null-restricted types, which exclude null from the type's value set, and in the case of value classes with optional constructors, allow for a non-null default value. There's more to say about nullness, which is covered by its own JEP that we're still working on. But the idea of null-restricted variables is enough to unblock progress on value object flattening. (Eventually, we envision?at least for now?delivering the two JEPs at the same time.) The document is here: https://openjdk.org/jeps/401 From forax at univ-mlv.fr Tue Mar 21 17:21:54 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 21 Mar 2023 18:21:54 +0100 (CET) Subject: Revised JEP: Null-Restricted Value Object Storage In-Reply-To: References: Message-ID: <2023320434.17256688.1679419314577.JavaMail.zimbra@u-pem.fr> I've just done a first pass. There is a typo new Thread(() -> ps[0] = new Point(1.0, 0.0)).run(); should be new Thread(() -> ps[0] = new Point(1.0, 0.0)).start(); In term of syntax, i'm sure you already knows that - Not having a keyword at the class level to differentiate between default-instance value type vs value type is not very readable because the optional constructor can be buried deep inside the class body. - The keyword "non-atomic" on the optional constructor is even weirder, given that has the example shown, the problem is unrelated to using the default value, Point.default or not. In term of semantics, I really like this JEP :) regards, R?mi ----- Original Message ----- > From: "daniel smith" > To: "valhalla-spec-experts" > Sent: Tuesday, March 21, 2023 5:10:17 PM > Subject: Revised JEP: Null-Restricted Value Object Storage > I've updated JEP 401, formerly "Primitive Classes", now titled "Null-Restricted > Value Object Storage". The purpose of this JEP is to allow for flattening of > value objects in fields and arrays. This update gets there via two key > features: > > - "Optional" constructors, which express the capability of a value class to have > instances created outside the normal construction process. > > - Null-restricted types, which exclude null from the type's value set, and in > the case of value classes with optional constructors, allow for a non-null > default value. > > There's more to say about nullness, which is covered by its own JEP that we're > still working on. But the idea of null-restricted variables is enough to > unblock progress on value object flattening. (Eventually, we envision?at least > for now?delivering the two JEPs at the same time.) > > The document is here: > > https://openjdk.org/jeps/401 From brian.goetz at oracle.com Tue Mar 21 17:33:18 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 21 Mar 2023 13:33:18 -0400 Subject: Revised JEP: Null-Restricted Value Object Storage In-Reply-To: <2023320434.17256688.1679419314577.JavaMail.zimbra@u-pem.fr> References: <2023320434.17256688.1679419314577.JavaMail.zimbra@u-pem.fr> Message-ID: > In term of syntax, i'm sure you already knows that In terms of constructive engagement, I'm sure you already know that commenting on syntax at this point is a party foul.... From forax at univ-mlv.fr Tue Mar 21 17:46:00 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Tue, 21 Mar 2023 18:46:00 +0100 (CET) Subject: Revised JEP: Null-Restricted Value Object Storage In-Reply-To: References: <2023320434.17256688.1679419314577.JavaMail.zimbra@u-pem.fr> Message-ID: <953970167.17265305.1679420760412.JavaMail.zimbra@u-pem.fr> ----- Original Message ----- > From: "Brian Goetz" > To: "Remi Forax" , "daniel smith" > Cc: "valhalla-spec-experts" > Sent: Tuesday, March 21, 2023 6:33:18 PM > Subject: Re: Revised JEP: Null-Restricted Value Object Storage >> In term of syntax, i'm sure you already knows that > > In terms of constructive engagement, I'm sure you already know that > commenting on syntax at this point is a party foul.... I'm commenting on the syntax "en passant". R?mi From brian.goetz at oracle.com Tue Mar 21 19:14:43 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 21 Mar 2023 15:14:43 -0400 Subject: Revised JEP: Null-Restricted Value Object Storage In-Reply-To: References: Message-ID: <1423aca3-819a-d2c4-bf6a-1d6978527689@oracle.com> There's been a lot of change since the last update of this JEP, so let me summarize the changes and the motivation.? The current JEP text is still very rough; the point of sharing it in this state is to sketch out the next chunk of the story and how it connects to the other chunks, even if they are not fully fleshed out. #### Value and "primitive" classes This JEP positions the Valhalla story as one of "the more flexibility you give up, the better flattening you get." Identity classes get no flattening.? Value classes (B2) give up identity (but nothing else), and they get better flattening on the stack (e.g., optimized calling convention), but (absent VM heroics) no flattening on the heap.? This is already confusing to many users, because they hear "flattening" and think "layout inlining." To get heap flattening / layout inlining, you have to give up some more.? It took a while to figure this out, but we finally realized that the key distinction between B2 and B3 has to do with its _initialization protocol_ (or lack thereof). Non-nullability is important for flattening, but it is secondary; before you can go non-nullable safely, you have to obviate the need for null in the first place, which means you need to make initialization optional. We have nulls because most objects require initialization; simply interpreting a block of zeroed memory as an instance of a class is usually only incrementally worse than interpreting a block of garbage as an instance of that class.? To protect from interpreting uninitialized memory as an object instance, object references use null as their default value.? The primitive types all share the characteristic that the zero value is actually a good default, and therefore they do not need the extra initialization safety afforded by object references and null, and therefore they can be non-nullable, and therefore they can be routinely flattened. With this in mind, we downplay the distinction between B2 and B3; B3 is a special kind of value class, one for which construction is optional because the default (zero) value is considered good. #### Performance story The performance story becomes one of a spectrum of tradeoffs: ?- Identity classes get lots of flexibility, but no flattening. ?- Value classes give up identity, and get flattening on the stack (optimized calling convention, reliable scalarization, etc), but no flattening on the heap. ?- Value classes that support default instances (B3) give up on the requirement that all instances be initialized, and in return, non-nullable variables can be flattened in the heap -- up to the limit of atomic load/store operations. ?- B3 classes that further opt out of atomicity can get heap flattening for larger instances. #### Ref, val, and bang The previous version of the story divided uses of B3 classes into a primitive type and a reference type, and there were a number of properties that derived from the choice of reference vs primitive (including nullability).? We've now arrived at the point where we can represent these properties individually, and therefore don't need to appeal to this coarser ref-vs-val distinction.? As a result, we can get rid of the clunky X.ref / X.val notation, and express null-restriction with the more familiar cardinality sigil, `X!`. For purposes of this JEP, the use of null-restriction types is limited to types where the null-restriction can be reified by the JVM (hello, Q types); a separate JEP will explore extending it to all reference types and the attendant consequences of erasure (e.g., null pollution.) In this interpretation, we do not have to call `Point!` a primitive type; we can call it a restriction of the reference type `Point`.? (If we do, we gain some uniformity for class types ("everything is a reference"), at the expense of permanently living with a more visible seam with primitives; we can continue to evaluate the tradeoffs here.) On 3/21/2023 12:10 PM, Dan Smith wrote: > I've updated JEP 401, formerly "Primitive Classes", now titled "Null-Restricted Value Object Storage". The purpose of this JEP is to allow for flattening of value objects in fields and arrays. This update gets there via two key features: > > - "Optional" constructors, which express the capability of a value class to have instances created outside the normal construction process. > > - Null-restricted types, which exclude null from the type's value set, and in the case of value classes with optional constructors, allow for a non-null default value. > > There's more to say about nullness, which is covered by its own JEP that we're still working on. But the idea of null-restricted variables is enough to unblock progress on value object flattening. (Eventually, we envision?at least for now?delivering the two JEPs at the same time.) > > The document is here: > > https://openjdk.org/jeps/401 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From daniel.smith at oracle.com Wed Mar 22 15:45:49 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 22 Mar 2023 15:45:49 +0000 Subject: EG meeting, 2023-03-22 Message-ID: EG meeting is on today. February 22, at 4pm UTC (9am PDT, 12pm EDT). (Note the time change for Europe, due to DST mismatches.) We can discuss the revised JEP, Null-Restricted Value Object Storage. From brian.goetz at oracle.com Tue Mar 28 19:13:02 2023 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 28 Mar 2023 15:13:02 -0400 Subject: B3, default values, and implicit initialization Message-ID: <61a456f3-88bc-553a-2310-50acf0fe9cf7@oracle.com> The recent update of JEP 401 contained a number of refinements to the user model, specifically, separating the primitive/reference distinction into a number of smaller distinctions (e.g., nullable vs non-nullable, optional vs required construction.)? Overall this has been a very positive step forward. We still have a need for the distinction between what we've been calling B2 and B3; JEP 401 currently frames that in terms of "construction is optional."? This is a big step forward; indeed, the key difference between them is whether the class _needs_ the "variables start out as null, and all instances are created by constructors" protection, or whether it admits the lighter-weight initialization protocol of "there's a a standard zero value, null-free variables are initialized to that" that primitives enjoy today.? (Note that B3 classes don't require this lighter protocol, they merely enable it, much as primitives all give you the option of boxing to get the full conservative initialization protocol.) The idea of framing this as "construction is optional" is a good one, but the expression of it proposed in JEP 401 feels "not quite there".? In this note I'll propose an alternative presentation, but the main goal here is around terminology and user model rather than syntax (so please keep the syntax agitation to a reasonable level.) The key distinction between B2 and B3 is that B3 has a _default value_ which the VM can summon at will.? This enables non-nullable heap variables to be flattened, because we can initialize these the same way we initialize other fields and array elements.? Further, that default value is highly constrained; it is a physical zero, the result of initializing all fields to their default value. Flattening is of course a goal, but it is not something that exists in the programming model -- its just an optimization. What exists in the programming model is the default value, and what this unlocks is the possibility for variables to be _implicitly initializated_.? Reference-typed variables today are _explicitly initialized_; variables start out null and have to be initialized with a constructed value.? A class with a default value has the option (opted in through null-exclusion) for its variables to be implicitly initialized, which, like primitives, means that they start out with a valid default value, and can be further assigned to. Framed this way, the Valhalla performance story simplifies to: ?- Give up identity, get flattening on the stack; ?- Further give up explicit initialization, get flattening for small objects on the heap; ?- Further give up atomicity, get flattening for larger objects on the heap. Giving up explicit initialization entails both the class opting out of explicit initialization, _and_ the variable opting out of nullity. The key new terminology that comes out of this is implicit vs explicit initialization. Syntactically, my preference is to indicate that the default value can be summoned by giving a value class a _default constructor_: ??? value class Complex { ??????? public final double re, im; ??????? public default Complex(); ??? } A default constructor has no arguments, no body, no throws clause, and implicitly initializes all fields to their default values.? Unlike identity classes, value classes don't get constructions implicitly; a value class must declare at least one constructor, default or otherwise.? This replaces the idea of "optional constructor", which is a negative statement about construction ("but you don't have to call me"), with a more direct and positive statement that there is a _default constructor_ with the required properties. Note that this is similar to the existing concept of "default constructor", which you get for free in an identity class if you don't specify any constructors.? It is possible we can unify these features (and also with constructors in "agnostic" abstract classes), but first let's work out what it would mean in value classes, and see if we like it. In this model, a B3 class is just a value class with a default constructor -> a default constructor means that you have the choice of implicit or explicit initialization -> non-nullity at the use site opts into implicit initialization -> B3! gets flattening (for small layouts.) -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Tue Mar 28 21:09:59 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 28 Mar 2023 23:09:59 +0200 (CEST) Subject: B3, default values, and implicit initialization In-Reply-To: <61a456f3-88bc-553a-2310-50acf0fe9cf7@oracle.com> References: <61a456f3-88bc-553a-2310-50acf0fe9cf7@oracle.com> Message-ID: <1005107757.22297332.1680037799290.JavaMail.zimbra@univ-eiffel.fr> > From: "Brian Goetz" > To: "valhalla-spec-experts" > Sent: Tuesday, March 28, 2023 9:13:02 PM > Subject: B3, default values, and implicit initialization > The recent update of JEP 401 contained a number of refinements to the user > model, specifically, separating the primitive/reference distinction into a > number of smaller distinctions (e.g., nullable vs non-nullable, optional vs > required construction.) Overall this has been a very positive step forward. > We still have a need for the distinction between what we've been calling B2 and > B3; JEP 401 currently frames that in terms of "construction is optional." This > is a big step forward; indeed, the key difference between them is whether the > class _needs_ the "variables start out as null, and all instances are created > by constructors" protection, or whether it admits the lighter-weight > initialization protocol of "there's a a standard zero value, null-free > variables are initialized to that" that primitives enjoy today. (Note that B3 > classes don't require this lighter protocol, they merely enable it, much as > primitives all give you the option of boxing to get the full conservative > initialization protocol.) > The idea of framing this as "construction is optional" is a good one, but the > expression of it proposed in JEP 401 feels "not quite there". In this note I'll > propose an alternative presentation, but the main goal here is around > terminology and user model rather than syntax (so please keep the syntax > agitation to a reasonable level.) > The key distinction between B2 and B3 is that B3 has a _default value_ which the > VM can summon at will. This enables non-nullable heap variables to be > flattened, because we can initialize these the same way we initialize other > fields and array elements. Further, that default value is highly constrained; > it is a physical zero, the result of initializing all fields to their default > value. > Flattening is of course a goal, but it is not something that exists in the > programming model -- its just an optimization. What exists in the programming > model is the default value, and what this unlocks is the possibility for > variables to be _implicitly initializated_. Reference-typed variables today are > _explicitly initialized_; variables start out null and have to be initialized > with a constructed value. A class with a default value has the option (opted in > through null-exclusion) for its variables to be implicitly initialized, which, > like primitives, means that they start out with a valid default value, and can > be further assigned to. > Framed this way, the Valhalla performance story simplifies to: > - Give up identity, get flattening on the stack; > - Further give up explicit initialization, get flattening for small objects on > the heap; > - Further give up atomicity, get flattening for larger objects on the heap. > Giving up explicit initialization entails both the class opting out of explicit > initialization, _and_ the variable opting out of nullity. > The key new terminology that comes out of this is implicit vs explicit > initialization. > Syntactically, my preference is to indicate that the default value can be > summoned by giving a value class a _default constructor_: > value class Complex { > public final double re, im; > public default Complex(); > } > A default constructor has no arguments, no body, no throws clause, and > implicitly initializes all fields to their default values. Unlike identity > classes, value classes don't get constructions implicitly; a value class must > declare at least one constructor, default or otherwise. This replaces the idea > of "optional constructor", which is a negative statement about construction > ("but you don't have to call me"), with a more direct and positive statement > that there is a _default constructor_ with the required properties. > Note that this is similar to the existing concept of "default constructor", > which you get for free in an identity class if you don't specify any > constructors. It is possible we can unify these features (and also with > constructors in "agnostic" abstract classes), but first let's work out what it > would mean in value classes, and see if we like it. > In this model, a B3 class is just a value class with a default constructor -> a > default constructor means that you have the choice of implicit or explicit > initialization -> non-nullity at the use site opts into implicit initialization > -> B3! gets flattening (for small layouts.) For me, the notion of default value is clearly better than the notion of optional constructor. It also works well with the idea of being able to get the default value of a type variable (T.default). I also really like the idea that the value class semantics is defined in terms of giving up properties even if it is equivalent to getting the VM more leeway. I fear that in term of syntax we need a little more ceremony because the default constructor may be buried deeply inside the class, far from the declaration of the value class, making the semantics of the class non obvious for readers. I believe, the class should declare a default constructor and should also be annotated with a keyword, a kind of belt and suspender approach. Or perhaps we can use the "functional interface"/"override" playbook here and not add a new keyword on value class but introduce an annotation similar to @FunctionalInterface/@Override, let say @DefaultValue (or whatever suits better) that documents that there is a default constructor thus a default value. If this annotation is set on a value class, the compiler will verify that a default constructor is present. regards, R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From mcnepp02 at googlemail.com Wed Mar 29 06:05:53 2023 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Wed, 29 Mar 2023 08:05:53 +0200 Subject: B3, default values, and implicit initialization In-Reply-To: <1005107757.22297332.1680037799290.JavaMail.zimbra@univ-eiffel.fr> References: <61a456f3-88bc-553a-2310-50acf0fe9cf7@oracle.com> <1005107757.22297332.1680037799290.JavaMail.zimbra@univ-eiffel.fr> Message-ID: Am Di., 28. M?rz 2023 um 23:10 Uhr schrieb Remi Forax : > > ------------------------------ > > For me, the notion of default value is clearly better than the notion of > optional constructor. > It also works well with the idea of being able to get the default value of > a type variable (T.default). > > I also really like the idea that the value class semantics is defined in > terms of giving up properties even if it is equivalent to getting the VM > more leeway. > > I fear that in term of syntax we need a little more ceremony because the > default constructor may be buried deeply inside the class, far from the > declaration of the value class, making the semantics of the class non > obvious for readers. I believe, the class should declare a default > constructor and should also be annotated with a keyword, a kind of belt and > suspender approach. > Or perhaps we can use the "functional interface"/"override" playbook here > and not add a new keyword on value class but introduce an annotation > similar to @FunctionalInterface/@Override, let say @DefaultValue (or > whatever suits better) that documents that there is a default constructor > thus a default value. > If this annotation is set on a value class, the compiler will verify that > a default constructor is present. > > I agree that an annotation at class-level would make the intent much clearer than just having a default-constructor-declaration that can be hard to spot. (another proposal for the name: @DefaultConstructable) Now, if that annotation is present, then the additional "default MyClass();" declaration seems pointless, given that it has to look exactly that way for every value-class, and that it actually does not correspond to any generated code (especially no constructor-related code). Another point I see: Each @DefaultConstructable value-class claims that it is fine with being zero-initialized. To me, this also implies that having an additional user-defined parameterless constructor (for use with by "new MyClass()") would be at least confusing, if not outright wrong. Thus, I suggest to specify that if the @DefaultConstructable Annotation is present, the compiler will enforce that there is no user-defined parameterless constructor! -------------- next part -------------- An HTML attachment was scrubbed... URL: