(The name _wither_ method does not mean a way to blight or shrivel
something--certainly a shady activity. It refers to a naming
convention for methods that perform functional update of record
values. Asking a complex number `c.withRe(0)` would return a new
pure-imaginary complex number. By contrast, `c.setRe(0)`, a call to a
_setter_ method, would seem to mutate the complex number, removing any
non-zero real component. Setter methods are appropriate to mutable
objects, while wither methods are appropriate to values. Note that a
method can in fact be a getter, setter, or wither method even if it
does not begin with one of those standard words. The eventual
conventions for value types may well discourage forms like `withRe(0)`
in favor of simply `re(0)`.)
It is likely that these methods in `ValueTypeSupport` will eventually
become virtual methods of `Lookup` itself (if that is the leading
argument), else static methods of `MethodHandles`.
## Future work
This minimal proposal is by nature temporary and provisional. It
gives a necessary foundation for further work, rather than a final
specification. Some of the further work will be similarly provisional
in nature, but over time we will build on our successes and learn
from our mistakes, eventually creating a well-designed specification
that can takes its place in the sun.
This present set of features that support value types will be
difficult to work with; this is intentional. The rest of this
document sketches a few additional features which may enable
experiments not practical or possible in the minimized proposal.
Therefore, this last section may be safely skipped. Any such features
will be given their own supporting documentation if they are pursued.
It may be of interest, however, to people who have noticed missing
features in the minimal values proposal.
### Denoting Q-types in Java source code
At a minimum, no language changes are needed to work with Q-types. A
combination of JVM hacks (value-capable classes), annotation-driven
classfile transformations, and direct bytecode generation are enough
to exercise interesting micro-benchmarks. Method handles supply a
useful alternative to direct bytecode generation, and they will be
made fully capable of working with Q-types (as described below).
Nevertheless, there is nothing like language support. It is likely
that very early experiments with `javac` will create simple ways to
refer to Q-types and create variables for them, directly in Java code
(subject to contextual restrictions, of course).
In particular, constructors for objects have a very different bytecode
shape than seemingly-equivalent constructors for value types. (The
syntax for Java object constructors is a perfectly fine notation for
value type constructors, as long as all fields are final.) It would
be reasonable for javac to take on the burden of byte-compiling both
versions of each constructor of a value-capable class.
Likewise, direct invocation of value type constructors, and direct
access of value type methods and fields, would be convenient to use
from Java source code, even if they had to be compiled to
invokedynamic calls, until bytecode support was completed.
### More constants
Additional enhancements to the constant pool may allow creation of
constants derived from bootstrap methods. Such features are not in
the scope of present document. They are described in the OpenJDK RFE
[JDK-8161256][]. This RFE mentions the present enhancement of
`CONSTANT_Class`.
If this RFE is implemented, it may be possible to delay a few of the
steps described in this section, such as using Q-types as receiver
types for `CONSTANT_MethodHandles`. The key requirement, in any case,
is that invokedynamic instructions be able to refer to a full range of
operations on Q-types, since the invokedyanmic instructions are
standing in as temporarily place-holders for bytecodes we are not yet
implementing.
Independently of user-bootstrapped constants, Q-types in the constant
pool might be carried, most gracefully, by variations on the
`CONSTANT_Class` constant. Right now, we choose to mangle type
descriptors in `CONSTANT_Class` constants as an easy-to-implement
place-holder, but the final design could introduce new constant pool
types to carry the required distinctions.
For example, `CONSTANT_Class` could be kept as-is, and re-labeled
`CONSTANT_ReferenceType`. Then, a new `CONSTANT_Type` constant could
support arbitrary descriptors. (Perhaps it would have other
substructure required by reified generic parameters, but that's
probably yet another kind of constant.) Or, a `CONSTANT_ValueType`
tag could be introduced for symmetry with `CONSTANT_ReferenceType`,
and some other way could be found for mentioning primitive
pseudo-classes. (They are useful as parameters to BSMs.)
### Q-replacement within value-capable classes
A value-capable class, compiled from Java source, may have additional
annotations (or perhaps attributes) on selected fields and methods
which cause the introduction of Q-types, as a bytecode-level
transformation when the value-capable class's file is loaded or
compiled.
Two transformations which seem useful may be called _Q-replacement_
and _Q-overloading_. The first deletes L-types and replaces them by
Q-types, while the second simply copies methods, replacing some or all
of the L-types in their descriptors by corresponding Q-types. This
set of ideas is tracked as [JDK-8164889][].
An alternative to annotation-driven Q-replacment would be an
experimental language feature allowing Q-types to be mentioned
directly in Java source. Such experiments are likely to happen
as part of Project Valhalla, and may happen early enough to make
transformation unnecessary.
### More bytecodes
The library method handle `defaultValueConstant` could be replaced by
a new `vnew` bytecode, or by a prefixed `aconst_null` bytecode.
The library method handle `substitutabilityTest` could be replaced by
a new `vcmp` bytecode, or by a prefixed `if_acmpeq` bytecode.
The library method handle `findWither` could be replaced by a new
`vwithfield` bytecode.
The library method handle `findGetter` could be replaced by a suitably
enhanced `getfield` bytecode.
The library method handle `arrayConstructor` could be replaced by a
suitably enhanced `anewarray` or `multianewarray` bytecode.
The library method handle `arrayElementGetter` could be replaced by a
new `vaload` bytecode, or a prefixed `aaload` bytecode.
The library method handle `arrayElementSetter` could be replaced by a
new `vastore` bytecode, or a prefixed `aastore` bytecode.
The library method handle `arrayLength` could be replaced by a
suitably enhanced `arraylength` bytecode.
### Bridge-o-matic
In some cases, supplying Q-replaced API points in classes is just a
matter of providing suitable bridge methods. Bytecode transformers or
generators can avoid the need to specify the bodies of such bridge
methods if the bridges are (instead of bytecodes) endowed with
suitably organized bootstrap methods. This set of ideas has many
additional uses, including auto-generation of standard `equals`,
`hashCode`, and `toString` methods. It is tracked as [JDK-8164891][].
### Heisenboxes
As suggested above, L-types for values are value-based, and some
version of the JVM may attempt to enforce this in various ways, such
as the following:
* Synchronizing a boxed Q-type value may throw an exception like
`IllegalMonitorStateException`.
* Reference comparision (Java operator `==`, or the `acmp`
instruction) may report "true" on two equivalent boxed Q-type
values, even if the references previously returned false, or
"false" when they previously returned "true". Such variation
would of course be subject to the logic of substitutability, of the
underlying Q-types. Two boxes that were once detected as equal
references would be permanently substitutable for each other.
* Attempts to reflectively store values into the fields of boxed
Q-type values may fail, even after `setAccessible` is called.
* Attempts to reflectively invoke the constructor for the box may
fail, even after `setAccessible` is called.
A box whose identity status is uncertain from observation to
observation is called a "heisenbox". To pursue the analogy, a
reference equality (`==`, `acmp`) observation of `true` for two
heisenboxes "collapses" them into the same object, since they are then
proven fully inter-substitutable, hence their Q-values are equivalent
also. Two copies of the reference can later decohere, reporting
inequality, despite the continued inter-substitutability of the boxed
values. The equality predicate could be investigated by wiring it to
a box containing Schrödinger's cat, with many puzzling and sad
results...
This set of ideas is tracked as [JDK-8163133][].
## References
[values]:
[valhalla-dev]:
[goetz-jvmls15]:
[valsem-0411]:
[simms-vbcs]:
[graves-jvmls16]:
[value-based]:
[Long2.java]:
[cimadamore-refman]:
[JDK-8164891]:
[JDK-8161256]:
[JDK-8164889]:
[JDK-8163133]:
\[values]:
\[valhalla-dev]:
\[goetz-jvmls15]:
\[valsem-0411]:
\[simms-vbcs]:
\[graves-jvmls16]:
\[value-based]:
\[goetz-jvmls16]:
\[Long2.java]:
\[cimadamore-refman]:
\[JDK-8164891]:
\[JDK-8161256]:
\[JDK-8164889]:
\[JDK-8163133]: