And the next iteration of the loop I think lands in a more comfortable
place.
Constable did indeed die, to be renamed to SymbolicRef. A SymbolicRef,
is, well, a symbolic reference for some classfile or platform entity,
including constants, but also possibly including annotations, classfile
attributes, indy bootstrap specifiers, or other constructs.
Most symbolic references have a live object analogue; ClassRef
corresponds to a Class, MethodTypeRef corresponds to a MethodType.
Some symbolic references are their own live object; this is true for
String, Integer, Float, Long, and Double.
Constable was then reborn to mean something else -- something that is
constant-able -- i.e., a live object that can be naturally represented
in the constant pool. This includes String and friends from above, as
well as Class, MethodType, and MethodHandle -- as well as anything that
knows how to represent itself in the constant pool with condy, like var
handles or enum constants.
So:
- Constable -- represents a live object that also knows how to
construct a symbolic reference for itself. Constructing a symbolic
reference is a partial function; not all method handles can be
represented in the constant pool directly, just the direct kind (for now).
- SymbolicRef -- a symbolic (purely nominal) descriptor for some
object. These can be resolved reflectively or can be intrinsified into
the constant pool. Symbolic references also implement Constable, so you
can explicitly store a symbolic ref in the CP (with condy).
- SymbolicRef.OfSelf -- for the types that act as their own symbolic ref.
On 9/22/2017 11:14 AM, Brian Goetz wrote:
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