From daniel.smith at oracle.com Wed Jan 11 06:25:33 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 11 Jan 2023 06:25:33 +0000 Subject: EG meeting *canceled*, 2022-01-11 Message-ID: <2107866A-AE76-46AD-8D4F-542F579B353D@oracle.com> No new traffic across the winter break, so we'll skip the meeting this week. I think we'll be ready with some updates by next time, stay tuned... From daniel.smith at oracle.com Wed Jan 11 06:26:21 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 11 Jan 2023 06:26:21 +0000 Subject: EG meeting *canceled*, 2022-01-11 In-Reply-To: <2107866A-AE76-46AD-8D4F-542F579B353D@oracle.com> References: <2107866A-AE76-46AD-8D4F-542F579B353D@oracle.com> Message-ID: Err, that's ***2023***-01-11, of course. ;-) > On Jan 10, 2023, at 10:25 PM, Dan Smith wrote: > > No new traffic across the winter break, so we'll skip the meeting this week. I think we'll be ready with some updates by next time, stay tuned... From forax at univ-mlv.fr Wed Jan 11 13:23:45 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 11 Jan 2023 14:23:45 +0100 (CET) Subject: Q-types are dead, long live non-null side attributes ! Message-ID: <2134190253.82963066.1673443425625.JavaMail.zimbra@u-pem.fr> Hi everybody, i would like to propose a slightly different semantics for Valhalla which is more backward compatible than the current one and that follows the vision of Brian that a non null zero-default value type is equivalent to what we currently what we call the .val mirror of a primitive class. Why do we need Q-types ? (1) to indicate that a field can be flattened, (2) to indicate that a method parameter can be called "by value", (3) to indicate that an array can be flattened, (4) to indicate the type argument of a universal generics. What is the problem with a Q-type ? Sadly we do not have all these benefits without paying a price. - a Q-type encodes compile time information not runtime information, so it does not support separate compilation (especially if Q-type is not compatible with its equivalent L-type), - a Q-type can not be erased. Erasure helps a lot adoptions when both use-site and declaration-site need to be updated to follow a new protocol. I propose to encode the same information as a Q-type using a side attribute instead to avoid the problems raised by the Q-type notation. A Q-type is use site notation equivalent to a L-type (a class name) + a non-null bit. I propose to store the non-null bit into a separate attribute associated to a field or a method declaration. For cover the use-cases (1) and (2) but not (3) and (4). In fact (3) and (4) are the same use-case, we need to create a specialized generics or an array specialized by a non-null type. In both case, the specialised array/generics is a runtime construction so we do not need a descriptor for it but a way to inject a runtime class of a non-null type (the secondary class as this is actually called in the prototype) as a descriptor. The parametric VM design proposed by John already propose such mechanism. Using a side attribute (on methods and fields) to record the nullability information greatly simplify the classfile verifier, because the verifier does not need to be aware of the side attribute. A worst the VM will throw a NPE at runtime. It makes the VM implementation slightly more complex because, - when calling a method, the VM (the interpreter) needs to checks the side attribute and emits a NPE accordingly - when storing a value inside a field, the VM needs to check the side attribute and if the field type is a zero-default value type at runtime and emits a NPE in that case (the VM already does the same thing for arrays). The JIT has the same information as before, - a field can be flattened if the type is zero-default value type at runtime and the non-null bit is set, - an argument can be passed by value if the type is a zero-default value type at runtime and the non-null bit is set, - a local variable of a zero-default value type at runtime + a nullcheck is scalarizable. I've implemented a prototype (John asks for it) of this semantics on top of the LW5 prototype, https://github.com/forax/civilizer It uses annotations, both at declaration site (@Value and @ZeroDefault) and use site (@NonNull and @Nullable) + bytecode rewriting because it's easier than modifying the compiler and the VM. - The nullchecks of the parameter is done by adding calls to Objects.requireNonNull() at the beginning of the methods, - The nullcheck of the field is done by declaring it with a Q-type + rewriting the access to the field using invokedynamic, so the access are done using L-types. Q-types are dead, long live non-null side attributes ! regards, R?mi From daniel.smith at oracle.com Wed Jan 11 19:46:51 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 11 Jan 2023 19:46:51 +0000 Subject: Q-types are dead, long live non-null side attributes ! In-Reply-To: <2134190253.82963066.1673443425625.JavaMail.zimbra@u-pem.fr> References: <2134190253.82963066.1673443425625.JavaMail.zimbra@u-pem.fr> Message-ID: <1EDCBCCA-5BA6-4B87-8503-9FDC942E8161@oracle.com> Yes, we've noticed the advantages of such a strategy independently. It aligns well with our plans for specialization, which push everything into a side channel (a 'T' always erases to a 'LObject' descriptor, and the specialized type information is in a side channel). There are some difficulties?one significant problem is how to handle overriding, especially in the special case that an inherited class method overrides an interface method. The downsides may end up outweighing the benefits. But we'll have to compare notes and see what you've learned. > On Jan 11, 2023, at 5:23 AM, Remi Forax wrote: > > Hi everybody, i would like to propose a slightly different semantics for Valhalla which is more backward compatible than the current one and that follows the vision of Brian that a non null zero-default value type is equivalent to what we currently what we call the .val mirror of a primitive class. > > Why do we need Q-types ? > (1) to indicate that a field can be flattened, > (2) to indicate that a method parameter can be called "by value", > (3) to indicate that an array can be flattened, > (4) to indicate the type argument of a universal generics. > > What is the problem with a Q-type ? > Sadly we do not have all these benefits without paying a price. > - a Q-type encodes compile time information not runtime information, so it does not support separate compilation > (especially if Q-type is not compatible with its equivalent L-type), > - a Q-type can not be erased. Erasure helps a lot adoptions when both use-site and declaration-site need to be updated to follow a new protocol. > > I propose to encode the same information as a Q-type using a side attribute instead to avoid the problems raised by the Q-type notation. > > A Q-type is use site notation equivalent to a L-type (a class name) + a non-null bit. I propose to store the non-null bit into a separate attribute associated to a field or a method declaration. > For cover the use-cases (1) and (2) but not (3) and (4). > > In fact (3) and (4) are the same use-case, we need to create a specialized generics or an array specialized by a non-null type. In both case, the specialised array/generics is a runtime construction so we do not need a descriptor for it but a way to inject a runtime class of a non-null type (the secondary class as this is actually called in the prototype) as a descriptor. The parametric VM design proposed by John already propose such mechanism. > > Using a side attribute (on methods and fields) to record the nullability information greatly simplify the classfile verifier, because the verifier does not need to be aware of the side attribute. A worst the VM will throw a NPE at runtime. > > It makes the VM implementation slightly more complex because, > - when calling a method, the VM (the interpreter) needs to checks the side attribute and emits a NPE accordingly > - when storing a value inside a field, the VM needs to check the side attribute and if the field type is a zero-default value type at runtime and emits a NPE in that case (the VM already does the same thing for arrays). > > The JIT has the same information as before, > - a field can be flattened if the type is zero-default value type at runtime and the non-null bit is set, > - an argument can be passed by value if the type is a zero-default value type at runtime and the non-null bit is set, > - a local variable of a zero-default value type at runtime + a nullcheck is scalarizable. > > I've implemented a prototype (John asks for it) of this semantics on top of the LW5 prototype, > https://github.com/forax/civilizer > > It uses annotations, both at declaration site (@Value and @ZeroDefault) and use site (@NonNull and @Nullable) + bytecode rewriting because it's easier than modifying the compiler and the VM. > - The nullchecks of the parameter is done by adding calls to Objects.requireNonNull() at the beginning of the methods, > - The nullcheck of the field is done by declaring it with a Q-type + rewriting the access to the field using invokedynamic, so the access are done using L-types. > > Q-types are dead, long live non-null side attributes ! > > regards, > R?mi > > From forax at univ-mlv.fr Wed Jan 11 21:30:13 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 11 Jan 2023 22:30:13 +0100 (CET) Subject: Q-types are dead, long live non-null side attributes ! In-Reply-To: <1EDCBCCA-5BA6-4B87-8503-9FDC942E8161@oracle.com> References: <2134190253.82963066.1673443425625.JavaMail.zimbra@u-pem.fr> <1EDCBCCA-5BA6-4B87-8503-9FDC942E8161@oracle.com> Message-ID: <1261019692.83229527.1673472613954.JavaMail.zimbra@u-pem.fr> ----- Original Message ----- > From: "daniel smith" > To: "Remi Forax" > Cc: "valhalla-spec-experts" > Sent: Wednesday, January 11, 2023 8:46:51 PM > Subject: Re: Q-types are dead, long live non-null side attributes ! > Yes, we've noticed the advantages of such a strategy independently. It aligns > well with our plans for specialization, which push everything into a side > channel (a 'T' always erases to a 'LObject' descriptor, and the specialized > type information is in a side channel). > > There are some difficulties?one significant problem is how to handle overriding, > especially in the special case that an inherited class method overrides an > interface method. The downsides may end up outweighing the benefits. But we'll > have to compare notes and see what you've learned. I believe we have to solve the overriding/calling convention adaptation issue you are talking about (for the record, i don't know how to, i'm even sure to fully understand it) because i'm pretty sure we will have the same issue with generics specialization anyway. So backtracking may not be an option. R?mi > >> On Jan 11, 2023, at 5:23 AM, Remi Forax wrote: >> >> Hi everybody, i would like to propose a slightly different semantics for >> Valhalla which is more backward compatible than the current one and that >> follows the vision of Brian that a non null zero-default value type is >> equivalent to what we currently what we call the .val mirror of a primitive >> class. >> >> Why do we need Q-types ? >> (1) to indicate that a field can be flattened, >> (2) to indicate that a method parameter can be called "by value", >> (3) to indicate that an array can be flattened, >> (4) to indicate the type argument of a universal generics. >> >> What is the problem with a Q-type ? >> Sadly we do not have all these benefits without paying a price. >> - a Q-type encodes compile time information not runtime information, so it does >> not support separate compilation >> (especially if Q-type is not compatible with its equivalent L-type), >> - a Q-type can not be erased. Erasure helps a lot adoptions when both use-site >> and declaration-site need to be updated to follow a new protocol. >> >> I propose to encode the same information as a Q-type using a side attribute >> instead to avoid the problems raised by the Q-type notation. >> >> A Q-type is use site notation equivalent to a L-type (a class name) + a non-null >> bit. I propose to store the non-null bit into a separate attribute associated >> to a field or a method declaration. >> For cover the use-cases (1) and (2) but not (3) and (4). >> >> In fact (3) and (4) are the same use-case, we need to create a specialized >> generics or an array specialized by a non-null type. In both case, the >> specialised array/generics is a runtime construction so we do not need a >> descriptor for it but a way to inject a runtime class of a non-null type (the >> secondary class as this is actually called in the prototype) as a descriptor. >> The parametric VM design proposed by John already propose such mechanism. >> >> Using a side attribute (on methods and fields) to record the nullability >> information greatly simplify the classfile verifier, because the verifier does >> not need to be aware of the side attribute. A worst the VM will throw a NPE at >> runtime. >> >> It makes the VM implementation slightly more complex because, >> - when calling a method, the VM (the interpreter) needs to checks the side >> attribute and emits a NPE accordingly >> - when storing a value inside a field, the VM needs to check the side attribute >> and if the field type is a zero-default value type at runtime and emits a NPE >> in that case (the VM already does the same thing for arrays). >> >> The JIT has the same information as before, >> - a field can be flattened if the type is zero-default value type at runtime and >> the non-null bit is set, >> - an argument can be passed by value if the type is a zero-default value type at >> runtime and the non-null bit is set, >> - a local variable of a zero-default value type at runtime + a nullcheck is >> scalarizable. >> >> I've implemented a prototype (John asks for it) of this semantics on top of the >> LW5 prototype, >> https://github.com/forax/civilizer >> >> It uses annotations, both at declaration site (@Value and @ZeroDefault) and use >> site (@NonNull and @Nullable) + bytecode rewriting because it's easier than >> modifying the compiler and the VM. >> - The nullchecks of the parameter is done by adding calls to >> Objects.requireNonNull() at the beginning of the methods, >> - The nullcheck of the field is done by declaring it with a Q-type + rewriting >> the access to the field using invokedynamic, so the access are done using >> L-types. >> >> Q-types are dead, long live non-null side attributes ! >> >> regards, >> R?mi >> From mcnepp02 at googlemail.com Sat Jan 21 11:14:50 2023 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Sat, 21 Jan 2023 12:14:50 +0100 Subject: Q-types are dead, long live non-null side attributes Message-ID: <6ea858bd-ee0b-8cda-388b-750fd3726b9e@gmail.com> Hi, looks like a great idea to me - which is no wonder because I propsed it back in June 2021 already, as this posting proves: https://mail.openjdk.org/pipermail/valhalla-spec-observers/2021-June/001527.html In that text, I wrote something very similar to Remi's reasoning: "do we really need to have two different type-mirrors corresponding to these descriptors? Isn't the "Q-ness" rather a property of the Field, method Parameter or method return-type, and therefore should be available there via reflection as a simple boolean property?" -------------- next part -------------- An HTML attachment was scrubbed... URL: From forax at univ-mlv.fr Sat Jan 21 13:50:43 2023 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Sat, 21 Jan 2023 14:50:43 +0100 (CET) Subject: Q-types are dead, long live non-null side attributes In-Reply-To: <6ea858bd-ee0b-8cda-388b-750fd3726b9e@gmail.com> References: <6ea858bd-ee0b-8cda-388b-750fd3726b9e@gmail.com> Message-ID: <560816316.2755072.1674309043862.JavaMail.zimbra@u-pem.fr> > From: "Gernot Neppert" > To: "Valhalla Expert Group Observers" > , "Remi Forax" > Sent: Saturday, January 21, 2023 12:14:50 PM > Subject: Q-types are dead, long live non-null side attributes > Hi, > looks like a great idea to me - which is no wonder because I propsed it back in > June 2021 already, as this posting proves: > [ > https://mail.openjdk.org/pipermail/valhalla-spec-observers/2021-June/001527.html > | > https://mail.openjdk.org/pipermail/valhalla-spec-observers/2021-June/001527.html > ] > In that text, I wrote something very similar to Remi's reasoning: > "do we really need to have two different type-mirrors corresponding > to these descriptors? > Isn't the "Q-ness" rather a property of the Field, method Parameter or > method return-type, and therefore should be available there via > reflection as a simple boolean property?" Hi Gernot, there is a subtle difference, what you are describing is a model based on a field/method property while the proposed model goes a step further and also defines the nullability on types. This is important because we want to be able to flatten the array of an ArrayList<@Nullable Complex>. Something we can not represent with only a boolean property on fields/methods. regards, R?mi -------------- next part -------------- An HTML attachment was scrubbed... URL: From mcnepp02 at googlemail.com Sat Jan 21 14:32:30 2023 From: mcnepp02 at googlemail.com (Gernot Neppert) Date: Sat, 21 Jan 2023 15:32:30 +0100 Subject: Q-types are dead, long live non-null side attributes In-Reply-To: <560816316.2755072.1674309043862.JavaMail.zimbra@u-pem.fr> References: <6ea858bd-ee0b-8cda-388b-750fd3726b9e@gmail.com> <560816316.2755072.1674309043862.JavaMail.zimbra@u-pem.fr> Message-ID: <2dc48bdd-93ce-5b76-a535-3e15138364c7@gmail.com> Am 21.01.2023 um 14:50 schrieb forax at univ-mlv.fr: > > > ------------------------------------------------------------------------ > > *From: *"Gernot Neppert" > *To: *"Valhalla Expert Group Observers" > , "Remi Forax" > > *Sent: *Saturday, January 21, 2023 12:14:50 PM > *Subject: *Q-types are dead, long live non-null side attributes > > Hi, > > looks like a great idea to me - which is no wonder because I > propsed it back in June 2021 already, as this posting proves: > > https://mail.openjdk.org/pipermail/valhalla-spec-observers/2021-June/001527.html > > In that text, I wrote something very similar to Remi's reasoning: > > "do we really need to have two different type-mirrors corresponding > to these descriptors? > Isn't the "Q-ness" rather a property of the Field, method Parameter or > method return-type, and therefore should be available there via > reflection as a simple boolean property?" > > > Hi Gernot, > there is a subtle difference, what you are describing is a model based > on a field/method property while the proposed model goes a step > further and also defines the nullability on types. > > This is important because we want to be able to flatten the array of > an ArrayList<@Nullable Complex>. Something we can not represent with > only a boolean property on fields/methods. > > regards, > R?mi > Of course there are subtle differences, there always are :) But the common ground of both proposals - and IMO a crucial difference to the approach that was taken in Valhalla so far - is this: Move away from burdening the type-declaration of value/primitive classes with so many implications on its use-sites. Also, do away with two different type-mirrors for primitive classes. Rather, request specific behaviour at the use-sites (parameter declarations, return-types etc.) BTW, I also proposed @Nullable (alternatively @ByRef) and its antagonist @ByValue. I also made a propsal on the overriding issue there: https://mail.openjdk.org/pipermail/valhalla-spec-comments/2021-November/000024.html Regards, Gernot -------------- next part -------------- An HTML attachment was scrubbed... URL: From daniel.smith at oracle.com Tue Jan 24 23:39:48 2023 From: daniel.smith at oracle.com (Dan Smith) Date: Tue, 24 Jan 2023 23:39:48 +0000 Subject: EG meeting *canceled*, 2023-01-25 Message-ID: <893A4AEA-01AE-4F01-912A-F80516A58D38@oracle.com> Well, I was hoping to have a writeup to share, but I've had some distractions and haven't gotten there yet (working on a home remodel...). So no meeting this Wednesday. I'll shoot for next time, with some lead time for people to review before we meet. From forax at univ-mlv.fr Tue Jan 31 10:25:42 2023 From: forax at univ-mlv.fr (Remi Forax) Date: Tue, 31 Jan 2023 11:25:42 +0100 (CET) Subject: Minimal Parametric VM ? Message-ID: <930885049.9309677.1675160742813.JavaMail.zimbra@u-pem.fr> Hi all, I've started to implement a prototype (far from finished) of the parametric VM based on John position paper. https://github.com/forax/civilizer Most of the design is great (even really great) but i think it goes too deep and there is a minimal parametric vm that is hidden inside. By Minimal Parameteric VM, or MPVM, i mean a barebone design which is just enough to able to specialize parametric class and parametric method so a List is using an array Complex instead of an array of Object which seems a nice intermediary goal. So i propose to simplify the design as an intermediary step with the explicit goal that the MPVM should be able to specialize generics over value types, not more. The main difference is that the MPVM does not need to deal with subtyping of parametrized classes, so the opcode checkcast and instanceof does not need to be specialized and calling methods on a parametric class does not require the owner+type parameters to be reified in the bytecode. - The Parametric attribute: A parametric class or a parametric method as declared as such if there is a the class attribute (the method attribute) Parametric is defined. You can not have more than one Parametric attribute by class/method. Parametric_attribute { u2 attribute_name_index; // Parametric u4 attribute_length; u2 anchor_index; } A parametric attribute references a CONSTANT_Anchor_info that after resolution stores a couple of Objects, the first one is the class parameter, the second one is the method parameter. It works that way. CONSTANT_Anchor_info { u1 tag; // CONSTANT_Anchor = 21 u2 bootstrap_method_attr_index; at runtime, CallSite.target: MH (Anchor)Anchor } When a parametric class/parametric method is instantiated with a parameter, the VM creates an Anchor object containing the parameter. The bootstrap method of the CONSTANT_Anchor_info is called to get a method handle (that takes an Anchor and returns an Anchor). The target of the BSM is called with the anchor created by the VM and here the jdk code can erase the parameter or do whatever should be done. The resulting Anchor is stored as result in a constant pool (it becomes a loadable constant that can be referenced by ldc or bootstrap method constants). The Anchor object is a value record: value record Anchor(Object parameter) {} - Parametrized opcodes The opcodes new, aconst_init, anewarray, invokestatic, invokevirtual, invokeinterface and invokespecial can specify a parameter. For that, instead of referencing a CONSTANT_Class_info or an XMethodref, they reference a CONSTANT_Linkage_info that itself reference the right constant CONSTANT_Linkage_info { u1 tag; // JVM_CONSTANT_Linkage = 22 u2 parameter_index; u2 reference_index; // CONSTANT_Class_info or XMethodref } The parameter_index references a loadable constants (the usuals + CONSTANT_Anchor_info). The reference_index references either a CONSTANT_Class_info or an XMethodref depending on the opcode. At runtime, the constant referenced by the parameter_index is a Species object for new, aconst_init and anewarray and a Linkage object for the invoke* opcodes. value record Species(Class raw, Object parameters) {} value record Linkage(Object parameters) {} A species object is defined by a runtime class (so it can represent classes that only available at runtime like the secondary type of a zero default value class) and a parameter. A linkage object only store a parameter. value record Species(Class raw, Object parameters) {} value record Linkage(Object parameters) {} Chain of constants and runtime representation depending on the opcode: new (CONSTANT_Linkage_info -> CONSTANT_Class_info), at runtime Species aconst_init (CONSTANT_Linkage_info -> CONSTANT_Class_info), at runtime Species anewarray (CONSTANT_Linkage_info -> CONSTANT_Class_info), at runtime Species invokestatic, invokevirtual, invokeinterface, invokespecial (CONSTANT_Linkage_info -> XMethodref) at runtime Linkage(parameters) At runtime, when one of the opcodes new, aconst_init and anewarray is first called, the VM checks that the raw class of the species is parametric, then parameter_index is resolved, then the VM calls the the BSM of the anchor and create a parametric version of the class with the parameter of the Anchor if it does not already exist. This parametric class is stored as the class of the instance created. Ar runtime, when one of the opcodes invoke* is first call, the parameter_index is resolved, the the VM checks that the raw class of the species is parametric, then parameter_index is resolved, then the VM calls the the BSM of the anchor and create a parametric version of the method with the parameter of the Anchor if it does not already exist. - Class Pool segregation Because the Anchors are the roots of the constant dynamic trees, the VM can segregate the constant pool items as described in John's paper. - Class that inherits/implements parametric class A class (parametric or not), can reference parametric class/interfaces, so the supername and interfaces of the class header may reference a CONSTANT_Linkage_info (that itself reference a CONSTANT_Class_info) resolved as a Species at runtime. - Type Restriction In order to avoid type pollution to propagate, fields and method can defined the attribute TypeRestriction that defines restriction (Class at runtime) on the method parameters and field. TypeRestriction_attribute { u2 attribute_name_index; // TypeRestriction u4 attribute_length; u2 restrictions_count; u2 restrictions[restrictions_count]; // at runtime Class } (Note: there is no need of validating return value for the MPVM but the class corresponding to the return type can be present). - Comparaison with John's vision It's the cheap version, it still require a lot of works but it has the advantage of being simpler, less opcodes to change, subtyping is not changed, the callee site does not do more validation and is in my opinion a good first step. R?mi