From forax at univ-mlv.fr Wed May 1 12:57:40 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 1 May 2019 14:57:40 +0200 (CEST) Subject: Is V? what we need ? Message-ID: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> Brian ask me to make it its own thread. so is V? what we need, because i believe we have been a little over our own head on this and loose the sight of what we need for V?. we need V? - to represent the L variation of a Q type. - to interact with generics that are not reified. V? does that but does far more, V? is a super type of V which is dangerous, because people will use it as parameter of function instead of V because it's a super type and works with null. Here we are back to a world were every value types may be null. I believe that the issue is that V? should work as a box and currently V? is to powerful/useful as a box so people will start to use it as a true type. - V? should not be a supertype of V - you should not be able to call methods or fields on V? (constructor are still allowed), again it should be a box, so the automatic conversions from/to V/V? are fine, but not more. the moto for V? should be works like an Integer (not more). R?mi From brian.goetz at oracle.com Wed May 1 13:03:42 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 1 May 2019 09:03:42 -0400 Subject: Is V? what we need ? In-Reply-To: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> Message-ID: <3A326959-15EF-4AEF-8057-9A90925850C2@oracle.com> > we need V? > - to represent the L variation of a Q type. > - to interact with generics that are not reified. These are the proximate causes, but I think this undersells it. > V? does that but does far more, V? is a super type of V which is dangerous, because people will use it as parameter of function instead of V because it's a super type and works with null. > Here we are back to a world were every value types may be null. Whoa, I think you just skipped a few dozen steps ? Perhaps you could clarify this with some examples of ?I worry people will write __ instead of ___, and then __ will happen.? > I believe that the issue is that V? should work as a box and currently V? is to powerful/useful as a box so people will start to use it as a true type. Again, lots to unpack here: - What, in your mind, is the difference between a box and an adjunction? - What benefits do box types give here? - What risks do you envision from ?using V? as a true type?? From maurizio.cimadamore at oracle.com Wed May 1 13:07:41 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 1 May 2019 14:07:41 +0100 Subject: Is V? what we need ? In-Reply-To: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> Message-ID: I agree, in principle - and I have raised similar points in the past, that is: V ~= int V? ~= Integer And have NO subtyping relationship between them; this puts the language on a solid footing, where we reuse existing conversion mechanism to sequence overload resolution and all that. I think what pushed us down this path was perhaps the perceived usability fall back: e.g.? we can no longer pass a V where a V? is expected. But that's not really the case, as you still have assignment conversions between the two, which means it would work on assignment context and method calls (albeit with lower priority w.r.t? true subtypes, which is what we want anyway). Maurizio On 01/05/2019 13:57, Remi Forax wrote: > Brian ask me to make it its own thread. > so is V? what we need, because i believe we have been a little over our own head on this and loose the sight of what we need for V?. > > we need V? > - to represent the L variation of a Q type. > - to interact with generics that are not reified. > > V? does that but does far more, V? is a super type of V which is dangerous, because people will use it as parameter of function instead of V because it's a super type and works with null. > Here we are back to a world were every value types may be null. > > I believe that the issue is that V? should work as a box and currently V? is to powerful/useful as a box so people will start to use it as a true type. > - V? should not be a supertype of V > - you should not be able to call methods or fields on V? (constructor are still allowed), again it should be a box, so the automatic conversions from/to V/V? are fine, but not more. > > the moto for V? should be works like an Integer (not more). > > R?mi From brian.goetz at oracle.com Wed May 1 13:13:06 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 1 May 2019 09:13:06 -0400 Subject: Is V? what we need ? In-Reply-To: References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> Message-ID: <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> But, this is Q-world thinking. In Q-world, values are like primitives, and we therefore need boxes to interoperate with objects. In L-world, values *ARE* Object. The difference is huge, and it takes some time to internalize just how different they are. We?re all in varying degrees of realizing the implications. Boxes are not a good thing; they were a necessarily evil that arises from the fact that primitives are not objects. But they create many problems of their own. I don?t see how ?more boxes? is the answer here. The main argument in favor of ?more boxes? is that ?users are already familiar with the model.? For a while, we thought that was a good thing, but this is mostly Stockholm Syndrome?.. > On May 1, 2019, at 9:07 AM, Maurizio Cimadamore wrote: > > I agree, in principle - and I have raised similar points in the past, that is: > > V ~= int > > V? ~= Integer > > And have NO subtyping relationship between them; this puts the language on a solid footing, where we reuse existing conversion mechanism to sequence overload resolution and all that. > > I think what pushed us down this path was perhaps the perceived usability fall back: e.g. we can no longer pass a V where a V? is expected. But that's not really the case, as you still have assignment conversions between the two, which means it would work on assignment context and method calls (albeit with lower priority w.r.t true subtypes, which is what we want anyway). > > Maurizio > > On 01/05/2019 13:57, Remi Forax wrote: >> Brian ask me to make it its own thread. >> so is V? what we need, because i believe we have been a little over our own head on this and loose the sight of what we need for V?. >> >> we need V? >> - to represent the L variation of a Q type. >> - to interact with generics that are not reified. >> >> V? does that but does far more, V? is a super type of V which is dangerous, because people will use it as parameter of function instead of V because it's a super type and works with null. >> Here we are back to a world were every value types may be null. >> >> I believe that the issue is that V? should work as a box and currently V? is to powerful/useful as a box so people will start to use it as a true type. >> - V? should not be a supertype of V >> - you should not be able to call methods or fields on V? (constructor are still allowed), again it should be a box, so the automatic conversions from/to V/V? are fine, but not more. >> >> the moto for V? should be works like an Integer (not more). >> >> R?mi From forax at univ-mlv.fr Wed May 1 13:19:59 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 1 May 2019 15:19:59 +0200 (CEST) Subject: Is V? what we need ? In-Reply-To: <3A326959-15EF-4AEF-8057-9A90925850C2@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <3A326959-15EF-4AEF-8057-9A90925850C2@oracle.com> Message-ID: <16975171.512084.1556716799732.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Remi Forax" > Cc: "valhalla-spec-experts" > Envoy?: Mercredi 1 Mai 2019 15:03:42 > Objet: Re: Is V? what we need ? >> we need V? >> - to represent the L variation of a Q type. >> - to interact with generics that are not reified. > > These are the proximate causes, but I think this undersells it. > >> V? does that but does far more, V? is a super type of V which is dangerous, >> because people will use it as parameter of function instead of V because it's a >> super type and works with null. >> Here we are back to a world were every value types may be null. > > Whoa, I think you just skipped a few dozen steps ? use the most super type possible for a parameter is the usual rule hence "program to an interface", i don't think i'v skipped a lot of steps. > > Perhaps you could clarify this with some examples of ?I worry people will write > __ instead of ___, and then __ will happen.? i worry people will code as we have told them to code. > >> I believe that the issue is that V? should work as a box and currently V? is to >> powerful/useful as a box so people will start to use it as a true type. > > Again, lots to unpack here: > > - What, in your mind, is the difference between a box and an adjunction? not sure to fully understand the question, is it about the syntax ? > - What benefits do box types give here? a box is a necessary evil, everybody want to write an ArrayList but we are not there yet, so we provide just the right abstraction to deal with value type in generics, not more. > - What risks do you envision from ?using V? as a true type?? V? everywhere where V should be used, or worst, people using V? half of the time, randomly. R?mi From brian.goetz at oracle.com Wed May 1 13:24:42 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 1 May 2019 09:24:42 -0400 Subject: Is V? what we need ? In-Reply-To: <16975171.512084.1556716799732.JavaMail.zimbra@u-pem.fr> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <3A326959-15EF-4AEF-8057-9A90925850C2@oracle.com> <16975171.512084.1556716799732.JavaMail.zimbra@u-pem.fr> Message-ID: <06CB2186-1023-4F4B-B935-5E2C81050294@oracle.com> > > a box is a necessary evil, everybody want to write an ArrayList but we are not there yet, so we provide just the right abstraction to deal with value type in generics, not more. I think this is where we part ways. In Java 1.0, with respect to primitives, a box was a necessary evil, because ints are not Objects. In Q-world, when we thought we couldn?t get away with values being Object, we thought it was a necessary evil again. L-world taught us we don?t need boxes, and that?s a huge weight lifted off our shoulders! Boxes are messy; if they are necessary, we can live with them, but if they are not, why would we want to? There are two paths here: - Cripple values exactly as much as primitives are crippled, and everyone is on an even footing; - Make values what we want everything to be, and catch up later with primitives to the extent we can. But, you?re not making your case, you?re just saying ?I think it should be the other way.? Make the case why the proposed new way is worse! From brian.goetz at oracle.com Wed May 1 13:28:33 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 1 May 2019 09:28:33 -0400 Subject: Is V? what we need ? In-Reply-To: <06CB2186-1023-4F4B-B935-5E2C81050294@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <3A326959-15EF-4AEF-8057-9A90925850C2@oracle.com> <16975171.512084.1556716799732.JavaMail.zimbra@u-pem.fr> <06CB2186-1023-4F4B-B935-5E2C81050294@oracle.com> Message-ID: <30BDD6DD-B0EE-4499-956F-441EEEFA2046@oracle.com> Also, we?re conflating two separate questions here. 1. What does V? mean. In the proposed world, it is the union type of V and Null, nothing more (alternately: V adjoined with null.). 2. What is the relationship between V and V? ? is it sub typing, or conversion? I think Remi is more interested in (2), but you keep saying ?it should be a box?,w which suggests we?re not on the same page with respect to (1) either, yet. > On May 1, 2019, at 9:24 AM, Brian Goetz wrote: > >> >> a box is a necessary evil, everybody want to write an ArrayList but we are not there yet, so we provide just the right abstraction to deal with value type in generics, not more. > > I think this is where we part ways. In Java 1.0, with respect to primitives, a box was a necessary evil, because ints are not Objects. In Q-world, when we thought we couldn?t get away with values being Object, we thought it was a necessary evil again. L-world taught us we don?t need boxes, and that?s a huge weight lifted off our shoulders! > > Boxes are messy; if they are necessary, we can live with them, but if they are not, why would we want to? > > There are two paths here: > - Cripple values exactly as much as primitives are crippled, and everyone is on an even footing; > - Make values what we want everything to be, and catch up later with primitives to the extent we can. > > But, you?re not making your case, you?re just saying ?I think it should be the other way.? Make the case why the proposed new way is worse! From forax at univ-mlv.fr Wed May 1 14:07:25 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 1 May 2019 16:07:25 +0200 (CEST) Subject: Is V? what we need ? In-Reply-To: <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> Message-ID: <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Maurizio Cimadamore" > Cc: "Remi Forax" , "valhalla-spec-experts" > Envoy?: Mercredi 1 Mai 2019 15:13:06 > Objet: Re: Is V? what we need ? > But, this is Q-world thinking. In Q-world, values are like primitives, and we > therefore need boxes to interoperate with objects. In L-world, values *ARE* > Object. The difference is huge, and it takes some time to internalize just how > different they are. We?re all in varying degrees of realizing the > implications. > > Boxes are not a good thing; they were a necessarily evil that arises from the > fact that primitives are not objects. But they create many problems of their > own. I don?t see how ?more boxes? is the answer here. More boxes is a temporary answer until we have fully reified generics because at that point we have generics over value types. Here we want to introduce boxes not because value type are not objects but because value types are not nullable objects but T is a nullable object. So it's a different kind of box, for a different reason but that it should work like a box because our users are already familiar with the box model. > > The main argument in favor of ?more boxes? is that ?users are already familiar > with the model.? For a while, we thought that was a good thing, but this is > mostly Stockholm Syndrome?.. until you think that N? is a temporary evil, in LW1000, when generics are reified using N? with a generics will be a corner case, so there is no reason to make N? powerful to the point they appear in method signature, because at that point it's too late. And yes, it's weird to actually promote for a less powerful semantics for N? but i think it's the right move. R?mi > > > >> On May 1, 2019, at 9:07 AM, Maurizio Cimadamore >> wrote: >> >> I agree, in principle - and I have raised similar points in the past, that is: >> >> V ~= int >> >> V? ~= Integer >> >> And have NO subtyping relationship between them; this puts the language on a >> solid footing, where we reuse existing conversion mechanism to sequence >> overload resolution and all that. >> >> I think what pushed us down this path was perhaps the perceived usability fall >> back: e.g. we can no longer pass a V where a V? is expected. But that's not >> really the case, as you still have assignment conversions between the two, >> which means it would work on assignment context and method calls (albeit with >> lower priority w.r.t true subtypes, which is what we want anyway). >> >> Maurizio >> >> On 01/05/2019 13:57, Remi Forax wrote: >>> Brian ask me to make it its own thread. >>> so is V? what we need, because i believe we have been a little over our own head >>> on this and loose the sight of what we need for V?. >>> >>> we need V? >>> - to represent the L variation of a Q type. >>> - to interact with generics that are not reified. >>> >>> V? does that but does far more, V? is a super type of V which is dangerous, >>> because people will use it as parameter of function instead of V because it's a >>> super type and works with null. >>> Here we are back to a world were every value types may be null. >>> >>> I believe that the issue is that V? should work as a box and currently V? is to >>> powerful/useful as a box so people will start to use it as a true type. >>> - V? should not be a supertype of V >>> - you should not be able to call methods or fields on V? (constructor are still >>> allowed), again it should be a box, so the automatic conversions from/to V/V? >>> are fine, but not more. >>> >>> the moto for V? should be works like an Integer (not more). >>> > >> R?mi From brian.goetz at oracle.com Wed May 1 14:12:05 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 1 May 2019 10:12:05 -0400 Subject: Is V? what we need ? In-Reply-To: <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> Message-ID: <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> >> Boxes are not a good thing; they were a necessarily evil that arises from the >> fact that primitives are not objects. But they create many problems of their >> own. I don?t see how ?more boxes? is the answer here. > > More boxes is a temporary answer until we have fully reified generics because at that point we have generics over value types. I agree that we need a plan for how to both be stable in the short term and long term. But I think ?temporary? is a fantasy! Whatever we add now, is part of Java forever. So we should add the types that make sense both now and later. Boxes are a temporary crutch; if we decide to go with them, we have to be honest ? it?s boxes forever, until the end of time. The V? story is a more stable long-term story. (But if you have a better one, we?re listening.). > Here we want to introduce boxes not because value type are not objects but because value types are not nullable objects but T is a nullable object. You?re assuming the utility of V? after reification is zero, but that?s not the case. For example, suppose ArrayList is reified. Then the user gets the choice of erasure or reification by selecting ArrayList or ArrayList. Erasure has a bad rap, but sometimes it is desirable. > So it's a different kind of box, for a different reason but that it should work like a box because our users are already familiar with the box model. I think we have to stop using the word box, because it seems very difficult to have a conversation when we?re not agreeing on what ?box? means. From forax at univ-mlv.fr Wed May 1 14:15:27 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 1 May 2019 16:15:27 +0200 (CEST) Subject: Is V? what we need ? In-Reply-To: <06CB2186-1023-4F4B-B935-5E2C81050294@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <3A326959-15EF-4AEF-8057-9A90925850C2@oracle.com> <16975171.512084.1556716799732.JavaMail.zimbra@u-pem.fr> <06CB2186-1023-4F4B-B935-5E2C81050294@oracle.com> Message-ID: <1820404895.514656.1556720127156.JavaMail.zimbra@u-pem.fr> > De: "Brian Goetz" > ?: "Remi Forax" > Cc: "valhalla-spec-experts" > Envoy?: Mercredi 1 Mai 2019 15:24:42 > Objet: Re: Is V? what we need ? >> a box is a necessary evil, everybody want to write an ArrayList but we are >> not there yet, so we provide just the right abstraction to deal with value type >> in generics, not more. > I think this is where we part ways. In Java 1.0, with respect to primitives, a > box was a necessary evil, because ints are not Objects. In Q-world, when we > thought we couldn?t get away with values being Object, we thought it was a > necessary evil again. L-world taught us we don?t need boxes, and that?s a huge > weight lifted off our shoulders! > Boxes are messy; if they are necessary, we can live with them, but if they are > not, why would we want to? > There are two paths here: > - Cripple values exactly as much as primitives are crippled, and everyone is on > an even footing; > - Make values what we want everything to be, and catch up later with primitives > to the extent we can. > But, you?re not making your case, you?re just saying ?I think it should be the > other way.? Make the case why the proposed new way is worse! As i said, it's not cripling value type, the underlying semantics of L and Q is the same, it's finding the right semantics for representing nullable value type, something we don't want to appear in the signature of methods, so it's crippling nullable vlue type but until we have fully reified generics, at that point nobody will care about nullable value type anymore. R?mi From dl at cs.oswego.edu Wed May 1 14:32:18 2019 From: dl at cs.oswego.edu (Doug Lea) Date: Wed, 1 May 2019 10:32:18 -0400 Subject: Is V? what we need ? In-Reply-To: <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> Message-ID: <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> On 5/1/19 10:12 AM, Brian Goetz wrote: > > You?re assuming the utility of V? after reification is zero, but > that?s not the case. For example, suppose ArrayList is reified. Then > the user gets the choice of erasure or reification by selecting > ArrayList or ArrayList. Erasure has a bad rap, but sometimes > it is desirable. As I tried but failed to get across in post on sorting, choosing V vs V? can lead to 5X cost differences in *either direction* for common aggregate (collection and array) operations. So programmers will need to learn some of these consequences. (Which is made harder/worse here because the cost tradeoffs will probably change over time as VM support improves.) Which is mainly an argument for Brian's position, except for those who believe that Java programmers should not have to encounter these kinds of issues that C++, C#, OCAML, etc programmers face all the time; betting that somehow VMs will make the right choice. (Maybe this is not the right time to mention this, but most other languages supporting this range of use have a middle-ground of call-by-ref for extracting small parts of large things, as seen in comparators, hash-codes, etc that can make a big performance difference. I expect people will complain about not supporting this.) -Doug From brian.goetz at oracle.com Wed May 1 14:39:59 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 1 May 2019 10:39:59 -0400 Subject: Is V? what we need ? In-Reply-To: <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> Message-ID: <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> This is the point I?ve been failing to get across to Remi as well. Suppose you have a big value, and you want a sparse ArrayList of that value? You need a way to say ?Arraylist of BigValue, but not flattened.? And that?s a use-site concern. ArrayList gives you that. Which is to say: the claim that V? is useless once we have reified generics is simply untrue. > On May 1, 2019, at 10:32 AM, Doug Lea
wrote: > > On 5/1/19 10:12 AM, Brian Goetz wrote: >> >> You?re assuming the utility of V? after reification is zero, but >> that?s not the case. For example, suppose ArrayList is reified. Then >> the user gets the choice of erasure or reification by selecting >> ArrayList or ArrayList. Erasure has a bad rap, but sometimes >> it is desirable. > > As I tried but failed to get across in post on sorting, choosing V vs V? > can lead to 5X cost differences in *either direction* for common > aggregate (collection and array) operations. So programmers will need to > learn some of these consequences. (Which is made harder/worse here > because the cost tradeoffs will probably change over time as VM support > improves.) > > Which is mainly an argument for Brian's position, except for those who > believe that Java programmers should not have to encounter these kinds > of issues that C++, C#, OCAML, etc programmers face all the time; > betting that somehow VMs will make the right choice. > > (Maybe this is not the right time to mention this, but most other > languages supporting this range of use have a middle-ground of > call-by-ref for extracting small parts of large things, as seen in > comparators, hash-codes, etc that can make a big performance difference. > I expect people will complain about not supporting this.) > > -Doug > > > From forax at univ-mlv.fr Wed May 1 14:46:55 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 1 May 2019 16:46:55 +0200 (CEST) Subject: Is V? what we need ? In-Reply-To: <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> Message-ID: <644773187.516604.1556722015375.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Remi Forax" > Cc: "Maurizio Cimadamore" , "valhalla-spec-experts" > > Envoy?: Mercredi 1 Mai 2019 16:12:05 > Objet: Re: Is V? what we need ? >>> Boxes are not a good thing; they were a necessarily evil that arises from the >>> fact that primitives are not objects. But they create many problems of their >>> own. I don?t see how ?more boxes? is the answer here. >> >> More boxes is a temporary answer until we have fully reified generics because at >> that point we have generics over value types. > > I agree that we need a plan for how to both be stable in the short term and long > term. But I think ?temporary? is a fantasy! Whatever we add now, is part of > Java forever. So we should add the types that make sense both now and later. I fully agree, it's like getting ride of Integer, it's a fantasy, but not having a lot of API taking a N? as parameter type make that fantasy actually possible for the libraries you care. > > Boxes are a temporary crutch; if we decide to go with them, we have to be honest > ? it?s boxes forever, until the end of time. The V? story is a more stable > long-term story. (But if you have a better one, we?re listening.). > >> Here we want to introduce boxes not because value type are not objects but >> because value types are not nullable objects but T is a nullable object. > > You?re assuming the utility of V? after reification is zero, but that?s not the > case. For example, suppose ArrayList is reified. Then the user gets the choice > of erasure or reification by selecting ArrayList or ArrayList. Erasure > has a bad rap, but sometimes it is desirable. V? as box allow that too. As i said there are two use cases for V?, not yet reified generics is one, backward compat is the other. Both semantics of V? give you backward compat, but do we we agree that this is a corner case. That why i don't want V? to be too powerful, because once generics are reified, the only use case that stay is backward compatibility, and for that the box semantics is enough. > >> So it's a different kind of box, for a different reason but that it should work >> like a box because our users are already familiar with the box model. > > I think we have to stop using the word box, because it seems very difficult to > have a conversation when we?re not agreeing on what ?box? means. yes and no. Part of the appeal of the proposal is that if we cripple N? so remove the subtyping relation and this is debatable, i think also the capability to call fields/methods on it, the semantics is the same a classical box from the type system POV, you have auto-boxing, overloaded methods are resolved in a second pass (preferring V to V?), etc. So it's not a box by its runtime capability, it's a nullable value type at runtime, but by how it interacts with the Java type system. Let's call it a coffer if you prefer, i.e. it's like a box but for our precious value type. R?mi From brian.goetz at oracle.com Wed May 1 14:50:53 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 1 May 2019 10:50:53 -0400 Subject: Is V? what we need ? In-Reply-To: <644773187.516604.1556722015375.JavaMail.zimbra@u-pem.fr> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <644773187.516604.1556722015375.JavaMail.zimbra@u-pem.fr> Message-ID: <9E44D846-A446-475A-956F-E23D7DAE12DF@oracle.com> > > I fully agree, it's like getting ride of Integer, it's a fantasy, but not having a lot of API taking a N? as parameter type make that fantasy actually possible for the libraries you care. We can?t get rid of Integer, but maybe we can make it 10x less important. That would be winning. > V? as box allow that too. As i said there are two use cases for V?, not yet reified generics is one, backward compat is the other. UndefinedTermException: ?box? is ambiguous > Part of the appeal of the proposal is that if we cripple N? so remove the subtyping relation and this is debatable, i think also the capability to call fields/methods on it, the semantics is the same a classical box from the type system POV Classic boxes have accidental identity. Are you really proposing that we take the accidental-identity problem from these eight types, and give them to all values? Yuck! Please, let?s be more specific about what you mean by box. From forax at univ-mlv.fr Wed May 1 14:52:33 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 1 May 2019 16:52:33 +0200 (CEST) Subject: Is V? what we need ? In-Reply-To: <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> Message-ID: <1815663347.516939.1556722353165.JavaMail.zimbra@u-pem.fr> Actually, you are more on my side because what i'm proposing make V? less present in public methods of API, which i think is a good move in term of perf model and for ArryList, both proposal work the same. R?mi ----- Mail original ----- > De: "Doug Lea"
> ?: "valhalla-spec-experts" > Envoy?: Mercredi 1 Mai 2019 16:32:18 > Objet: Re: Is V? what we need ? > On 5/1/19 10:12 AM, Brian Goetz wrote: >> >> You?re assuming the utility of V? after reification is zero, but >> that?s not the case. For example, suppose ArrayList is reified. Then >> the user gets the choice of erasure or reification by selecting >> ArrayList or ArrayList. Erasure has a bad rap, but sometimes >> it is desirable. > > As I tried but failed to get across in post on sorting, choosing V vs V? > can lead to 5X cost differences in *either direction* for common > aggregate (collection and array) operations. So programmers will need to > learn some of these consequences. (Which is made harder/worse here > because the cost tradeoffs will probably change over time as VM support > improves.) > > Which is mainly an argument for Brian's position, except for those who > believe that Java programmers should not have to encounter these kinds > of issues that C++, C#, OCAML, etc programmers face all the time; > betting that somehow VMs will make the right choice. > > (Maybe this is not the right time to mention this, but most other > languages supporting this range of use have a middle-ground of > call-by-ref for extracting small parts of large things, as seen in > comparators, hash-codes, etc that can make a big performance difference. > I expect people will complain about not supporting this.) > > -Doug From forax at univ-mlv.fr Wed May 1 14:54:30 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 1 May 2019 16:54:30 +0200 (CEST) Subject: Is V? what we need ? In-Reply-To: <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> Message-ID: <1140674150.517050.1556722470338.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Doug Lea"
> Cc: "valhalla-spec-experts" > Envoy?: Mercredi 1 Mai 2019 16:39:59 > Objet: Re: Is V? what we need ? > This is the point I?ve been failing to get across to Remi as well. Suppose you > have a big value, and you want a sparse ArrayList of that value? You need a > way to say ?Arraylist of BigValue, but not flattened.? And that?s a use-site > concern. ArrayList gives you that. > > Which is to say: the claim that V? is useless once we have reified generics is > simply untrue. i've said this is a corner case, anyway i don't get this example given that both our proposal work the same on this example, N? is the L view of a value type in both proposal, we only differ on the way we interact with the type system, at the VM level, both proposal are equals. R?mi > >> On May 1, 2019, at 10:32 AM, Doug Lea
wrote: >> >> On 5/1/19 10:12 AM, Brian Goetz wrote: >>> >>> You?re assuming the utility of V? after reification is zero, but >>> that?s not the case. For example, suppose ArrayList is reified. Then >>> the user gets the choice of erasure or reification by selecting >>> ArrayList or ArrayList. Erasure has a bad rap, but sometimes >>> it is desirable. >> >> As I tried but failed to get across in post on sorting, choosing V vs V? >> can lead to 5X cost differences in *either direction* for common >> aggregate (collection and array) operations. So programmers will need to >> learn some of these consequences. (Which is made harder/worse here >> because the cost tradeoffs will probably change over time as VM support >> improves.) >> >> Which is mainly an argument for Brian's position, except for those who >> believe that Java programmers should not have to encounter these kinds >> of issues that C++, C#, OCAML, etc programmers face all the time; >> betting that somehow VMs will make the right choice. >> >> (Maybe this is not the right time to mention this, but most other >> languages supporting this range of use have a middle-ground of >> call-by-ref for extracting small parts of large things, as seen in >> comparators, hash-codes, etc that can make a big performance difference. >> I expect people will complain about not supporting this.) >> >> -Doug >> >> From maurizio.cimadamore at oracle.com Wed May 1 18:12:17 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 1 May 2019 19:12:17 +0100 Subject: Is V? what we need ? In-Reply-To: <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> Message-ID: <44db19d4-84bc-5b10-e9d6-e795b96e2ff7@oracle.com> I agree with Brian that most of the 'conversion-like' nature we see in V to V? is likely associated with Q-thinking, after having been a victim of it myself in a private conversation :-) However, I think my more general point remains - the fact that the VM has the flexibility to treat V and V? as, fundamentally, the same thing shouldn't necessarily drive the conclusion that, _at the language level_ there should be a subtyping relationship between V and V?. From a pedagogical perspective, whether we like it or not, users are immediately going to think in terms of box/unbox, so I think it'd be surprising if the new inline classes and their projections had rules radically different from those which apply to the int/Integer case. Maurizio On 01/05/2019 14:13, Brian Goetz wrote: > But, this is Q-world thinking. In Q-world, values are like primitives, and we therefore need boxes to interoperate with objects. In L-world, values *ARE* Object. The difference is huge, and it takes some time to internalize just how different they are. We?re all in varying degrees of realizing the implications. > > Boxes are not a good thing; they were a necessarily evil that arises from the fact that primitives are not objects. But they create many problems of their own. I don?t see how ?more boxes? is the answer here. > > The main argument in favor of ?more boxes? is that ?users are already familiar with the model.? For a while, we thought that was a good thing, but this is mostly Stockholm Syndrome?.. > > > >> On May 1, 2019, at 9:07 AM, Maurizio Cimadamore wrote: >> >> I agree, in principle - and I have raised similar points in the past, that is: >> >> V ~= int >> >> V? ~= Integer >> >> And have NO subtyping relationship between them; this puts the language on a solid footing, where we reuse existing conversion mechanism to sequence overload resolution and all that. >> >> I think what pushed us down this path was perhaps the perceived usability fall back: e.g. we can no longer pass a V where a V? is expected. But that's not really the case, as you still have assignment conversions between the two, which means it would work on assignment context and method calls (albeit with lower priority w.r.t true subtypes, which is what we want anyway). >> >> Maurizio >> >> On 01/05/2019 13:57, Remi Forax wrote: >>> Brian ask me to make it its own thread. >>> so is V? what we need, because i believe we have been a little over our own head on this and loose the sight of what we need for V?. >>> >>> we need V? >>> - to represent the L variation of a Q type. >>> - to interact with generics that are not reified. >>> >>> V? does that but does far more, V? is a super type of V which is dangerous, because people will use it as parameter of function instead of V because it's a super type and works with null. >>> Here we are back to a world were every value types may be null. >>> >>> I believe that the issue is that V? should work as a box and currently V? is to powerful/useful as a box so people will start to use it as a true type. >>> - V? should not be a supertype of V >>> - you should not be able to call methods or fields on V? (constructor are still allowed), again it should be a box, so the automatic conversions from/to V/V? are fine, but not more. >>> >>> the moto for V? should be works like an Integer (not more). >>> >>> R?mi From brian.goetz at oracle.com Wed May 1 19:34:22 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 1 May 2019 15:34:22 -0400 Subject: Is V? what we need ? In-Reply-To: <44db19d4-84bc-5b10-e9d6-e795b96e2ff7@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <44db19d4-84bc-5b10-e9d6-e795b96e2ff7@oracle.com> Message-ID: <031bc01d-9e63-3349-3e3e-92971da37c47@oracle.com> > However, I think my more general point remains - the fact that the VM > has the flexibility to treat V and V? as, fundamentally, the same > thing shouldn't necessarily drive the conclusion that, _at the > language level_ there should be a subtyping relationship between V and > V?. > > From a pedagogical perspective, whether we like it or not, users are > immediately going to think in terms of box/unbox, so I think it'd be > surprising if the new inline classes and their projections had rules > radically different from those which apply to the int/Integer case. I agree that users are going to first reach for the box/unbox intuition.? So let's talk about what's going to happen there. Let's assume that `V` translates to `QV` and `V?` translates to `LV`; let's compare the language we get under a subtyping relationship or a boxing conversion.? (Either way, we get V? <: Object.) The box intuition says you can lock on a box (though we discourage it.)? But locking on a V? will result in an exception.? (Same for wait/notify.) The box intuition says that == on a box is an identity comparison. But a V? has no identity (it did in Q-world, not in L-world.) The box intuition says you can create a weak reference of a box. But you cannot for a value. So there are multiple ways in which the box intuition _already_ leads users down the wrong road, regardless of whether it is subtyping or not. One big difference between whether we convert V to V? via subsumption or via a boxing conversion is how overload selection is done.? But, if we have methods m(Object) and m(V?), and it is invoked with a v, in the subtyping case, we'll select m(Object), and in the conversion case, we'll select m(V?).? But it's not clear that this is what we want -- I would think to most people, V? feels "more specific" than Object.? The rules regarding "try first without boxing" exist solely for compatibility; they are not necessarily the rules we would have wanted had we started with autoboxing in 1.0. If we define the relationship between V and V? as boxing, then equality comparisons between V and V? similarly have to go through boxing.? This is doable, but under subtyping, it is simpler -- do they refer to the same value. Overall, I'm not really seeing much of value (that joke never gets old) for the "it's a boxing conversion" route; it's more complexity in the language, but the boxing intuition is not really serving the user very well in the first place. From john.r.rose at oracle.com Wed May 1 22:29:45 2019 From: john.r.rose at oracle.com (John Rose) Date: Wed, 1 May 2019 15:29:45 -0700 Subject: a new contract for reference types In-Reply-To: <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> Message-ID: On May 1, 2019, at 7:39 AM, Brian Goetz wrote: > > This is the point I?ve been failing to get across to Remi as well. Suppose you have a big value, and you want a sparse ArrayList of that value? You need a way to say ?Arraylist of BigValue, but not flattened.? And that?s a use-site concern. ArrayList gives you that. > > Which is to say: the claim that V? is useless once we have reified generics is simply untrue. Uses of value type (and templates, after that) have a new feature, not seen before on the JVM. They pull information from the definition (the class-file) and employ it at the use site. This fact has subtle and disruptive effects on our JVM and user model. I'll take a crack at explaining? Today's types in the JVM are either hardwired primitives, or else references. The references do *not* pull information from the definition, unless the operation specifically requests it (via a resolution step, as in a `new` or `checkcast` instruction). In many usages, our existing reference types work like forward declarations in C: typedef struct Foo Foo; //"class Foo;" in C++ extern Foo* makeFoo(const char* name); extern Foo* processFoo(Foo* arg); I'll use the acronym *FDT* for "forward declared type". Whole APIs can can be defined using such FDTs in C. Eventually somebody needs to make a Foo, but that can be in a small subset of the application which actually loads a header file that defines the body of `struct Foo`. In physical terms, FDTs are obviously nullable because they use an indirection pointer, which can assume a sentinel value. This allows variables of FDT type (like `Foo*`) to be initialized safely without the FDT's definition (such as a visible body for `struct Foo`). FDTs are not globally optimizable; at most they can be locally optimized by rewriting a region of the program. This applies in general, and specifically to Java's reference types today. Valhalla disrupts this state of affairs, in mostly good ways. If you have an array of values for a FDT, you must have an array of pointers. It's impossible to secretly inline some of these arrays because you are clever about knowing the source of them, except in very limited case where local escape analysis lets you rewrite the program secretly. (Such technology has not been invented, despite a half century of trying. I'll call that "impossible" for short.) Every mature OOL has a user switch to let the user choose, non-secretly, whether to use an optimized representation or an abstract one. For Java, it's `int[]` vs. `Integer[]`. It's not just arrays either. If you want an optimized field, you have to use a different contract than the FDTs. For Java, it's `int f` vs `Integer f`, with the definition of `int` hardwired for your benefit. The fact that Integer is a FDT at this point is invisible to users, since it's built in (and in fact the JVM loads it really early). But if you were to make a user defined primitive `uint`, then suddenly you'd have to load the class-file for `uint` before laying out a field of that type. Or you'd have to use an indirection. So forward declarations can be used, with indirections, to lay out fields and arrays abstractly. Conversely, non-abstract layouts (without indirections) cannot be used with forward declarations. (Side note: You could include the full layout redundantly at every use site. We're not doing that; it would break Java's core binary compatibility model.) This is a deep reason why Java has nulls. If you declare a reference variable in Java, it is a FDT (although you might not realized it). To initialize that variable, you need a value which is available before the type is defined. Hello, null. (Java could have chosen to omit null, I suppose, but then every field load would potentially throw a "field not initialized" exception. The larger point is that variables of forward-declared type need a state which does not depend on the type's definition.) And it's not just arrays and fields either. It turns out to be infeasible to arrange efficient calling sequences for virtual method hierarchies unless those hierarchies are loaded under a contract which allows full knowledge of the definitions of argument and return types in those hierarchies, *if* those argument and return types are to be optimized as part of the calling sequence. (There are lots of 80% and 90% solutions to this, but the 100% solution involves asking the user to accept a new contract for the types that are to be optimized. Spoiler: We intend that this new contract will be the default for value types V, while V? makes use of the old contract.) For this reason, when we change the performance characteristics of Java types by making some "inline" (aka "value" or "immediate"), we also require a distinction between fully abstract occurrences of such optimized values (using the old contract) and normally optimized occurrences, using a new contract. What is the new contract? Here are the essentials: 1. An occurrence of the optimized type in a descriptor causes resolution. This applies to field, method, array, and method types. 1a. There may be side effects due to class-file loading. 1b. There may be circularity errors due to loading of ill-formed programs. 1c. In the case of templates, there may be side effects due to template expansion logic (including bootstrap methods). 2. The optimized type does not necessarily permit null values. 2a. After resolving the type, validity of null is determined unambiguously from the type's definition, not its use. 3. Uses of an optimized type aggressively employ the details of that type as found in its class-file (or template expansion). 3a. In most cases this entails aggressive inlining. 3b. The only reliable way to turn off aggressive inlining is to request the old contract, by using the old descriptor. I think what's going on behind the questions about V and V? is the emergence of this new contract, and the clarification of the old contract. The contract differences can be hidden in many cases, but not all. Users will expect the new contract in cases like the following: - when making a field or (in most cases) an array - when passing values to and from methods In most cases where the type is resolved, the old and new contracts don't differ. These include: - making an instance - type casting or testing - reflection In some cases, users may wish for the old contract. Such cases include: - nullability (if the type doesn't natively support null) - layout polymorphism based on indirections (old generics) - sparse arrays of multi-word types - descriptor equivalence (avoidance of bridges) - copy avoidance (cf. Doug's note) We are presently using the type name V? to refer to the old contract. This means that V? could serve any of the above use cases. Although it seems unnatural for copy avoidance, but natural enough for the others. Thus, the deep difference of V and V?, or V.val and V.box, amounts to "V considered natively" and "V considered as a FDT". This is very like the distinction in C++ between `const T&` vs. `T`. And like C++ we might examine reasons to add further distinctions, such as `const T&&` and `T&` and (nullable) `T*` or `const T*`. Each of those variations of `T` in C++ have distinct contracts in the C++ user model. Java surely won't have so many distinctions; after all it differs from C++ by moving many representational choice from compile-time specifications into the JVM's runtime. I hope we only need two basic contracts for the Valhalla user model, the old one (necessary at least for backward compatibility) and one new one (sketched above). Doug's note raises a possible need for a third contract, which I hope we can avoid. I think V? can help in Doug's examples to force an indirection, which (in most cases but not all) can be strength-reduced to something off the heap. Doug's note has a comforting observation that such fine tuning is most important at large scales, and that there are several tactics which can be deployed there. The job of choosing tactics can sometimes be deferred to the library code, rather than the user. For example, sometimes the right answer for sorting a large flat array will be to first sort a temporary array of indexes into that array, and then permute the array. Such a tactical decision doesn't need to show up in the user model of the sort function. Another ray of hope: Al though the JIT cannot rewrite data structure, since it operates after data is defined, it locally rewrites large amounts of program structure, including the formats of method arguments and returns. (This assumes successful de-virtualization which is often the case, more often than successful escape analysis that allows data to be reformatted.) Indirections are not important to the JIT, since the JIT can always just use the original definition. Anyway, it's clear to me we need to nail down the new contract, and (in hindsight) elucidate the old one. It also seems to me that we are OK tying the new contract to V (the natural contract for the natural name) and the old one to V? (meaning nullable, but also indirect). Regarding subtyping, I don't see (from these considerations) a firm reason to declare that V? is a super of V. The value set of V? *might* have one more point than that of V, or it *might not*. The reason we are doing V? is not the value set, but the whole contract, which includes the value set as an obvious, but ultimately non-determinative part. I suppose if we were to spell V? as V* it would be clearer what we mean, relative to C and C++. But V? is fine by me, as long as we use Java's tradition of "lump instead of split", and be firm that V? lumps together nullability (*guaranteed* as opposed to only *when natural*) plus other aspects, notably backward compatibility, and sparse random order (not dense linear order) in arrays. ? John From john.r.rose at oracle.com Wed May 1 22:47:06 2019 From: john.r.rose at oracle.com (John Rose) Date: Wed, 1 May 2019 15:47:06 -0700 Subject: Is V? what we need ? In-Reply-To: <30BDD6DD-B0EE-4499-956F-441EEEFA2046@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <3A326959-15EF-4AEF-8057-9A90925850C2@oracle.com> <16975171.512084.1556716799732.JavaMail.zimbra@u-pem.fr> <06CB2186-1023-4F4B-B935-5E2C81050294@oracle.com> <30BDD6DD-B0EE-4499-956F-441EEEFA2046@oracle.com> Message-ID: On May 1, 2019, at 6:28 AM, Brian Goetz wrote: > > Also, we?re conflating two separate questions here. > > 1. What does V? mean. In the proposed world, it is the union type of V and Null, nothing more (alternately: V adjoined with null.). > > 2. What is the relationship between V and V? ? is it sub typing, or conversion? > > I think Remi is more interested in (2), but you keep saying ?it should be a box?,w which suggests we?re not on the same page with respect to (1) either, yet. As you folks saw, I wrote a separate note that tries to explain the difference between legacy L-types and the new requirements of value (and template) types. Our best way so far to "shake the box" of language features is to have native int-like values of class V be declared with the plain syntax "V". These values need a new contract which is incompatible with the old contract for the JVM's references, so to access the old reference behavior we need a different syntax, and (so far) that seems to be V?. But let's not let ourselves be blinded by syntax. The term V?, if it is to mean "a reference under the old contract", cannot mean only "the values of V plus null". It also has to mean "extra indirections" and "no loading side effects when used" and probably also "can participate in circular definitions", as well "unconditionally accepts null". A language feature which only adjoins null doesn't pull its weight. We are adding V? because it also pulls the weight of the old contract, allowing backward compatibility with the JVM's references. But since those references are a permanent part of the JVM's *future*, it is also *future* compatibility with code which selects the old contract instead of the new. I suggest the following thought experiment: In our discussions of "what does V? mean", temporarily replace "V?" with "V*", read according to the norms of the C language. It will more accurately reflect the underlying "physics" of the JVM. ? John From john.r.rose at oracle.com Wed May 1 22:55:19 2019 From: john.r.rose at oracle.com (John Rose) Date: Wed, 1 May 2019 15:55:19 -0700 Subject: Is V? what we need ? In-Reply-To: <9E44D846-A446-475A-956F-E23D7DAE12DF@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <644773187.516604.1556722015375.JavaMail.zimbra@u-pem.fr> <9E44D846-A446-475A-956F-E23D7DAE12DF@oracle.com> Message-ID: <39F2C520-6F81-445C-9065-CEA8A94CBB35@oracle.com> On May 1, 2019, at 7:50 AM, Brian Goetz wrote: > >> I fully agree, it's like getting ride of Integer, it's a fantasy, but not having a lot of API taking a N? as parameter type make that fantasy actually possible for the libraries you care. > > We can?t get rid of Integer, but maybe we can make it 10x less important. That would be winning. I agree with this. It is an argument to "cripple" V? (aka V*) as Remi is suggesting. A counter argument is that this makes code gratuitously hard to use; auto-unboxing of Integer is a decision to partially un-cripple Integer. Fully crippled case: The type V? has no operations except a null constant (V?.default), an explicit conversion from V ((V?)x), and an explicit conversion back ((V)x). Fully functional case: The type V? is a super of V, interpreted as V with null adjoined (if not already present), *and* all operations of V are lifted to V? with a NPE thrown for null. My guess is we will end up somewhere between; there are many points in between, including today's policy about Integer. I agree it doesn't help much to talk about "boxes" as a generic design tactic. There are too many design degrees of freedom. Maybe there are "coffers" in our future, but the real question is what operations are available on V? (aka V*). I agree with you, Brian, that the best user model outcome will make boxes disappear as separate APIs. This means that either V? (aka V*) has a trivial API, or else its API differs trivially from that of V, so that the "?" denotes more of a mode of use, than a full-blown API. I would prefer the latter. ? John From john.r.rose at oracle.com Wed May 1 23:12:24 2019 From: john.r.rose at oracle.com (John Rose) Date: Wed, 1 May 2019 16:12:24 -0700 Subject: Is V? what we need ? In-Reply-To: <031bc01d-9e63-3349-3e3e-92971da37c47@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <44db19d4-84bc-5b10-e9d6-e795b96e2ff7@oracle.com> <031bc01d-9e63-3349-3e3e-92971da37c47@oracle.com> Message-ID: <26E09AC4-D7BF-4334-BB80-525D7B4B10DC@oracle.com> I buy your argument, Brian, for shedding boxes from the center of the user model for V and V?. Given that V and V? have different contracts (per my previous note), so that they can have different physical representations in the JVM, it turns out that this statement: V is a subtype of V? (for any inline type) is true in pretty much the same way as this statement: int is a subtype of long Does that mean their formats are the same? No. (In fact their descriptors are of wholly different *kinds*.) Is the value set of one a superset of the other? Why yes. Can overloading selection (first phase!) choose either but prefer the narrower? Oh, yes. (No boxes in that phase.) Is it a different kind of super-type relation that inheritance? Yes, it's a corner case in the JLS. (Are their respective arrays related? Hmm, that's interesting. We've been round and round on this one. It looks like V? and V are closer in that respect than int and long.) > On May 1, 2019, at 12:34 PM, Brian Goetz wrote: > > >> However, I think my more general point remains - the fact that the VM has the flexibility to treat V and V? as, fundamentally, the same thing shouldn't necessarily drive the conclusion that, _at the language level_ there should be a subtyping relationship between V and V?. >> >> From a pedagogical perspective, whether we like it or not, users are immediately going to think in terms of box/unbox, so I think it'd be surprising if the new inline classes and their projections had rules radically different from those which apply to the int/Integer case. > > I agree that users are going to first reach for the box/unbox intuition. So let's talk about what's going to happen there. > > Let's assume that `V` translates to `QV` and `V?` translates to `LV`; let's compare the language we get under a subtyping relationship or a boxing conversion. (Either way, we get V? <: Object.) > > The box intuition says you can lock on a box (though we discourage it.) But locking on a V? will result in an exception. (Same for wait/notify.) > The box intuition says that == on a box is an identity comparison. But a V? has no identity (it did in Q-world, not in L-world.) > The box intuition says you can create a weak reference of a box. But you cannot for a value. > > So there are multiple ways in which the box intuition _already_ leads users down the wrong road, regardless of whether it is subtyping or not. > > One big difference between whether we convert V to V? via subsumption or via a boxing conversion is how overload selection is done. But, if we have methods m(Object) and m(V?), and it is invoked with a v, in the subtyping case, we'll select m(Object), and in the conversion case, we'll select m(V?). But it's not clear that this is what we want -- I would think to most people, V? feels "more specific" than Object. The rules regarding "try first without boxing" exist solely for compatibility; they are not necessarily the rules we would have wanted had we started with autoboxing in 1.0. > > If we define the relationship between V and V? as boxing, then equality comparisons between V and V? similarly have to go through boxing. This is doable, but under subtyping, it is simpler -- do they refer to the same value. > > Overall, I'm not really seeing much of value (that joke never gets old) for the "it's a boxing conversion" route; it's more complexity in the language, but the boxing intuition is not really serving the user very well in the first place. > > From forax at univ-mlv.fr Wed May 1 23:38:06 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 2 May 2019 01:38:06 +0200 (CEST) Subject: Is V? what we need ? In-Reply-To: <39F2C520-6F81-445C-9065-CEA8A94CBB35@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <644773187.516604.1556722015375.JavaMail.zimbra@u-pem.fr> <9E44D846-A446-475A-956F-E23D7DAE12DF@oracle.com> <39F2C520-6F81-445C-9065-CEA8A94CBB35@oracle.com> Message-ID: <1605926745.549186.1556753886599.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "John Rose" > ?: "Brian Goetz" > Cc: "Remi Forax" , "valhalla-spec-experts" > Envoy?: Jeudi 2 Mai 2019 00:55:19 > Objet: Re: Is V? what we need ? > On May 1, 2019, at 7:50 AM, Brian Goetz wrote: >> >>> I fully agree, it's like getting ride of Integer, it's a fantasy, but not having >>> a lot of API taking a N? as parameter type make that fantasy actually possible >>> for the libraries you care. >> >> We can?t get rid of Integer, but maybe we can make it 10x less important. That >> would be winning. > > I agree with this. It is an argument to "cripple" V? (aka V*) > as Remi is suggesting. > > A counter argument is that this makes code gratuitously > hard to use; auto-unboxing of Integer is a decision to > partially un-cripple Integer. > > Fully crippled case: The type V? has no operations except a > null constant (V?.default), an explicit conversion from V ((V?)x), > and an explicit conversion back ((V)x). > > Fully functional case: The type V? is a super of V, interpreted > as V with null adjoined (if not already present), *and* all operations > of V are lifted to V? with a NPE thrown for null. > > My guess is we will end up somewhere between; there > are many points in between, including today's policy about > Integer. > > I agree it doesn't help much to talk about "boxes" as a generic > design tactic. There are too many design degrees of freedom. > Maybe there are "coffers" in our future, but the real question > is what operations are available on V? (aka V*). > > I agree with you, Brian, that the best user model outcome > will make boxes disappear as separate APIs. This means > that either V? (aka V*) has a trivial API, or else its API > differs trivially from that of V, so that the "?" denotes > more of a mode of use, than a full-blown API. I would > prefer the latter. So let's call it V*. I want also make clear that there is no proposal to not have a V*, we need it, and it's the L-version of an inline type for the VM. I agree that i made the mistake to talk about "box" to describe my proposal for V*. As Brian said, it's not a box at runtime because it works like an inline type with no identity. Before decided where to put the cursor, i want to explain why we should not choose the fully functional semantics and why we should not choose the crippled one too. V* describe a reference, as John said the old contract, if we end up with V* in APIs, we have not improved the Java world because JITs can not see through a V* and we have actually make it worst because V* has all the shortcomings of a reference type and all the shortcomings of an inline class at runtime i.e. no identity. So if we have V* in the API, we loose. We want V* for some use cases but not in the signature of the methods. Here comes the parallel with Integer, the way we use Integer currently is, i believe, the way we should use V*. It's fine to use V* as a type argument, it's fine to use it in a field if you want the reference semantics or a null value. It's not fine to use Integer as parameter of a method. That's why i think V* should not have the fully crippled semantics, but a kind of in-between. and i will stop here, because if we don't agree on that, there is no need to go further. > > ? John R?mi From john.r.rose at oracle.com Thu May 2 02:17:54 2019 From: john.r.rose at oracle.com (John Rose) Date: Wed, 1 May 2019 19:17:54 -0700 Subject: Is V? what we need ? In-Reply-To: <1605926745.549186.1556753886599.JavaMail.zimbra@u-pem.fr> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <644773187.516604.1556722015375.JavaMail.zimbra@u-pem.fr> <9E44D846-A446-475A-956F-E23D7DAE12DF@oracle.com> <39F2C520-6F81-445C-9065-CEA8A94CBB35@oracle.com> <1605926745.549186.1556753886599.JavaMail.zimbra@u-pem.fr> Message-ID: <6794D10D-E161-4CAB-AFC4-9AF6E22348A5@oracle.com> It looks like we're getting somewhere; thanks for the detailed response. I have one targeted reply: On May 1, 2019, at 4:38 PM, forax at univ-mlv.fr wrote: > > So let's call it V*. I want also make clear that there is no proposal to not have a V*, we need it, and it's the L-version of an inline type for the VM. That would an ugly choice, for sure. But it's also a full disclosure of the presence of the indirection. ? > It's not fine to use Integer as parameter of a method. There's one place where Integer is OK as a method parameter or return, and that is when you are reaching for null as a sentinel. I'm pretty sure I've written code like that. This, I think, is why V* is OK to spell as V?. My contribution to this conversation is to explain why, as one of Java's lumping-not-splitting design moves, we are adjoining the responsibilities of V* to the contract of V?. If V? were purely a value-set variant of V, then V* and V? would be distinct and subtly different types. But one of Java's super-powers is that it doesn't *do* that level of type refinement. ? John From maurizio.cimadamore at oracle.com Thu May 2 11:16:39 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 2 May 2019 12:16:39 +0100 Subject: Is V? what we need ? In-Reply-To: <031bc01d-9e63-3349-3e3e-92971da37c47@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <44db19d4-84bc-5b10-e9d6-e795b96e2ff7@oracle.com> <031bc01d-9e63-3349-3e3e-92971da37c47@oracle.com> Message-ID: On 01/05/2019 20:34, Brian Goetz wrote: > ne big difference between whether we convert V to V? via subsumption > or via a boxing conversion is how overload selection is done.? But, if > we have methods m(Object) and m(V?), and it is invoked with a v, in > the subtyping case, we'll select m(Object), and in the conversion > case, we'll select m(V?).? But it's not clear that this is what we want There's a tiny gap in this line of reasoning. All these arguments rely on the fact that V <: Object, I realized. While, again, this might be true from a VM perspective, it doesn't have to be true for the language. We can be in a world where: V? <: Object and V ~> V? That is, the first relation is covered by subtyping, while the latter involves a conversion (albeit a trivial one). If you go down this path, overload resolution works the way you expect: if you wanna pass a V to a m(Object) or m(V?) you require a conversion anyway. So m(V?) wins because it's most specific. If you wanna pass a V to m(V) or m(V?), m(V) wins, and m(V?) wouldn't even be considered. All this boils down, I think, to one question: do we want array covariance? E.g. should V[] <: Object[] ? If yes, then we need to have V <: Object (which then implies also V <: V?). If not, then we can use conversions as described above. Another factor that might inform the decision is wildcard treatment (as covariance is unsurprisingly related to arrays) - do we want: List <: List ? These are, IMHO, they key questions - once we answer them unambiguously, all else fall as a sequence of basically forced moves, I think. P.S. If we're really appealing to int vs. long, as John noted, int[] and long[] are unrelated types currently, so as int[] and Object[], which seems to push against covariance. I also remember some arguments exchanged about subtyping between primitive types being a 'bug' in the current JLS - e.g. int <: long is more a bug than a feature, but I could be remembering incorrectly. Maurizio From forax at univ-mlv.fr Thu May 2 19:48:20 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 2 May 2019 21:48:20 +0200 (CEST) Subject: Is V? what we need ? In-Reply-To: <6794D10D-E161-4CAB-AFC4-9AF6E22348A5@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <644773187.516604.1556722015375.JavaMail.zimbra@u-pem.fr> <9E44D846-A446-475A-956F-E23D7DAE12DF@oracle.com> <39F2C520-6F81-445C-9065-CEA8A94CBB35@oracle.com> <1605926745.549186.1556753886599.JavaMail.zimbra@u-pem.fr> <6794D10D-E161-4CAB-AFC4-9AF6E22348A5@oracle.com> Message-ID: <1746904691.838902.1556826500478.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "John Rose" > ?: "Remi Forax" > Cc: "Brian Goetz" , "valhalla-spec-experts" > Envoy?: Jeudi 2 Mai 2019 04:17:54 > Objet: Re: Is V? what we need ? > It looks like we're getting somewhere; thanks for > the detailed response. I have one targeted reply: > > On May 1, 2019, at 4:38 PM, forax at univ-mlv.fr wrote: >> >> So let's call it V*. I want also make clear that there is no proposal to not >> have a V*, we need it, and it's the L-version of an inline type for the VM. > > That would an ugly choice, for sure. But it's also a > full disclosure of the presence of the indirection. > > ? >> It's not fine to use Integer as parameter of a method. > > There's one place where Integer is OK as a method > parameter or return, and that is when you are reaching > for null as a sentinel. I'm pretty sure I've written code > like that. i should have added "in public API". Here are the offending methods in JDK 12*: java.sql.JDBCType public java.lang.Integer java.sql.JDBCType.getVendorTypeNumber() java.sql.SQLType public abstract java.lang.Integer java.sql.SQLType.getVendorTypeNumber() java.util.PrimitiveIterator$OfInt public default java.lang.Integer java.util.PrimitiveIterator$OfInt.next() java.lang.Integer public static java.lang.Integer java.lang.Integer.valueOf(int) java.lang.Integer public static java.lang.Integer java.lang.Integer.valueOf(java.lang.String,int) throws java.lang.NumberFormatException java.lang.Integer public static java.lang.Integer java.lang.Integer.valueOf(java.lang.String) throws java.lang.NumberFormatException java.lang.Integer public java.lang.Integer java.lang.Integer.resolveConstantDesc(java.lang.invoke.MethodHandles$Lookup) java.lang.Integer public static java.lang.Integer java.lang.Integer.decode(java.lang.String) throws java.lang.NumberFormatException java.lang.Integer public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String,int) java.lang.Integer public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String) java.lang.Integer public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String,java.lang.Integer) > > This, I think, is why V* is OK to spell as V?. My contribution > to this conversation is to explain why, as one of Java's > lumping-not-splitting design moves, we are adjoining > the responsibilities of V* to the contract of V?. > > If V? were purely a value-set variant of V, then V* and V? > would be distinct and subtly different types. But one of > Java's super-powers is that it doesn't *do* that level of > type refinement. yes, i fully agree. > > ? John R?mi * i've filtered out JMX because the API is reflection based with limitation on primitive types. From karen.kinnear at oracle.com Fri May 3 19:06:30 2019 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Fri, 3 May 2019 15:06:30 -0400 Subject: No Valhalla EG meeting Weds May 8 Message-ID: <00E3645D-672E-4B87-9C89-59E1D5BB1782@oracle.com> Next meeting Weds May 22nd thanks, Karen From dl at cs.oswego.edu Sun May 5 11:07:01 2019 From: dl at cs.oswego.edu (Doug Lea) Date: Sun, 5 May 2019 07:07:01 -0400 Subject: generic specialization design discussion In-Reply-To: References: <213d368c-5948-2385-a1b4-982d189b5fc9@oracle.com> <25220157-E4FF-45A7-B8F3-A4A963AB286E@oracle.com> <0D86D3E0-A8B9-45FF-8A69-84BD037007B9@oracle.com> <69C2B250-8E17-4279-A661-C61285C1A230@oracle.com> <8234fa64-bd23-872d-b465-6ef838faf72e@cs.oswego.edu> <983278D5-7CF3-45AA-8FC1-51530C19641F@oracle.com> <1874D686-4E92-4888-9A54-3AF8CF37C916@oracle.com> <401126eb-614e-7584-fe8f-ac239421df4d@cs.oswego.edu> Message-ID: <2fbe1393-ab3e-0683-1be6-c28511f8b93e@cs.oswego.edu> On 4/18/19 6:08 PM, John Rose wrote: > ... > There's another shoe that needs to drop here, another > term which is *not* good enough, for us to bikeshed: > "reference". If we could get away with saying "value" > and "reference" have a special meaning as adjectives, > we could allow those terms, as nouns, to retain their > standard meanings in the JVMS. > > > Finally, we need to use the positive term inline > and the positive term NI to construct the very > useful type names formerly known as ValObject > and RefObject. Clearly, those names should be > readable in code as "inline object" and "NI object". > > Now for a NI bikeshed color. I think it is sufficient > to use the term "identity" for NI. Not having any better ideas after sitting on this a while, I agree. Some usages are about referring to an identity, not the identity itself. But I don't know any everyday terms for this that work ("allusion" is sorta close but weird). -Doug > > Thus, we would have: > > - inline classes and identity classes > - inline types and identity types > - the top types InlineObject and IdentityObject > - inline objects and identity objects > - inline values and identity values > - inline references and identity references > - informally, maybe "inlines" and "identities" > > (Or maybe something like InlineObj and IdentityObj > or InObject and IdObject, if we feel the need to > abbreviate.) > > What other colors are there for NI? > From jfinn at boxoftricks.org Mon May 6 14:34:23 2019 From: jfinn at boxoftricks.org (Jonathan Finn) Date: Mon, 6 May 2019 15:34:23 +0100 Subject: =?utf-8?Q?=E2=80=98inline=E2=80=99_?=and =?utf-8?Q?=E2=80=98identity=E2=80=99_?=classes Message-ID: This is from the point of a view of a regular programmer - I don?t write VMs or compilers, though I?m somewhat aware of the issues?? The term ?inline class? seems to encourage a mental model where fields, arrays, local variables etc. of inline classes ?contain? their objects instead of referring/pointing to them. This seems confusing and wrong. Imagine I change class Point to inline class Point: am I meant to think that every other class with a Point field has now changed to ?contain? its Point? Likewise every place that stores a Point in a Point[] array now does some kind of copying instead of storing a reference? Maybe passing a Point to a method now copies it too? This may be true inside the VM, but it's invisible in the language - they still act like normal references (except for ==), which is indeed the the whole aim of this feature. Inline classes just allow the VM to save memory in an unspecified way, in exchange for certain restrictions. Much like an enum class: for its users it?s (almost) just another class, but for its authors there are restrictions (e.g. subclassing).? Despite almost no change in behaviour, the term ?inline? (like contained, flattened) kind of suggests I have to mentally reinterpret every use of my class! Instead:?since you'd use this feature to save memory/time, how about the term *compact*, or *mini* (which also implies reduced functionality), or possibly *lightweight* (to hint that these are arguably flyweight objects, but that?s another story). As for the corresponding term?identity class: you?d probably decide a class should be non-inline because you want it to be mutable or subclassable. Identity seems to be over-stressed from the point of view of the programmer: it isn?t that obviously connected with subclassing; and it?s very unimportant for immutable classes. Instead: how about a *full*?class, meaning full functionality at the cost of full size. Or just a *normal* or *regular* class.? So Object has subclasses CompactObject (or MiniObject) and FullObject (or NormalObject) etc.? best wishes, Jonathan Jonathan Finn From peter.levart at gmail.com Wed May 8 06:37:18 2019 From: peter.levart at gmail.com (Peter Levart) Date: Wed, 8 May 2019 08:37:18 +0200 Subject: a new contract for reference types In-Reply-To: References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> Message-ID: Hi, On 5/2/19 12:29 AM, John Rose wrote: > Regarding subtyping, I don't see (from these considerations) > a firm reason to declare that V? is a super of V. The value > set of V?*might* have one more point than that of V, > or it*might not*. The reason we are doing V? is not the > value set, but the whole contract, which includes the > value set as an obvious, but ultimately non-determinative part. Just one observation... If inline class V was declared to support a "kind" of null (default, sentinel) value by itself, then how such value would be denoted? Is this a way? V v = null; If this was possible, then what would be the distinction between the following two then? V? vInd1 = null; V? vInd2 = v; Would vInd1 and vInd2 represent the same "null" value? Regards, Peter From john.r.rose at oracle.com Wed May 8 17:16:22 2019 From: john.r.rose at oracle.com (John Rose) Date: Wed, 8 May 2019 10:16:22 -0700 Subject: a new contract for reference types In-Reply-To: References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> Message-ID: <58B64983-8DE5-48C3-8826-577E3550D008@oracle.com> On May 7, 2019, at 11:37 PM, Peter Levart wrote: > > On 5/2/19 12:29 AM, John Rose wrote: >> Regarding subtyping, I don't see (from these considerations) >> a firm reason to declare that V? is a super of V. The value >> set of V?*might* have one more point than that of V, >> or it*might not*. The reason we are doing V? is not the >> value set, but the whole contract, which includes the >> value set as an obvious, but ultimately non-determinative part. > > Just one observation... > > If inline class V was declared to support a "kind" of null (default, sentinel) value by itself, then how such value would be denoted? > > Is this a way? > > V v = null; Yes, because there's only one null in the whole world. (The possibility of having many kinds of null, perhaps one per type, is something we are trying to avoid. Null is a costly feature, sometimes referred to as a billion dollar mistake[1]. We have to deal with it in Java. Adding more of them would be even more costly IMO.) [1]: https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare > If this was possible, then what would be the distinction between the following two then? > > V? vInd1 = null; > V? vInd2 = v; > > Would vInd1 and vInd2 represent the same "null" value? Yes, please please please. A related question is, if V is nullable, then what is the possible use of `V?`? If V's value set already has null in it, then `V?` can't add another null, or re-add the existing (unique please please) null. A decent answer to this is, "V?" means "a classic indirection" as well as "can be null". I.e., it's the New Contract I've been writing about. Usually the user of a JVM doesn't know or care about where the JVM is using indirections or not, but for those corner cases where indirections *might* show up (somehow) "V?" might be a useful way to say, "make indirections show up here" where just "V" means "use inline layouts here". One place where there users might plausibly wish to make the choice is in array layouts. As Doug pointed out, some array algorithms work better one way and others another way. The concurrency effects are different with the two versions, also. So if V is a nullable inline class (perhaps migrated from a classic identity class) you almost never say V?, but you might do this: V[] a1 = new V[1000]; // inline layout V[] a2 = new V?[1000]; // indirect layout You wouldn't even need to make `V?[]` be a user visible type in order for `new V?[]` to be valid syntax, although it would be a stretch to design things this way. My bottom line opinion: We want to make `V?` be a real type for users even if V is nullable. But we want to make it a rare occasion that a user would want to reach for `V?`. Certainly the `?` token must *not* become a new "register" keyword, to be sprinkled superstitiously over our programs. ? John P.S. Back to Doug's array example: I would be tempted to refactor sort algorithms to work on a temporary array of type int[]. Even for classic object references this might go faster if it's profitable to eliminate GC barrier effects absent on int[] but present on Object[]. For multi-word inline array elements, working on int[] as a proxy for the larger flattened array of inlines might reduce data movement overall, without too much extra burden on cache. From brian.goetz at oracle.com Wed May 8 18:31:52 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 8 May 2019 11:31:52 -0700 Subject: Is V? what we need ? In-Reply-To: <1605926745.549186.1556753886599.JavaMail.zimbra@u-pem.fr> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <644773187.516604.1556722015375.JavaMail.zimbra@u-pem.fr> <9E44D846-A446-475A-956F-E23D7DAE12DF@oracle.com> <39F2C520-6F81-445C-9065-CEA8A94CBB35@oracle.com> <1605926745.549186.1556753886599.JavaMail.zimbra@u-pem.fr> Message-ID: > Here comes the parallel with Integer, the way we use Integer currently is, i believe, the way we should use V*. It's fine to use V* as a type argument, it's fine to use it in a field if you want the reference semantics or a null value. It's not fine to use Integer as parameter of a method. That's why i think V* should not have the fully crippled semantics, but a kind of in-between. I think there are two points of disagreement here: 1. The meaning of ?not fine?. 2. Whether the language should attempt to make such things impossible. So, while I agree that it is _generally_ a smell to write APIs that have Integer as parameter or return types, but that doesn?t mean that _any_ such use is an error, and I certainly don?t think that Integer should not be denotable as a parameter type. Here?s an example of how a param/return type of Integer arises naturally: interface Foo { T mangle(T t); } class C implements Foo { Integer mangle(Integer i) { ? } } If it?s OK to say Foo, and it?s OK for a class to specialize the generic type arguments of its super types, then it has to be OK to use Integer as a parameter or return type. Similarly, what if Foo was: interface Foo { void process(Consumer c); } clients of C might well want to explicitly type their lambdas as (Integer i) -> ?. Now, s/Integer/V?/: class D implements Foo { V? mangle(V? v) { ? } } Same argument. While I wouldn?t encourage people to write APIs that make heavy use of V?, the natural flow of generic types into signatures will occasionally make it happen, and that?s OK. From daniel.smith at oracle.com Wed May 8 19:31:34 2019 From: daniel.smith at oracle.com (Dan Smith) Date: Wed, 8 May 2019 13:31:34 -0600 Subject: generic specialization design discussion In-Reply-To: References: <213d368c-5948-2385-a1b4-982d189b5fc9@oracle.com> <25220157-E4FF-45A7-B8F3-A4A963AB286E@oracle.com> <0D86D3E0-A8B9-45FF-8A69-84BD037007B9@oracle.com> <69C2B250-8E17-4279-A661-C61285C1A230@oracle.com> <8234fa64-bd23-872d-b465-6ef838faf72e@cs.oswego.edu> <983278D5-7CF3-45AA-8FC1-51530C19641F@oracle.com> <1874D686-4E92-4888-9A54-3AF8CF37C916@oracle.com> <401126eb-614e-7584-fe8f-ac239421df4d@cs.oswego.edu> Message-ID: > On Apr 18, 2019, at 4:08 PM, John Rose wrote: > > Here's the background: The JVMS takes great care to > use the terms "reference" and "value" with > precision, and this occasionally surfaces in explanations > meant for ordinary Java users. We have already released > the term "value" from its new duties; I think we have an > equal need to release "reference" from its new duties > as well. > > (Put another way: The JVMS says that all a-series opcodes > take "reference" arguments, and all L-series descriptors > denotes reference variables. In L-world "reference" means > a value which refers potentially to either an inline object > or a non-inlinable identity-laden object. Changing this > term is IMO not feasible. I'm arguing against overloading > as well.) > > So what we need is a formal term NI which means "not > inline", the opposite of the formal term "inline". I'm working on the introductory spec material, and have also come to this conclusion. All values are either *primitives* or *references*. Everything we've done in L-world has to do with refining the space of things that references can point to (*objects*). > Now for a NI bikeshed color. I think it is sufficient > to use the term "identity" for NI. > > Thus, we would have: > > - inline classes and identity classes > - inline types and identity types > - the top types InlineObject and IdentityObject > - inline objects and identity objects > - inline values and identity values > - inline references and identity references > - informally, maybe "inlines" and "identities" Here's a cut of JVMS 2.4 that incorporates some of this terminology (some of it I've avoided, either because I didn't need it, or it seemed insufficiently precise.) I also decided to call out the `Object` type as a unique entity. This probably have some ripple effects elsewhere, which I haven't explored yet. It's hard to say much about identity without talking about acmp/substitutability; I chose the term "identical" here for that purpose (rather than the overloaded "equal"). ~~~~~~~~~~ ### 2.4 Reference Types and Values There are five kinds of reference types: identity class types, inline class types, array types, interface types, and the `Object` type. Their values are references to *objects* or the special `null` reference. An identity class type names a non-inline, non-interface class other than `Object` defined in a `class` file. The objects referenced by values of an identity class type are instances of the class or one of its subclasses. Each instance is dynamically allocated and has a unique *identity*, which is used to determine whether two references are identical. The instance encapsulates *fields*; the values of fields may be changed, but doing so does not change the identity of the object. An inline class type names an inline class defined in a `class` file. The objects referenced by values of an inline class type are instances of the class. Each instance encapsulates fields whose values cannot be changed. Inline class instances do not have a unique identity?two references are identical if they reference instances of the same inline class and the values of the objects' fields are identical. For each inline class, there is a *nullable* and a *null-free* inline class type. These types share the same set of values, with the exception that `null` is a value of the nullable type, but not the null-free type. An array type names a *component type*, which may be `boolean`, any numeric type, or any reference type. The objects referenced by values of an array type are dynamically-allocated arrays. Each array object has a unique identity, a component type, and a vector of mutable components. The identity is used to determine whether two references are identical. The components store values of the component type; the number of components is fixed at allocation time, but is not constrained by the array type. Array types are covariant: if an array type has component type *T*, an array referenced by a value of the array type has a component type that is a subtype of *T*. The component type of an array type may itself be an array type; such a type is a *multi-dimensional* array type. The *element type* of a single-dimensional array type is its component type; the element type of a multi-dimensional array type is the element type of its component type. An interface type names an interface defined in a `class` file. The objects referenced by values of an interface type are instances of a class that implements the interface. These instances may be identity objects or inline objects. The objects referenced by values of interface types `Cloneable` and `java.io .Serializable` may also be arrays. The `Object` type names the `Object` class. References of type `Object` may refer to any object: identity class instances, inline class instances, or arrays. Instances of the `Object` class itself are treated as identity class instances. The default value of a null-free inline class type is a reference to a class instance whose fields all have the default value for their type. The default value of any other reference type is `null`. ~~~~~~~~~~ From forax at univ-mlv.fr Wed May 8 22:12:04 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Thu, 9 May 2019 00:12:04 +0200 (CEST) Subject: It's not safe until it's in the coffer Message-ID: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> I would like to propose an alternative to the V? syntax we are currently using for representing an inline class encoded as a L-type. I propose to use Coffer instead of Complex? (with Complex an inline class). as notice several of us, the V? syntax as several shortcoming: - as Brian said, using '?' as a character makes a type that mix wildcards and V? syntax hard to parse. - as John said, using ? is misleading because other languages have use ? to indicate a nullable type but the Ltype of an inline class is an identityless nullable reference (and being an identityless reference is as important as being nullable) - as i tried to say, the syntax V? means that V? is a supertype of V, so something that should be preferred to V as type of parameters in methods but we don't want to encourage people to write APIs that make heavy use of V? (using the words of Brian). I think that a good alternative is to introduce a new class named java.lang.Coffer and makes the compiler to erase Coffer to LComplex; with a mechanism named auto-coffering to go from an inline class to its coffer and vice-versa. Note that because auto-coffering is introduced at the same type as inline class is introduced in the lange, we are free to specify whatever semantics we want for overloaded methods that takes a coffer or its corresponding inline type. Here are the advantage of using java.lang.Coffer - we can document the exact semantics of a coffer in the javadoc of java.lang.Coffer. - nullability and being a reference comes from free because it's a classical class from the user POV. - it's obvious that if you want to call a method on a value type, you have to un-coffer it first which may lead to a NPE at that point. - because auto-coffering is a conversion, Coffer is not a supertype of Complex. There are two oddities: - while the class java.lang.Coffer exists, you can not have an instance of Coffer at runtime, so you have these special rules: - java.lang.Coffer.class can exist but it can not be instantiated (like java.lang.Void). - java.lang.Coffer can not be a raw type and doens't accept any wildcard bounded or unbounded, because we don't know how to erase them. - Coffer is a reified type so - instanceof Coffer and new Coffer[42] are ok. So the main drawback is that a Coffer is a new kind of type with some very specific rules. R?mi From john.r.rose at oracle.com Wed May 8 22:18:30 2019 From: john.r.rose at oracle.com (John Rose) Date: Wed, 8 May 2019 15:18:30 -0700 Subject: generic specialization design discussion In-Reply-To: References: <213d368c-5948-2385-a1b4-982d189b5fc9@oracle.com> <25220157-E4FF-45A7-B8F3-A4A963AB286E@oracle.com> <0D86D3E0-A8B9-45FF-8A69-84BD037007B9@oracle.com> <69C2B250-8E17-4279-A661-C61285C1A230@oracle.com> <8234fa64-bd23-872d-b465-6ef838faf72e@cs.oswego.edu> <983278D5-7CF3-45AA-8FC1-51530C19641F@oracle.com> <1874D686-4E92-4888-9A54-3AF8CF37C916@oracle.com> <401126eb-614e-7584-fe8f-ac239421df4d@cs.oswego.edu> Message-ID: <52A990F4-47B1-42C0-9306-1A17AB7B0CFD@oracle.com> On May 8, 2019, at 12:31 PM, Dan Smith wrote: > > I'm working on the introductory spec material, and have also come to this conclusion. All values are either *primitives* or *references*. Everything we've done in L-world has to do with refining the space of things that references can point to (*objects*). > >> ... > > Here's a cut of JVMS 2.4 that incorporates some of this terminology (some of it I've avoided, either because I didn't need it, or it seemed insufficiently precise.) > > I also decided to call out the `Object` type as a unique entity. This probably have some ripple effects elsewhere, which I haven't explored yet. > > It's hard to say much about identity without talking about acmp/substitutability; I chose the term "identical" here for that purpose (rather than the overloaded "equal"). When the current JLS and JVMS must talk about object identity (identicality??) they tend to use the term "same". It's such a humble word it's easy to miss. Maybe the latinate term "identical" is better, although it's confusingly similar to "identity". What you've written reads very well, and I have no suggestion for improving it, except that the stuff about "nullable" and "null-free" will shortly be false, when we introduce inline classes that encode null natively (as a combination of their field values). I did a careful search in the JVMS and JLS for the word "same" and found these uses where "identical" could be a candidate for replacing or clarifying "same": > JVMS 5.4.3 Resolution > Subsequent attempts to resolve the symbolic reference always succeed > trivially and result in the same entity produced by the initial resolution. > [condy may resolve to an inline instance] > JLS 4.3.1 Objects > There may be many references to the same object. > Most objects have state, stored in the fields of objects that are instances of > classes or in the variables that are the components of an array object. > If two variables contain references to the same object, the state of the object > can be modified using one variable's reference to the object, and then the > altered state can be observed through the reference in the other variable. > ? > Example 4.3.1-2. Primitive and Reference Identity > ? > Each object is associated with a monitor ([17.1]), which is used by > `synchronized` methods ([8.4.3]) and the `synchronized` statement ([14.19]) to > provide control over concurrent access to state by multiple threads ([17]). > JLS 4.12.4 `final` Variables > Once a `final` variable has been assigned, it always contains the same value. > If a `final` variable holds a reference to an object, then the state of the > object may be changed by operations on the object, but the variable will always > refer to the same object. > This applies also to arrays, because arrays are objects; if a `final` variable > holds a reference to an array, then the components of the array may be changed > by operations on the array, but the variable will always refer to the same > array. > > JLS Example 8.3.1.1-1. `static` Fields > These two ways of accessing the `origin` class variable access the same object, > evidenced by the fact that the value of the reference equality expression > ([15.21.3]) > JLS Example 8.8.7.1-2. Qualified Superclass Constructor Invocation > Perhaps surprisingly, the same instance of `Outer` may serve as the immediately > enclosing instance of `ChildOfInner` with respect to `Inner` *for multiple > instances of `ChildOfInner`*. [careful outers could be inline objects] > JLS Example 10.7-2. Shared Subarrays After A Clone > showing that the `int[]` array that is `ia[0]` and the `int[]` array that is > `ja[0]` are the same array. [seems OK here] > JLS 14.11 The `switch` Statement {#jls-14.11} > - No two of the `case` constants associated with the `switch` statement have > the same value. [can be java.lang.String references!] > JLS 14.19 The `synchronized` Statement > Acquiring the lock associated with an object does not in itself prevent other > threads from accessing fields of the object or invoking un-`synchronized` > methods on the object. [may need to be restricted to identity objects] > JLS Example 15.8.3-1. The `this` Expression > If the other vector is the same vector object as the one for which the `equals` > method was invoked, then the check can skip the length and value comparisons. > [seems OK here] > JLS 15.21.3 Reference Equality Operators `==` and `!=` > At run time, the result of `==` is `true` if the operand values are both `null` > or both refer to the same object or array; otherwise, the result is `false`. > ? > The result of `!=` is `false` if the operand values are both `null` or both > refer to the same object or array; otherwise, the result is `true`. Also watch out for the phrase "same monitor". It's safe if used carefully, but it tends to go along with the assumption that objects and monitors are in one-to-one correspondence, which is not true for inline objects. The following section might need to be reformulated or rescoped, if static factory methods named are classified as I.I.M.s: > JVMS 4.10.2.4 Instance Initialization Methods and Newly Created Objects > When an instance initialization method is invoked on a class instance, only > those occurrences of the special type on the operand stack or in the local > variable array that are the same object as the class instance are replaced. The language about arrays is good. When the dust settles, we might want to talk about making *some* arrays of existing array types, or *new array types*, marry the semantics of arrays to those of inline objects. This would be one approach to frozen arrays. ? John From john.r.rose at oracle.com Wed May 8 22:50:10 2019 From: john.r.rose at oracle.com (John Rose) Date: Wed, 8 May 2019 15:50:10 -0700 Subject: It's not safe until it's in the coffer In-Reply-To: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> References: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> Message-ID: On May 8, 2019, at 3:12 PM, Remi Forax wrote: > > I propose to use Coffer instead of Complex? (with Complex an inline class). So you are giving a name, "Coffer", to the Old Contract. The javadoc for the named type-constructor could describe this contract fully: - array performance profile associated with indirections not inlines - non-tearing indirection-based updates - null in the value set, if the inline type is already null natively - L-descriptors in the JVM (for those who peek) - circularities OK (a Foo can have a field of type Coffer) Maybe Indirect is the right name, then? The effect of doing this would be to make the indirect version of a type VT to look superficially more like a box, at a time when we are trying to downplay boxes. But it's only superficial. The Coffer/Indirect generic is a one-off type constructor, like ? itself. Put another way, matchfix C<.> is just a bulkier syntax for postfix-? As such it would have to be documented in its essence in the JLS, as well as in its javadoc. One consequence of Coffer/Indirect is that it puts a larger distance between the two types than VT -vs- VT? does. In that, it's sort of like Integer-vs-int. But unlike boxes, natural VT operations are not lifted to Coffer. The difference between VT and VT? is small enough that I (for one) would expect operations on VT to be lifted to VT?. We would also expect a type system relation between VT and VT?. A consequence of bulkier notation is that it's clear that VT <: C is false. Another is that programmers will think twice before saying C where VT? could be an attractive nuisance (like the register keyword). So, there are some things to like about this bulky syntax. There are lots to dislike: - it's bulky (bug or feature?) - the nullability is less obvious (but maybe that's not a problem) - it's a one-off that has to be defined in JLS and javadoc both - it will remind us of wrappers, sometimes ? John P.S. BTW, would Coffer erase to Object? P.P.S. Must? not? mention? covfefe? argh!!! From forax at univ-mlv.fr Wed May 8 23:28:41 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 9 May 2019 01:28:41 +0200 (CEST) Subject: It's not safe until it's in the coffer In-Reply-To: References: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> Message-ID: <1629679616.884802.1557358121602.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "John Rose" > ?: "Remi Forax" > Cc: "valhalla-spec-experts" > Envoy?: Jeudi 9 Mai 2019 00:50:10 > Objet: Re: It's not safe until it's in the coffer > On May 8, 2019, at 3:12 PM, Remi Forax wrote: >> >> I propose to use Coffer instead of Complex? (with Complex an inline >> class). > > So you are giving a name, "Coffer", to the Old Contract. > > The javadoc for the named type-constructor could describe > this contract fully: > > - array performance profile associated with indirections not inlines > - non-tearing indirection-based updates > - null in the value set, if the inline type is already null natively > - L-descriptors in the JVM (for those who peek) > - circularities OK (a Foo can have a field of type Coffer) > > Maybe Indirect is the right name, then? it's better than Coffer. > > The effect of doing this would be to make the indirect version > of a type VT to look superficially more like a box, at a time > when we are trying to downplay boxes. But it's only superficial. yes > > The Coffer/Indirect generic is a one-off type constructor, > like ? itself. Put another way, matchfix C<.> is just a bulkier > syntax for postfix-? As such it would have to be documented > in its essence in the JLS, as well as in its javadoc. > > One consequence of Coffer/Indirect is that it puts a larger > distance between the two types than VT -vs- VT? does. > In that, it's sort of like Integer-vs-int. But unlike boxes, > natural VT operations are not lifted to Coffer. > The difference between VT and VT? is small enough > that I (for one) would expect operations on VT to be > lifted to VT?. We would also expect a type system > relation between VT and VT?. > > A consequence of bulkier notation is that it's clear that > VT <: C is false. Another is that programmers > will think twice before saying C where VT? could be > an attractive nuisance (like the register keyword). yes > > So, there are some things to like about this bulky syntax. > There are lots to dislike: > > - it's bulky (bug or feature?) > - the nullability is less obvious (but maybe that's not a problem) > - it's a one-off that has to be defined in JLS and javadoc both > - it will remind us of wrappers, sometimes for the nullability, given that Indirect is not an inline class but an indirect class, i don't think this is an issue. > > ? John > > P.S. BTW, would Coffer erase to Object? It can be but i was not able to find that useful given that V is already a subtype of Object and erasing instanceof Indirect to instanceof Object is surprising. > > P.P.S. Must? not? mention? covfefe? argh!!! i hope my proposal will not gone covfefe :) R?mi From maurizio.cimadamore at oracle.com Thu May 9 10:00:12 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 9 May 2019 11:00:12 +0100 Subject: It's not safe until it's in the coffer In-Reply-To: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> References: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> Message-ID: <494bb07e-3180-d95d-1fc3-e51713b524ff@oracle.com> Another oddity, that I find hard to explain away: Coffer ~= String This seems to be a bad property, as you have two types to name the same thing. You could, in principle, say that the type parameter of Coffer is restricted to... values. But here's the second, pedagogical oddity: Coffer looks an awful lot like a specialized generic type. I think people will be surprised in seeing that this magic types works, while the types they want (List) does not. Besides... List> is reeeallly verbose, do we really want to read code like that? At the language level, the number of exceptions this will require all over the place, from generic well-formedness to inference (imagine passing a 'Value' where a Coffer) is expected, that, while I can sympathize with your opening position of '?' being confusing, it seems the proposed cure is worse than the disease :-) Maurizio On 08/05/2019 23:12, Remi Forax wrote: > There are two oddities: From forax at univ-mlv.fr Thu May 9 12:35:16 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 9 May 2019 14:35:16 +0200 (CEST) Subject: It's not safe until it's in the coffer In-Reply-To: <494bb07e-3180-d95d-1fc3-e51713b524ff@oracle.com> References: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> <494bb07e-3180-d95d-1fc3-e51713b524ff@oracle.com> Message-ID: <960275818.1072692.1557405316949.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Maurizio Cimadamore" > ?: "Remi Forax" , "valhalla-spec-experts" > Envoy?: Jeudi 9 Mai 2019 12:00:12 > Objet: Re: It's not safe until it's in the coffer > Another oddity, that I find hard to explain away: > > Coffer ~= String > > This seems to be a bad property, as you have two types to name the same > thing. > > You could, in principle, say that the type parameter of Coffer is > restricted to... values. yes, the type argument of a Coffer is restricted to an inline class, i've forgotten to mention that, thanks. > > But here's the second, pedagogical oddity: Coffer looks an awful > lot like a specialized generic type. I think people will be surprised in > seeing that this magic types works, while the types they want > (List) does not. Yes, it's surprising but it has nothing to do with Coffer or V? but with the fact that a T can be nullable and an inline class is not. Note that the error message saying that List doesn't work, can suggest that List> may work (at least for LW10). Now, yes, it looks like a specialized generic type and i think it's fine given we want to introduce specialized generics types in LW3000. > > Besides... > > List> > > is reeeallly verbose, do we really want to read code like that? yes, it's verbose by design. > > At the language level, the number of exceptions this will require all > over the place, from generic well-formedness to inference (imagine > passing a 'Value' where a Coffer) is expected, that, while I can > sympathize with your opening position of '?' being confusing, it seems > the proposed cure is worse than the disease :-) I don't think so, here you are supposing, i believe, that the inference has to be changed because inferring Z as an indirect object is not useful. But we don't have to change the inference, the same way when you have a T... you don't have a special inference rule because creating an array of parameterized type is unsafe, the idea is to do the same inference algorithm and at the end, you emit an error if Z is not an inline class. So yes you have some rules around creating a Coffer but they are far less invasive than adding a new union type V? in the type system. > > Maurizio R?mi > > > On 08/05/2019 23:12, Remi Forax wrote: > > There are two oddities: From maurizio.cimadamore at oracle.com Thu May 9 17:54:17 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 9 May 2019 18:54:17 +0100 Subject: It's not safe until it's in the coffer In-Reply-To: <960275818.1072692.1557405316949.JavaMail.zimbra@u-pem.fr> References: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> <494bb07e-3180-d95d-1fc3-e51713b524ff@oracle.com> <960275818.1072692.1557405316949.JavaMail.zimbra@u-pem.fr> Message-ID: <25347de8-e414-578f-4e75-2edda3c4a8a7@oracle.com> On 09/05/2019 13:35, forax at univ-mlv.fr wrote: > yes, it's verbose by design. I object to this a bit. There will be cases where using nullable projection will be _the only_ way to solve certain problems (e.g. to build value types that can reference to themselves). Forcing an heavy syntax on these cases seems punitive. You seem to assume that, once we have specialized generics, people will just use them and forget about nullable projections. I don't think that's the case, and some internal discussions we started (e.g. to sprinkle values on HashMap implementation) seem to point in that direction too. Maurizio From brian.goetz at oracle.com Thu May 9 18:30:02 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 9 May 2019 11:30:02 -0700 Subject: It's not safe until it's in the coffer In-Reply-To: <25347de8-e414-578f-4e75-2edda3c4a8a7@oracle.com> References: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> <494bb07e-3180-d95d-1fc3-e51713b524ff@oracle.com> <960275818.1072692.1557405316949.JavaMail.zimbra@u-pem.fr> <25347de8-e414-578f-4e75-2edda3c4a8a7@oracle.com> Message-ID: <2F6C1784-63BD-45C1-BDE8-5195AFD974B1@oracle.com> Another thing to object to is: the use of pseudo-generics as type operators. This raises many new problems: including readability problems (how are readers supposed to know that Coffer is a magic fake type, with possibly different rules? If Coffer accepts primitive args, users would be confused that they can say Coffer but not List, etc) and generalized magic-angst (?why can?t I write my own type operators.?). All that said, I think we?re getting way^3 ahead of ourselves. I still don?t think you?ve adequately outlined what problem you think needs solving; I get that you think it would be not-great to use V? types in public APIs, but it?s a long leap from there to this proposal. > On May 9, 2019, at 10:54 AM, Maurizio Cimadamore wrote: > > > On 09/05/2019 13:35, forax at univ-mlv.fr wrote: >> yes, it's verbose by design. > > I object to this a bit. > > There will be cases where using nullable projection will be _the only_ way to solve certain problems (e.g. to build value types that can reference to themselves). Forcing an heavy syntax on these cases seems punitive. You seem to assume that, once we have specialized generics, people will just use them and forget about nullable projections. I don't think that's the case, and some internal discussions we started (e.g. to sprinkle values on HashMap implementation) seem to point in that direction too. > > Maurizio > From forax at univ-mlv.fr Thu May 9 21:48:06 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 9 May 2019 23:48:06 +0200 (CEST) Subject: It's not safe until it's in the coffer In-Reply-To: <2F6C1784-63BD-45C1-BDE8-5195AFD974B1@oracle.com> References: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> <494bb07e-3180-d95d-1fc3-e51713b524ff@oracle.com> <960275818.1072692.1557405316949.JavaMail.zimbra@u-pem.fr> <25347de8-e414-578f-4e75-2edda3c4a8a7@oracle.com> <2F6C1784-63BD-45C1-BDE8-5195AFD974B1@oracle.com> Message-ID: <1528962373.1203574.1557438486021.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Brian Goetz" > ?: "Maurizio Cimadamore" > Cc: "Remi Forax" , "valhalla-spec-experts" > Envoy?: Jeudi 9 Mai 2019 20:30:02 > Objet: Re: It's not safe until it's in the coffer > Another thing to object to is: the use of pseudo-generics as type operators. > This raises many new problems: including readability problems (how are readers > supposed to know that Coffer is a magic fake type, with possibly different > rules? by reading the JLS, it's the same way you know that you can do a += on a Double or call values() on an enum. > If Coffer accepts primitive args, users would be confused that they can > say Coffer but not List, etc) and generalized magic-angst (?why can?t > I write my own type operators.?). Why do you want Coffer to accept primitive args ? and i don't get the "why can?t I write my own type operators ?", you can't because you don't control the JLS. Or are you referencing an old proposal of John about adding an open ended number of postfix type operators, but at that point i'm lost. What you are trying to express is that the way Coffer works is more similar to a reified generics than our current generics, no ? In that case the answer is yes, but i don't think it's an issue when we will look at that feature from LW3000 when generics will be reified. > > All that said, I think we?re getting way^3 ahead of ourselves. I still don?t > think you?ve adequately outlined what problem you think needs solving; I get > that you think it would be not-great to use V? types in public APIs, but it?s a > long leap from there to this proposal. I would like you to answer honestly to that question, why all inline classes are not always nullable ? With that model, we are not able to squeeze as much performance as with a non nullable inline class (apart the happy cases where there is at least 1 bit left due to the alignment) but we offer a far simpler model which is one of the Java trademark. Because if it's okay to have V? types in the public APIs, it's okay to propagate them in between APIs and at that point your performance are not better than using escape analysis. In fact, it's worst because all the spurious NPE that will come from the conversion in between V and V? So either we go with a complex model and we recognize that V? has to be used with care or perhaps better, we decide that inline class are always nullable (and there is an opt-in to "encode" null in an user-controlled way). R?mi > > >> On May 9, 2019, at 10:54 AM, Maurizio Cimadamore >> wrote: >> >> >> On 09/05/2019 13:35, forax at univ-mlv.fr wrote: >>> yes, it's verbose by design. >> >> I object to this a bit. >> >> There will be cases where using nullable projection will be _the only_ way to >> solve certain problems (e.g. to build value types that can reference to >> themselves). Forcing an heavy syntax on these cases seems punitive. You seem to >> assume that, once we have specialized generics, people will just use them and >> forget about nullable projections. I don't think that's the case, and some >> internal discussions we started (e.g. to sprinkle values on HashMap >> implementation) seem to point in that direction too. >> >> Maurizio From forax at univ-mlv.fr Thu May 9 21:51:30 2019 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 9 May 2019 23:51:30 +0200 (CEST) Subject: It's not safe until it's in the coffer In-Reply-To: <25347de8-e414-578f-4e75-2edda3c4a8a7@oracle.com> References: <593160089.882085.1557353524555.JavaMail.zimbra@u-pem.fr> <494bb07e-3180-d95d-1fc3-e51713b524ff@oracle.com> <960275818.1072692.1557405316949.JavaMail.zimbra@u-pem.fr> <25347de8-e414-578f-4e75-2edda3c4a8a7@oracle.com> Message-ID: <366996678.1203779.1557438690592.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Maurizio Cimadamore" > ?: "Remi Forax" > Cc: "valhalla-spec-experts" > Envoy?: Jeudi 9 Mai 2019 19:54:17 > Objet: Re: It's not safe until it's in the coffer > On 09/05/2019 13:35, forax at univ-mlv.fr wrote: >> yes, it's verbose by design. > > I object to this a bit. if it's just a bit :) > > There will be cases where using nullable projection will be _the only_ > way to solve certain problems (e.g. to build value types that can > reference to themselves). Forcing an heavy syntax on these cases seems > punitive. it's notheavy, it's bulkier than the V? syntax > You seem to assume that, once we have specialized generics, > people will just use them and forget about nullable projections. I don't > think that's the case, and some internal discussions we started (e.g. to > sprinkle values on HashMap implementation) seem to point in that > direction too. no, i don't assume that, i assume that the nullable projection is a double edged sword so you can use it at your own risk but for that you have to opt-in and not use randomly V or V? because you don't want to know the difference. > > Maurizio R?mi From forax at univ-mlv.fr Fri May 10 20:50:33 2019 From: forax at univ-mlv.fr (Remi Forax) Date: Fri, 10 May 2019 22:50:33 +0200 (CEST) Subject: V? and generics Message-ID: <1463918186.1585701.1557521433693.JavaMail.zimbra@u-pem.fr> Let's say i have this interface: interface Orderable> { boolean lessThan(T t); } and i want my inline class to implement it: @__inline__ class FooOrderable implements Orderable { ... @Override public boolean lessThan(FooOrderable? foo) { return false; } } how i'm suppose to write it given that the bound of FooOrderable as to be Orderable but Orderable is not a valid type ? I think that we have moved from a generic of an inline class is unsafe (because of the NPEs) to it's an illegal type a little to fast. I believe we should emit an unchecked warning instead with the definition of unchecked to be widened to include not only the CCEs but also the NPEs. R?mi From peter.levart at gmail.com Sat May 11 19:50:18 2019 From: peter.levart at gmail.com (Peter Levart) Date: Sat, 11 May 2019 21:50:18 +0200 Subject: a new contract for reference types In-Reply-To: <58B64983-8DE5-48C3-8826-577E3550D008@oracle.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> <58B64983-8DE5-48C3-8826-577E3550D008@oracle.com> Message-ID: <1ab2b09a-a251-485c-47ee-8814d0cbc6ef@gmail.com> Hi, On 5/8/19 7:16 PM, John Rose wrote: > On May 7, 2019, at 11:37 PM, Peter Levart wrote: >> On 5/2/19 12:29 AM, John Rose wrote: >>> Regarding subtyping, I don't see (from these considerations) >>> a firm reason to declare that V? is a super of V. The value >>> set of V?*might* have one more point than that of V, >>> or it*might not*. The reason we are doing V? is not the >>> value set, but the whole contract, which includes the >>> value set as an obvious, but ultimately non-determinative part. >> Just one observation... >> >> If inline class V was declared to support a "kind" of null (default, sentinel) value by itself, then how such value would be denoted? >> >> Is this a way? >> >> V v = null; > Yes, because there's only one null in the whole world. > > (The possibility of having many kinds of null, perhaps > one per type, is something we are trying to avoid. > Null is a costly feature, sometimes referred to as a > billion dollar mistake[1]. We have to deal with it > in Java. Adding more of them would be even more > costly IMO.) > > [1]: https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare A really good and though provoking talk. In particular I liked the part where Tony Hoare compares flow control abstractions in high level languages (loops, if-then-else, exceptions) with data structure abstractions. The machine level building block for the first is jump instruction, while for the second a pointer. While there are several different flow control abstractions, there's not much that is abstracted about pointers in high level languages. V vs. V? seems to be an abstraction in that direction that is just approximately tied to the machine level implementation. So a question arises whether to allow calling instance methods on null V or to runtime check for null (sentinel) value and throw NPE at call site. Since null (sentinel) value of null capable V is represented by a real state, it should be possible for instance methods to operate on that state, but... > >> If this was possible, then what would be the distinction between the following two then? >> >> V? vInd1 = null; >> V? vInd2 = v; >> >> Would vInd1 and vInd2 represent the same "null" value? > Yes, please please please. ... what should be the outcome of invoking an instance method on a null V? then? If you allow calling instance method on a null V: V v = null; v.m(); // OK Then the following becomes confusing for the user: V v = null; v.m(); // OK V? vInd = v; vInd.m(); // NPE or OK ? You might implement the 2nd call to operate on a re-constructed null (sentinel) state of V in that case, but then throwing NPE or not becomes a matter of whether V is null-sentinel capable or not, because you can not construct null state when V does not declare that capability. So the only consistent behavior seems to be to always throw NPE on null, which might involve runtime check for null sentinel state. Regards, Peter From peter.levart at gmail.com Sun May 12 09:33:13 2019 From: peter.levart at gmail.com (Peter Levart) Date: Sun, 12 May 2019 11:33:13 +0200 Subject: a new contract for reference types In-Reply-To: <1ab2b09a-a251-485c-47ee-8814d0cbc6ef@gmail.com> References: <808908220.510660.1556715460517.JavaMail.zimbra@u-pem.fr> <0A9F753B-B2F7-4867-875E-BDD0E48DB87B@oracle.com> <539081449.514328.1556719645915.JavaMail.zimbra@u-pem.fr> <7FE66A56-923D-41AB-AFEC-51F4D2DE016C@oracle.com> <4d7025b6-e3b3-5de0-7513-a15e978b40bb@cs.oswego.edu> <17ACA497-5669-4DDE-BDE0-765C97232E03@oracle.com> <58B64983-8DE5-48C3-8826-577E3550D008@oracle.com> <1ab2b09a-a251-485c-47ee-8814d0cbc6ef@gmail.com> Message-ID: <115bb54c-0f2c-93f3-58d0-616d275a3b19@gmail.com> On 5/11/19 9:50 PM, Peter Levart wrote: > > So a question arises whether to allow calling instance methods on null > V or to runtime check for null (sentinel) value and throw NPE at call > site. > > Since null (sentinel) value of null capable V is represented by a real > state, it should be possible for instance methods to operate on that > state, but... > ... > ... what should be the outcome of invoking an instance method on a > null V? then? > > > If you allow calling instance method on a null V: > > > V v = null; > > v.m(); // OK > > > Then the following becomes confusing for the user: > > > V v = null; > > v.m(); // OK > > V? vInd = v; > > vInd.m(); // NPE or OK ? > > > You might implement the 2nd call to operate on a re-constructed null > (sentinel) state of V in that case, but then throwing NPE or not > becomes a matter of whether V is null-sentinel capable or not, because > you can not construct null state when V does not declare that capability. > > > So the only consistent behavior seems to be to always throw NPE on > null, which might involve runtime check for null sentinel state. > On the other hand, there might be another way out of this problem. Suppose that all inline classes were null capable. Suppose that it was up to the inline class declaration to decide whether its null value is also part of the "normally constructable" values set or whether it is a value that can not possibly be constructed in a normal way (other than assigning null to a variable). In that case every inline class would have a null state defined, calls to instance methods of null values would be possible and there will be no need for runtime checks for null values. Regards, Peter From brian.goetz at oracle.com Mon May 13 16:46:12 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 13 May 2019 12:46:12 -0400 Subject: V? and generics In-Reply-To: <1463918186.1585701.1557521433693.JavaMail.zimbra@u-pem.fr> References: <1463918186.1585701.1557521433693.JavaMail.zimbra@u-pem.fr> Message-ID: <284b723d-9948-b280-24ce-d78e5e252e71@oracle.com> The question about "what about F-bounds" is a good one; thanks for raising this.? Needs further thought. But, while I agree you've raised a problem, I think it's a pretty big leap to the "solution" you propose.? So let's table that (re-)proposal pending a deeper understanding of the problem, and its relation to the other requirements. On 5/10/2019 4:50 PM, Remi Forax wrote: > Let's say i have this interface: > interface Orderable> { > boolean lessThan(T t); > } > > and i want my inline class to implement it: > @__inline__ class FooOrderable implements Orderable { > ... > @Override > public boolean lessThan(FooOrderable? foo) { > return false; > } > } > > how i'm suppose to write it given that the bound of FooOrderable as to be Orderable but Orderable is not a valid type ? > > I think that we have moved from a generic of an inline class is unsafe (because of the NPEs) to it's an illegal type a little to fast. > > I believe we should emit an unchecked warning instead with the definition of unchecked to be widened to include not only the CCEs but also the NPEs. > > R?mi From maurizio.cimadamore at oracle.com Mon May 13 20:02:05 2019 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Mon, 13 May 2019 21:02:05 +0100 Subject: V? and generics In-Reply-To: <284b723d-9948-b280-24ce-d78e5e252e71@oracle.com> References: <1463918186.1585701.1557521433693.JavaMail.zimbra@u-pem.fr> <284b723d-9948-b280-24ce-d78e5e252e71@oracle.com> Message-ID: <4f5d60f6-dc9c-d992-564b-ff88a25899d0@oracle.com> Actually, I'm not sure I see the problem. The well formedness rules in the JLS say that it must be: FooOrderable? <: [T:=FooOrderable?]Orderable (that is, the actual type argument must be a subtype of the bound where type-variables are replaced for the type-parameter) If you expand that you get: FooOrderable? <: Orderable Which seems trivially true (the supertype of FooOrderable is the same as that of FooOrderable? and is Orderable). Can we please clarify as to what the problem is? Maurizio On 13/05/2019 17:46, Brian Goetz wrote: > The question about "what about F-bounds" is a good one; thanks for > raising this.? Needs further thought. > > But, while I agree you've raised a problem, I think it's a pretty big > leap to the "solution" you propose.? So let's table that (re-)proposal > pending a deeper understanding of the problem, and its relation to the > other requirements. > > On 5/10/2019 4:50 PM, Remi Forax wrote: >> Let's say i have this interface: >> ?? interface Orderable> { >> ??? boolean lessThan(T t); >> ?? } >> >> and i want my inline class to implement it: >> ?? @__inline__ class FooOrderable implements Orderable { >> ???? ... >> ???? @Override >> ???? public boolean lessThan(FooOrderable? foo) { >> ?????? return false; >> ???? } >> ?? } >> >> how i'm suppose to write it given that the bound of FooOrderable as >> to be Orderable but Orderable is not a >> valid type ? >> >> I think that we have moved from a generic of an inline class is >> unsafe (because of the NPEs) to it's an illegal type a little to fast. >> >> I believe we should emit an unchecked warning instead with the >> definition of unchecked to be widened to include not only the CCEs >> but also the NPEs. >> >> R?mi > From frederic.parain at oracle.com Wed May 15 20:37:06 2019 From: frederic.parain at oracle.com (Frederic Parain) Date: Wed, 15 May 2019 16:37:06 -0400 Subject: @Contended and inline classes Message-ID: <490F8BA7-CD67-4D21-8124-1A6D721F36DD@oracle.com> Here?s the basic question: how the JVM should handle the @Contended annotation with respect to inline classes? Here?s some thoughts: First scenario: the @Contended annotation is used within an inline class: The @Contended annotation aims to solve the problem of false sharing, but false sharing requires that the data in the cache are altered. Because inline classes are immutable, no write operation can be performed on their fields, so no false sharing is possible between fields of a single inline class. So there?s no point to change the layout of the inline class to put fields on different cache lines. In addition to that, each use the @Contended adds 256 bytes to the size of the instance (at least on the current HotSpot implementation), which is well above the threshold we have considered reasonable so far to flatten an inline classes instance. So the proposal would be to simply ignore @Contended when used in an inline class. The javadoc of @Contended describes the annotation as a hint to the JVM, so there?s no strict requirement to alter the layout because of the annotation. Second scenario: A regular class has a field which is an inline class, and this field is annotated with @Contended This use case still makes sense, to isolate this field (which could be flattened or not) from other fields. This use of @Contended impacts the layout of the container (the regular class) but not the layout of the inline class. In this case, the JVM should use the hint to compute a layout isolating the inline class field. Does this analysis make sense to you? Feedback and comments are welcome. Regards, Fred From brian.goetz at oracle.com Wed May 15 20:44:41 2019 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 15 May 2019 16:44:41 -0400 Subject: @Contended and inline classes In-Reply-To: <490F8BA7-CD67-4D21-8124-1A6D721F36DD@oracle.com> References: <490F8BA7-CD67-4D21-8124-1A6D721F36DD@oracle.com> Message-ID: Agreed. And you can always transform the first situation into the second when you need to. > On May 15, 2019, at 4:37 PM, Frederic Parain wrote: > > Here?s the basic question: how the JVM should handle the @Contended > annotation with respect to inline classes? > > Here?s some thoughts: > > First scenario: the @Contended annotation is used within an inline class: > > The @Contended annotation aims to solve the problem of false sharing, > but false sharing requires that the data in the cache are altered. Because > inline classes are immutable, no write operation can be performed on their fields, > so no false sharing is possible between fields of a single inline class. > So there?s no point to change the layout of the inline class to put fields on > different cache lines. > > In addition to that, each use the @Contended adds 256 bytes to the size > of the instance (at least on the current HotSpot implementation), which is > well above the threshold we have considered reasonable so far to flatten > an inline classes instance. > > So the proposal would be to simply ignore @Contended when used > in an inline class. The javadoc of @Contended describes the annotation > as a hint to the JVM, so there?s no strict requirement to alter the layout > because of the annotation. > > Second scenario: A regular class has a field which is an inline class, and > this field is annotated with @Contended > > This use case still makes sense, to isolate this field (which could be > flattened or not) from other fields. This use of @Contended impacts > the layout of the container (the regular class) but not the layout of > the inline class. > > In this case, the JVM should use the hint to compute a layout isolating > the inline class field. > > Does this analysis make sense to you? Feedback and comments > are welcome. > > Regards, > > Fred > > > From dl at cs.oswego.edu Wed May 15 23:08:15 2019 From: dl at cs.oswego.edu (Doug Lea) Date: Wed, 15 May 2019 19:08:15 -0400 Subject: @Contended and inline classes In-Reply-To: <490F8BA7-CD67-4D21-8124-1A6D721F36DD@oracle.com> References: <490F8BA7-CD67-4D21-8124-1A6D721F36DD@oracle.com> Message-ID: <0c526380-64af-d520-f790-b23441c0552a@cs.oswego.edu> On 5/15/19 4:37 PM, Frederic Parain wrote: > Here?s the basic question: how the JVM should handle the @Contended > annotation with respect to inline classes? I agree to ignore, or perhaps better make it a compiler warning. It doesn't make much sense to say "@Contended inline class" because at the point of declaration, you normally don't know what it will be inlined into (maybe just stack frames). But it should remain legal to have a @Contended field of another (regular) class that happens to be an inline class instance. As in: inline class IC { ... } class OC { @Contended IC aField; ... } -Doug > > Here?s some thoughts: > > First scenario: the @Contended annotation is used within an inline class: > > The @Contended annotation aims to solve the problem of false sharing, > but false sharing requires that the data in the cache are altered. Because > inline classes are immutable, no write operation can be performed on their fields, > so no false sharing is possible between fields of a single inline class. > So there?s no point to change the layout of the inline class to put fields on > different cache lines. > > In addition to that, each use the @Contended adds 256 bytes to the size > of the instance (at least on the current HotSpot implementation), which is > well above the threshold we have considered reasonable so far to flatten > an inline classes instance. > > So the proposal would be to simply ignore @Contended when used > in an inline class. The javadoc of @Contended describes the annotation > as a hint to the JVM, so there?s no strict requirement to alter the layout > because of the annotation. > > Second scenario: A regular class has a field which is an inline class, and > this field is annotated with @Contended > > This use case still makes sense, to isolate this field (which could be > flattened or not) from other fields. This use of @Contended impacts > the layout of the container (the regular class) but not the layout of > the inline class. > > In this case, the JVM should use the hint to compute a layout isolating > the inline class field. > > Does this analysis make sense to you? Feedback and comments > are welcome. > > Regards, > > Fred > > > > From karen.kinnear at oracle.com Tue May 21 17:26:26 2019 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Tue, 21 May 2019 13:26:26 -0400 Subject: Valhalla EG notes April 24, 2019 Message-ID: <1C911A3E-8478-48FB-821A-76BEF6AE18DB@oracle.com> Attendees: Tobi, Dan H, John, Frederic, Karen short meeting due to Oracle meeting conflict immediately following. I. Inline class static field circularity It is necessary to eagerly load any embedded fields that we want to actually flatten. This can lead to circularities - either directly or indirectly. Question was whether we need to consider actual flattening (not the same as flattenability) for statics? Benefits and costs? Performance - from earlier hotspot experiments, an additional indirection on static fields had no significant performance cost. Costs: complexity for circularities larger than directly containing self Conclusion: we can offer flattenable semantics for statics and not actually flatten them. II. John: Propose inline factory: static that returns self JVMS will need modifications - e.g. relax structural constraints Verifier will allow invokespecial for existing that returns void only Core reflection will see these new static methods as constructors MethodHandles will see these as both constructors and static methods ed. note: clarification from John - for java.lang.reflect: all constructors and static methods will be exposed as constructors. Neither will be exposed as methods. This is because java.lang.Reflect is about language-level constructs. for java.lang.invoke: findConstructor will only find constructors that use the new/dup/invokespecial model. MethodHandles will see these only as static methods. This is because the java.lang.invoke package is about ?bytecode behaviors?. Dan H: full range of access controls on static ? John: yes Dan H: will non inline classes have a static ? John: no. non-inline classes should have an instance ()V inline classes may not have an instance ()V, and may define a static ()this Karen: can an inline class omit a static ? John: yes - e.g. anonymous class - name is not mentionable in a descriptor From karen.kinnear at oracle.com Fri May 31 18:51:32 2019 From: karen.kinnear at oracle.com (Karen Kinnear) Date: Fri, 31 May 2019 14:51:32 -0400 Subject: Valhalla EG minutes May 22, 2019 Message-ID: Attendees: Remi, Tobi, Dan H, John, David Simms, Frederic, Karen I. Remi: the new static ()this needs to work with indy, but today you can?t use ?<>? in the name. John: the MethodHandle is legit Dan H: name in a BSM does not have to relate to the underling method Remi: BSM has to change so that the name allows (i.e. brackets) II. withfield - is staying III. @Contended Ignore for an inline class or within an inline class, ok for a field containing an inline class see: http://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2019-May/001074.html Dan H: @Contended is for bootclasspath only, only support class level today Frederic: javadoc on the annotation: Just a hint also: ?trusted" classes only ed. note: I believe trusted classes means bootclasspath or platform class loader IV. Karen: There have been some email exchanges recently and I wanted to make sure we all were using the same terminology. For example, when we get to LW20 and offer support for null-default inline classes, we have been using the symbols: NV and NV? Note - that both are nullable. My question - what is the difference between them and do we need two ?types? here? Remi: presented a session last week. ??? syntax was confusing to people a. relative to Kotlin and b. why not on reference classes John: Nullable is a side issue. The difference between NV and NV? for an inline class is whether the class is handled embedded vs. indirect Remi: NV? has an L-signature, right? Still, it is an inline class? John: ?L? notation - does not allow us to find out if it is an inline class before use. So consistently, it is not determinable if this is an inline class. Remi: Once we load the class we will know it is an inline class. Need to consider separate compilation handling. Karen: Note that the ?L? descriptor in this model does NOT imply identity. It does imply indirect. Remi: What if we were to throw an exception if an L descriptor defined an inline class, even when lazily loaded (e.g. post verification)? Karen: Due to the current proposal of VBC migration, existing ?L? signatures would be used, and some clients would be aware that this was now an inline class and some would not. Remi: If NV? is not flattenable - is it still scalarizable on stack? John: Trying to avoid corner cases - which cause a long trail of tears old contract vs. new contract old contract: always indirect references heap storage is always indirect always nullable can be treated opaquely allows lazy loading allows circularity because it allows lazy loading Remi: There is a declaration world and a runtime world. If you declare as L and actually load the class and it is an inline class - does acmp determine identity handling vs. identities handling via descriptor? [ed note: no - acmp has to check the runtime type to see if it is inline vs. supports identity) John: Container semantics - define what it can contain - old vs. new contract new contract: load before layout Karen: concern about needing to know if nullable or not both programmer?s perspective - if switching from Point to Point? not only changes to indirect, but also allows null and vm perspective - as we discussed in the past, the JIT needs to know null-free for max optimizations John: bridging will allow going from old descriptor to new descriptor maybe also allow changing name? Remi: For renaming - what if that information was in module-info? The module-infos are loaded before the containers Karen: that is a partial solution to the problem John: great when you can do it. The vm always needs to know. Remi: all value-based-classes (VBCs) are currently in java.base or JDK Karen: Do others use VBCs? We could restrict migration of VBCs to java.base or JDK or in a module John: ?adhoc? types we control need to define an overall policy clear old and new contracts and bridging technology Karen: Question is: with a new (not migrated VBC) null-default inline class - e.g. Person, does it need two representations? John: When would a developer need to specify ?indirect?? 1. instance field circularity 2. atomicity - for containers in the heap only if the use-site does not want to say Volatile 3. arrays: e.g. performance - for heap container - e.g. if lots of copies are performed e.g. large object John: The translation strategy makes adhoc decisions between the old and new contract (ed. note - I think what John is saying that even if a user specifies ?new? contract, i.e. please inline, the vm makes the decision of whether an inline class is inlined or not - e.g. based on size or atomicity) set a default policy allow advanced users to influence the decision Remi: One challenge for power users, is that an specific optimization often applies at one point in time, and not later (changes in software or hardware) - like ?register? keyword in C - the decision was meaningful at one time An annotation perhaps Dan H: This might be different - since it ties into the data structure layout A change might be a surprise to users, they might be concerned if we ignore the hint Remi: Not want the hint in JVMS, like @Contended John: there is a language syntax point of view goal: simplest default - does the desirable thing want naturally inline object might want different - e.g. for generics or performance want a syntax that implies that this would not be for general use Karen: For NV and NV? (or Person/Person?) would we be looking at a subtype relationship or a conversion? This impacts verification and array covariance John: If contract is about containers This allows the vm to check correctness - specifically for a value set e.g. checkcast/ArrayStoreException/NullPointerException - if try to add null goal: the verifier type system forces the right checks whether that is a subtype/supertype or checkcast check prefer never checkcast to LObject (ed. note - my notes are not clear here) John: new contract: load class file eagerly and look at the definition verifier - only use information you have from descriptor, still tries to not load classes eagerly old contract: you do not know if you have an inline class or an indirect class you do not know if you have null ok or null free Karen: We have already discussed that we want the verifier to not eagerly load and still be able to exclude nulls so we need a use-site signal John: That is a requirement on the descriptor format, that the container is null-hostile Karen: Need to be clear that inline vs. indirect is not about null-ok/null-hostile John: distinguish between - ?can use opaquely? vs. ?must eagerly load and find out from class file? Agreed: verifier specifically - without loading can check null-free In the end we might not need that Remi: Kotlin - require-not null John: shake out in prototyping null-ok/null-hostile is not the primary dimension John: Also want old/new contract with templates templatedtype as a pure symbol vs. expand e.g. Optional vs. Optional some uses of template type need to be opaque, to allow circularities need to distinguish - indirect with abstraction vs. inlining with eager expansion still need a pair of contracts Karen: Doesn?t the wildcard/raw type already represent the non-expanded abstract use case? Or the erased generic use of jlObject? What problem does this not solve? John: Those are both old contract This solves most problems - but not corner cases such as - changes to overloading and overriding rules based on signature matching - therefore would want different method descriptors Remi: Useful for code specialization, even if indirect type e.g. HashMap specialization is orthogonal to inline vs. indirect corrections welcome, thanks, Karen