From afe2dd89e4600617f374095dc0076e86071026d6 Mon Sep 17 00:00:00 2001 From: John Rose Date: Wed, 10 Sep 2014 19:19:51 +0400 Subject: [PATCH] 8057657: Annotate LambdaForm parameters with types Reviewed-by: vlivanov, psandoz --- .../java/lang/invoke/BoundMethodHandle.java | 3 +- .../lang/invoke/DelegatingMethodHandle.java | 4 ++- .../classes/java/lang/invoke/Invokers.java | 4 ++- .../classes/java/lang/invoke/LambdaForm.java | 30 +++++++++++++++++-- .../java/lang/invoke/MethodHandleImpl.java | 1 + 5 files changed, 37 insertions(+), 5 deletions(-) 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 f59b19d6a7e..6086310085d 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 @@ import jdk.internal.org.objectweb.asm.Type; */ 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 3079fd78a9e..63ba8fea5b2 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 @@ abstract class DelegatingMethodHandle extends MethodHandle { 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 @@ abstract class DelegatingMethodHandle extends MethodHandle { 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 09320dfaee7..12a118a7576 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 @@ class Invokers { : 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 989f0e60a9e..c6027ead2f9 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 @@ class LambdaForm { 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 @@ class LambdaForm { 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 @@ class LambdaForm { 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 @@ class LambdaForm { } 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 @@ class LambdaForm { 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 @@ class LambdaForm { 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 5ba63f9c589..649e6c535e6 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 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; 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]);