From forax at univ-mlv.fr Sat Sep 2 14:51:42 2017 From: forax at univ-mlv.fr (Remi Forax) Date: Sat, 2 Sep 2017 16:51:42 +0200 (CEST) Subject: Constable interface should die Message-ID: <1058715836.2467666.1504363902094.JavaMail.zimbra@u-pem.fr> Brian ask me to explain my concerns about the Constable interface. The whole constant folding story is like a macro system, it's a limited macro system, but still a macro system. I've developed several macro systems, all have limitations, some limitation that i have introduced voluntarily, some that have appear after being being used, all the macro systems have always evolved after the first release. So the first lesson of designing a macro system seems to be, because it will evolve, it should provide the minimal API so it can be refactored easily. In the case of constant-folding mechanism, it's not a mechanism that target end users but JDK maintainers, so end users should not be able to see the implementation of such mecanism. It's my main concern with the Constable interface, it's a public visible type with a public visible API. We have already introduced in the past a mechanism that requires a specific interaction between the user code, the JDK and the compiler, it's the polymorphic methods signature and it was solved by using a private annotation. I think constant folding should use the same trick. Mark constant foldable type with a hidden annotation (@Constable ?) and mark methods (private) that can be called by the compiler with another hidden annotation (@TrackableConstant ?) and i will be happy. Compared to using an interface, there is a loss of discover-ability from the end user, but their is no loss of compiler checking because the compiler can check if a type is annotated by an annotation the same way it can check if it implements an interface. Now, we can discuss if @Constable should be a public annotation or not because once a type can be constant folded, removing the annotation is a non backward compatible change. So having the @Constable public is perhaps better than having to have a sentence in the middle of the javadoc saying that this is a constant foladable type. Note that constant folding things is also a form of serialization, the first Java serialization API have made that mistake to make the implementation of the part that serialize each object too visible. I think we can do better here. You can also think that like Serializable, Constable could be an empty interface and ldc will take a Constable. But int constant-foldable and i do not see why it should be boxed to an Integer to becomes Constable (The full implication of that is that ldc should be a method with a polymorphic signature but we are moving in that direction anyway). Long live to @Constable ! regards, R?mi From brian.goetz at oracle.com Mon Sep 4 16:38:55 2017 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 4 Sep 2017 12:38:55 -0400 Subject: Remi's fear of the constabulatory In-Reply-To: <1058715836.2467666.1504363902094.JavaMail.zimbra@u-pem.fr> References: <1058715836.2467666.1504363902094.JavaMail.zimbra@u-pem.fr> Message-ID: <739c5be5-0def-c8c3-fc0d-11a1025f02f8@oracle.com> Thanks for putting your thoughts in one place on this.? Now let me see if I can separate this out into the component issues, and maybe there's a better stacking of the story.? There are a number of interlocking design questions here: ?- How do we designate that an object describes a classfile constant? ?- How is constant-ness used in APIs? ?- Is it important to have a uniform means of going from symbolic constant description (e.g., MethodHandleRef) to the live object it represents (e.g., MethodHandle)?? (This requires additional context, such as lookups, class loaders, etc.) ?- Is it important to have a uniform means of going from a live object to a symbolic description?? (This is necessarily a partial function.) ?- Is the set of constant descriptors necessarily extensible, or is the set embodied in j.l.i sufficient? Remi's main objection is (and I am sympathetic to this) that Constable is a public interface, which serves a small audience but pollutes the APIs of classes like String and Integer, where the rest of the world will see it (and wonder what it is for.) Secondarily, Constable has a method that performs reflective conversion from the symbolic form to the live form.? Currently nothing uses this, so arguably this is not needed; if we remove it, Constable becomes a marker interface. The primary value of having Constable be an actual type comes from the API: ??? Intrinsics.ldc(Constable c) ??? BootstrapSpecifier.of(MethodHandleRef bootstrap, Constable... staticArgs) These send a clear signal to the caller about what sort of arguments can be passed (though the compiler still need to apply additional constraints, such as the constables being compile-time constant expressons.)? You could validly argue either way; that "because the compiler still must apply additional outside-the-type-system checks, these could just as well be Object", and also that the type specificity helps users understand the API better. The compiler treatment of these two API points is subtly different.? For the former, the compiler will absolutely require that the passed Constable is indeed a compile-time constant, so it can intrinsify to an LDC.? Whereas for the latter, the compiler will gladly accept non-constant static arguments, and will only balk if these are fed into an Intrinsics.invokedynamic() or ldc() call. Another point in Remi's favor here is that, lacking an adequate sealing mechanism, user-defined instances of Constable would still not be foldable by the compiler.? While this isn't itself a problem, it means that the Constable abstraction is leaky; that the JDK-supplied implementations are magic and blessed, and there's no way for user code to conform to the Constable contract.? While I don't object to this restriction, leaky abstractions are a warning that shouldn't be ignored. Switching to an annotation means that these API points have to switch over to Object.? You could argue (and you are, implicitly) that this is OK; these are low-level, dynamically typed APIs for use by experts, who don't need the hand-holding of type checking. On 9/2/2017 10:51 AM, Remi Forax wrote: > Brian ask me to explain my concerns about the Constable interface. > > The whole constant folding story is like a macro system, it's a limited macro system, but still a macro system. > I've developed several macro systems, all have limitations, some limitation that i have introduced voluntarily, some that have appear after being being used, all the macro systems have always evolved after the first release. > So the first lesson of designing a macro system seems to be, because it will evolve, it should provide the minimal API so it can be refactored easily. > > In the case of constant-folding mechanism, it's not a mechanism that target end users but JDK maintainers, so end users should not be able to see the implementation of such mecanism. > It's my main concern with the Constable interface, it's a public visible type with a public visible API. > > We have already introduced in the past a mechanism that requires a specific interaction between the user code, the JDK and the compiler, it's the polymorphic methods signature and it was solved by using a private annotation. > > I think constant folding should use the same trick. Mark constant foldable type with a hidden annotation (@Constable ?) and mark methods (private) that can be called by the compiler with another hidden annotation (@TrackableConstant ?) and i will be happy. > > Compared to using an interface, there is a loss of discover-ability from the end user, but their is no loss of compiler checking because the compiler can check if a type is annotated by an annotation the same way it can check if it implements an interface. > > Now, we can discuss if @Constable should be a public annotation or not because once a type can be constant folded, removing the annotation is a non backward compatible change. So having the @Constable public is perhaps better than having to have a sentence in the middle of the javadoc saying that this is a constant foladable type. > > Note that constant folding things is also a form of serialization, the first Java serialization API have made that mistake to make the implementation of the part that serialize each object too visible. I think we can do better here. > You can also think that like Serializable, Constable could be an empty interface and ldc will take a Constable. But int constant-foldable and i do not see why it should be boxed to an Integer to becomes Constable (The full implication of that is that ldc should be a method with a polymorphic signature but we are moving in that direction anyway). > > Long live to @Constable ! > > regards, > R?mi > > From maurizio.cimadamore at oracle.com Tue Sep 5 11:50:14 2017 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 5 Sep 2017 12:50:14 +0100 Subject: Remi's fear of the constabulatory In-Reply-To: <739c5be5-0def-c8c3-fc0d-11a1025f02f8@oracle.com> References: <1058715836.2467666.1504363902094.JavaMail.zimbra@u-pem.fr> <739c5be5-0def-c8c3-fc0d-11a1025f02f8@oracle.com> Message-ID: <845b1053-803c-97e3-62a5-241aa74fb324@oracle.com> On 04/09/17 17:38, Brian Goetz wrote: > These send a clear signal to the caller about what sort of arguments > can be passed (though the compiler still need to apply additional > constraints, such as the constables being compile-time constant > expressons.) You could validly argue either way; that "because the > compiler still must apply additional outside-the-type-system checks, > these could just as well be Object", and also that the type > specificity helps users understand the API better. A possible third option when reading this would be: Intrinsics.ldc(@FoldableConstant Object c) BootstrapSpecifier.of(MethodHandleRef bootstrap, @FoldableConstant Object... staticArgs) That is, decouple constant-ness from the type system, and use a dedicated annotation to do that. Maurizio From brian.goetz at oracle.com Thu Sep 21 14:54:00 2017 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 21 Sep 2017 10:54:00 -0400 Subject: Constables API, slightly revamped Message-ID: The document linked below describes the current design center of the API for symbolic references.? This work is driven by the need for intrinsification via JEP 303, but its applicability runs much deeper.? This is a checkpoint along the way; we're not done, but we think that the current approach works well. The current API differs from the previous iteration mostly in focus; we've backed away from trying to describe the constant pool directly, and instead focus primarily on symbolic references, leaving the translation from symbolic reference to compilers and bytecode APIs. You can get a peek at the current state of the API by watching the condy-folding branch of the amber repository. http://cr.openjdk.java.net/~briangoetz/amber/constables.html From brian.goetz at oracle.com Fri Sep 22 15:14:23 2017 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 22 Sep 2017 11:14:23 -0400 Subject: Constable interface should die In-Reply-To: <1058715836.2467666.1504363902094.JavaMail.zimbra@u-pem.fr> References: <1058715836.2467666.1504363902094.JavaMail.zimbra@u-pem.fr> Message-ID: <113776be-1bab-0358-e99e-8611e6796625@oracle.com> So, to close the loop here ... Based on these comments, we went through three more rounds of API design, and ... ended up in a pretty similar place to where we started.? First we tried a more formal separation between "Constable" and "ConstantPoolEntry."? Then we tried a CP-entry-centric approach.? And what that brought us back to was, that the central abstraction here is the symbolic references -- that this isn't only about intrinsification.? (If it were, then the comments regarding macro-systems would be spot-on.)? So the current draft brings the symbolic references front and center -- and leaves intrinsification and constant pool entries deliberately in the background. On 9/2/2017 10:51 AM, Remi Forax wrote: > Brian ask me to explain my concerns about the Constable interface. > > The whole constant folding story is like a macro system, it's a limited macro system, but still a macro system. > I've developed several macro systems, all have limitations, some limitation that i have introduced voluntarily, some that have appear after being being used, all the macro systems have always evolved after the first release. > So the first lesson of designing a macro system seems to be, because it will evolve, it should provide the minimal API so it can be refactored easily. > > In the case of constant-folding mechanism, it's not a mechanism that target end users but JDK maintainers, so end users should not be able to see the implementation of such mecanism. > It's my main concern with the Constable interface, it's a public visible type with a public visible API. > > We have already introduced in the past a mechanism that requires a specific interaction between the user code, the JDK and the compiler, it's the polymorphic methods signature and it was solved by using a private annotation. > > I think constant folding should use the same trick. Mark constant foldable type with a hidden annotation (@Constable ?) and mark methods (private) that can be called by the compiler with another hidden annotation (@TrackableConstant ?) and i will be happy. > > Compared to using an interface, there is a loss of discover-ability from the end user, but their is no loss of compiler checking because the compiler can check if a type is annotated by an annotation the same way it can check if it implements an interface. > > Now, we can discuss if @Constable should be a public annotation or not because once a type can be constant folded, removing the annotation is a non backward compatible change. So having the @Constable public is perhaps better than having to have a sentence in the middle of the javadoc saying that this is a constant foladable type. > > Note that constant folding things is also a form of serialization, the first Java serialization API have made that mistake to make the implementation of the part that serialize each object too visible. I think we can do better here. > You can also think that like Serializable, Constable could be an empty interface and ldc will take a Constable. But int constant-foldable and i do not see why it should be boxed to an Integer to becomes Constable (The full implication of that is that ldc should be a method with a polymorphic signature but we are moving in that direction anyway). > > Long live to @Constable ! > > regards, > R?mi > > From john.r.rose at oracle.com Sun Sep 24 02:38:28 2017 From: john.r.rose at oracle.com (John Rose) Date: Sat, 23 Sep 2017 19:38:28 -0700 Subject: Constable interface should die In-Reply-To: <113776be-1bab-0358-e99e-8611e6796625@oracle.com> References: <1058715836.2467666.1504363902094.JavaMail.zimbra@u-pem.fr> <113776be-1bab-0358-e99e-8611e6796625@oracle.com> Message-ID: On Sep 22, 2017, at 8:14 AM, Brian Goetz wrote: > > First we tried a more formal separation between "Constable" and "ConstantPoolEntry." Then we tried a CP-entry-centric approach. And what that brought us back to was, that the central abstraction here is the symbolic reference In hindsight here's how I see this choice: In the JVMS, symbolic references sit between the low-level constant pool structures of JVMS 4.4 and the resolved "live" values of JVMS 5.4.3. They are decoupled from the concrete, static structures of 4.4 but are not yet resolved. As such, they are exactly the right level for this API, since it models the unresolved references, but without imitating their bitwise layouts in the class file.