Enhancing java.lang.constant for Valhalla
Brian Goetz
brian.goetz at oracle.com
Tue Dec 14 19:48:42 UTC 2021
The jl.constant API will have to be updated somewhat for Valhalla.
Since it was already on the drawing board when we designed jl.constant,
shouldn't be too bad, but there are a few subtleties. Now that the
descriptors are largely settling down, we can take a stab at this.
ClassDesc (the base abstraction) has several factories to get a CD from
a String:
of(String qualifiedName)
of(String packageName, unqualifiedClassName)
ofDescriptor(String fieldDescriptor)
Obviously we can already represent extended primitives with the last of
these, but doing nothing else would make them somewhat second-class.
For reference, we also have combinators:
nested(String unqualifiedNestedName): give me a ClassDesc for a
class nested in this one
arrayType(): give me a ClassDesc for the array with this component type
componentType(): (partial) give me a ClassDesc for the component
type of this one, assuming this one is an array type
With the addition of Q descriptors, this library reveals itself to be
L-biased; ClassDesc.of("com.foo.Bar") gives us an L-Bar. ("You could
look in the classfile", I hear some of you say. Not so fast; this is a
symbolic API, not a reflective one, by design.) But this is OK; L is a
reasonable default.
The fully orthogonal version would involve adding:
static ClassDesc ofValue(qualifiedName)
static ClassDesc ofValue(String packageName, unqualifiedClassName)
boolean isValue()
ClassDesc valueType() // flip to Q
ClassDesc refType() // flip to L
But the first two are not really necessary, since they can be expressed
both with ClassDesc.of(name).valueType(), or with
ClassDesc.ofDescriptor(desc), and I'm inclined to go that route -- the
canonical constructor is ofDescriptor, the others are conveniences
around that, and complex transforms are done by combinators.
Separately, over in bytecode-API land, we have identified a desire for
another overload of ClassDesc::of, which is one that takes an internal
(slash-separated) name.
One of the horrors of classfile APIs is that the classfile format is
woefully inconsistent about names. Sometimes it wants an internal
binary name (foo/Bar), sometimes a descriptor (Lfoo/Bar;), and there are
other exceptions (e.g., module and package names use dots, operand to
`new` is sometimes an internal binary name, but a descriptor for
arrays.) So accepting any sort of String immediately raises the
question: "in what format?" A more strongly typed API would use
ClassDesc in some places, but given that we might have an internal
binary name, or external binary name, or descriptor in hand, we need a
way to convert all of these to a ClassDesc. For the external binary
name and descriptor, we have ClassDesc::of and ::ofDescriptor, but we're
missing one for internal binary names. So I'm proposing:
ClassDesc ofInternal(String internalBinaryName)
to round out the set.
So, summarizing the new methods (modulo naming changes to reflect
changes in Valhalla language syntax):
ClassDesc ofInternal(String internalBinaryName)
boolean isValue()
ClassDesc valueType()
ClassDesc refType()
Also, eventually, all the *Impl classes in this library can become B2
primitives, since identity doesn't matter.
More information about the valhalla-spec-observers
mailing list