-
JEP
-
Resolution: Unresolved
-
P3
-
None
-
None
-
Feature
-
Open
-
JDK
Summary
Add API points to java.lang.invoke
for working with unboxed argument lists.
Goals
A common theme with java.lang.invoke
is transforming calls which
work with variable-length argument lists, especially of type
Object[]
or List<Object>
. These lists often serve as a
dynamically-typed proxy for a more strongly typed collection of
arguments, maybe described by a MethodType
. The reference-based
homogeneous argument list boxes primitives, and will also box future
value types. This boxing, as well as the containing array itself,
creates inefficiencies.
The root cause of the inefficiency is a mismatch between what an
argument list really is and the envelope (homogeneous array or list)
that carries it. We will remove this inefficiency by adding a new
value-based class ArgumentList
which will polymorphically "box" any
valid argument list into a single heap node.
When value types arrive, this class may be upgraded to an interface implemented by value types, allowing on-stack buffering of arbitrary argument lists with zero heap activity.
Success Criteria
If successful, this feature will allow performance-sensitive programmers
to use ArgumentList
as an alternative to homogeneous lists or arrays
when working with method handle signature polymorphism.
This feature will also be useful as a utility type for ad hoc collections of data values, such as are produced by pattern match "extractor" APIs currently under development.
Motivation
New API design with method handles (such as pattern matching) is sometimes blocked or constrained by performance losses from boxing multiple value groups. As value types are adopted, boxing will increase.
Existing code using method handles can in some cases be made more efficient by using box-free (or box-minimal) alternatives to boxed varargs arrays.
A better argument list envelope will allow us to develop more efficient "varargs" mechanisms for the Java language. (A sketch is included below, but is not part of this JEP.)
Description
The type ArgumentList
is either a value-based class or an interface
to a family of private value-based classes.
An instance of an argument list represents a constant set of up to 255
values, each one conforming to an associated (constant) runtime type
(a java.lang.Class
object).
The API for an argument list allows individual arguments to be
extracted under either static or dynamic types. Dynamic typing is
provided by a view of type List<Object>
, which can also be used
to materialize an array of possibly boxed object references.
Static typing is mediated by method handles.
The nested type ArgumentList.Type
provides an API for querying the
type an argument list. There is a 1-1 relation between distinct
argument list types and MethodType
s after return types are
disregarded. (Conventionally the return type is regarded as void
.)
Each argument list type offers a list of method handles, tailored to
ArgumentList
instances of that type, to efficiently extract each
argument from the argument list, without the boxing overheads required
by the dynamically typed view.
An argument list type will also provide a method handle for gathering
a list of arguments (of the corresponding static types) efficiently
into an ArgumentList
instance.
API points in java.lang.invoke
which currently work with variable
arity argument lists (invokeWithArguments
, asSpreader
) or other
groups of arguments (insertArguments
) will acquire additional API
points which operate on ArgumentList
parameters as an alternative
to existing varargs-like APIs.
One or more factory methods for argument lists will be provided also.
These are public API points which can used to create argument lists
with arbitrary component types, determined by the user. Such API
points will be signature polymorphic in the same sense that the
MethodHandle
and VarHandle
invocation points are signature
polymorphic. A likely such API point is ArgumentList.of
.
Possible future varargs extensions
In a later JEP, the varargs mechanism itself may be upgraded in the
Java language to allow polymorphic calls with heterogeneous argument
lists, including the full signature polymorphism enjoyed by method
handle APIs, but also including more limited patterns such as an
alternating key/value argument list for a Map
factory method.
The key insight of this is that a variable-arity API point must
specify both an internal type and an external bundling method for a
group of arguments. The internal type is what the method "sees" after
it is called, but the extern bundling method is used by the caller to
assemble a polymorphically-typed group of arguments into a single
argument. Also, invokedynamic
can play a mediating role.
In the current state of the Java language, the internal type must be an array type, and the bundling method must be the creation of a new array of that type. These procedures can and should be generalized.
A signature polymorphic API point for building argument lists (as proposed by this JEP) is an initial building block for an varargs bundling method, and such bundling methods can be built on top of other bundling methods also. The net result would be allowing library designers or even end-users to create new forms of strongly-typed generic API points with variable arity.
Possible use with pattern matching combinators
Pattern matching consists of examining a single value, comparing it against a user-specified pattern, and giving a "yes" answer if it matches. The "yes" answer is optionally accompanied by a set of range values extracted from points in the pattern which correspond to "wild cards" or "bound variables". This is also like regular expression "groups", whose substrings can be queried after a match is successful.
An object-oriented API for pattern matching must be able (somehow) to return the values and/or locations of any number of range values that are expressed by a pattern. Sometimes this is possible by using a static set of locators (such as method handles) to "pick out" the range values from the originally matched object.
But in the general case, a pattern match operation sometimes needs to buffer up the range values into an ad hoc tuple or record. In the general case, the matched data structure might be mutable, and the record needs to record the state which did match, despite the fact that the state might not match a microsecond later.
In any case, an ad hoc record of match values can be perfectly
represented by an argument list of those values, and it can be
conveniently handed on to the next computation in the chain simply by
calling invokeWithArguments
. Thus, the argument list API is likely
to be a useful component of a general-purpose matching API.
Risks and Assumptions
Low-risk compatible extension to java.lang.invoke
APIs.
Small risk of upgrade path being blocked, from object class to
interface to polymorphic value class. Worst case scenario is having
to add a new value-type that inter-converts with ArgumentList
object
class. This is a similar risk to those faced by java.lang.Integer
and java.util.Optional
when value types arrive.
Dependencies
None.