JEP draft: unboxed argument lists for method handles

OwnerJohn Rose
Created2017/06/26 06:28
Updated2017/06/26 06:31
TypeFeature
StatusDraft
Componentcore-libs / java.lang.invoke
ScopeJDK
Priority3
Issue8182862

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 MethodTypes 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.