8057657: Annotate LambdaForm parameters with types
Reviewed-by: vlivanov, psandoz
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
index f59b19d..6086310 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java
@@ -138,7 +138,8 @@
*/
static BoundMethodHandle makeReinvoker(MethodHandle target) {
LambdaForm form = DelegatingMethodHandle.makeReinvokerForm(
- target, MethodTypeForm.LF_REBIND, Species_L.SPECIES_DATA.getterFunction(0) );
+ target, MethodTypeForm.LF_REBIND,
+ Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0));
return Species_L.make(target.type(), form, target);
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java
index 3079fd7..63ba8fe 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java
@@ -85,12 +85,13 @@
private static LambdaForm chooseDelegatingForm(MethodHandle target) {
if (target instanceof SimpleMethodHandle)
return target.internalForm(); // no need for an indirection
- return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, NF_getTarget);
+ return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget);
}
/** Create a LF which simply reinvokes a target of the given basic type. */
static LambdaForm makeReinvokerForm(MethodHandle target,
int whichCache,
+ Object constraint,
NamedFunction getTargetFn) {
MethodType mtype = target.type().basicType();
boolean customized = (whichCache < 0 ||
@@ -108,6 +109,7 @@
final int REINVOKE = nameCursor++;
LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType());
assert(names.length == nameCursor);
+ names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint);
Object[] targetArgs;
if (customized) {
targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class);
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
index 09320df..12a118a 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java
@@ -260,7 +260,9 @@
: Arrays.asList(mtype, customized, which, nameCursor, names.length);
if (MTYPE_ARG >= INARG_LIMIT) {
assert(names[MTYPE_ARG] == null);
- NamedFunction getter = BoundMethodHandle.speciesData_L().getterFunction(0);
+ BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L();
+ names[THIS_MH] = names[THIS_MH].withConstraint(speciesData);
+ NamedFunction getter = speciesData.getterFunction(0);
names[MTYPE_ARG] = new Name(getter, names[THIS_MH]);
// else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM)
}
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
index 989f0e6..c6027ea 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java
@@ -460,6 +460,11 @@
return param;
}
+ /** Report the N-th argument type constraint. */
+ Object parameterConstraint(int n) {
+ return parameter(n).constraint;
+ }
+
/** Report the arity. */
int arity() {
return arity;
@@ -1421,6 +1426,7 @@
final BasicType type;
private short index;
final NamedFunction function;
+ final Object constraint; // additional type information, if not null
@Stable final Object[] arguments;
private Name(int index, BasicType type, NamedFunction function, Object[] arguments) {
@@ -1428,8 +1434,18 @@
this.type = type;
this.function = function;
this.arguments = arguments;
+ this.constraint = null;
assert(this.index == index);
}
+ private Name(Name that, Object constraint) {
+ this.index = that.index;
+ this.type = that.type;
+ this.function = that.function;
+ this.arguments = that.arguments;
+ this.constraint = constraint;
+ assert(constraint == null || isParam()); // only params have constraints
+ assert(constraint == null || constraint instanceof BoundMethodHandle.SpeciesData || constraint instanceof Class);
+ }
Name(MethodHandle function, Object... arguments) {
this(new NamedFunction(function), arguments);
}
@@ -1477,7 +1493,11 @@
}
Name cloneWithIndex(int i) {
Object[] newArguments = (arguments == null) ? null : arguments.clone();
- return new Name(i, type, function, newArguments);
+ return new Name(i, type, function, newArguments).withConstraint(constraint);
+ }
+ Name withConstraint(Object constraint) {
+ if (constraint == this.constraint) return this;
+ return new Name(this, constraint);
}
Name replaceName(Name oldName, Name newName) { // FIXME: use replaceNames uniformly
if (oldName == newName) return this;
@@ -1557,7 +1577,12 @@
return (function == null) ? s : s + "=" + exprString();
}
public String paramString() {
- return toString();
+ String s = toString();
+ Object c = constraint;
+ if (c == null)
+ return s;
+ if (c instanceof Class) c = ((Class<?>)c).getSimpleName();
+ return s + "/" + c;
}
public String exprString() {
if (function == null) return toString();
@@ -1679,6 +1704,7 @@
static Name internArgument(Name n) {
assert(n.isParam()) : "not param: " + n;
assert(n.index < INTERNED_ARGUMENT_LIMIT);
+ if (n.constraint != null) return n;
return argument(n.index, n.type);
}
static Name[] arguments(int extra, String types) {
diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
index 5ba63f9..649e6c5 100644
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
@@ -710,6 +710,7 @@
Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
+ names[THIS_MH] = names[THIS_MH].withConstraint(data);
names[GET_TARGET] = new Name(data.getterFunction(0), names[THIS_MH]);
names[GET_CLASS] = new Name(data.getterFunction(1), names[THIS_MH]);
names[GET_CATCHER] = new Name(data.getterFunction(2), names[THIS_MH]);