src/share/classes/java/lang/invoke/MethodHandle.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/share/classes/java/lang/invoke

src/share/classes/java/lang/invoke/MethodHandle.java

Print this page
rev 10273 : 8049555: Move varargsArray from sun.invoke.util package to java.lang.invoke
Reviewed-by: ?
rev 10274 : 8050052: Small cleanups in java.lang.invoke code
Reviewed-by: ?
rev 10275 : 8050053: Improve caching of different invokers
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com
rev 10276 : 8050166: Get rid of some package-private methods on arguments in j.l.i.MethodHandle
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com


 749      * @see MethodHandles#explicitCastArguments
 750      */
 751     public MethodHandle asType(MethodType newType) {
 752         // Fast path alternative to a heavyweight {@code asType} call.
 753         // Return 'this' if the conversion will be a no-op.
 754         if (newType == type) {
 755             return this;
 756         }
 757         // Return 'this.asTypeCache' if the conversion is already memoized.
 758         MethodHandle atc = asTypeCache;
 759         if (atc != null && newType == atc.type) {
 760             return atc;
 761         }
 762         return asTypeUncached(newType);
 763     }
 764 
 765     /** Override this to change asType behavior. */
 766     /*non-public*/ MethodHandle asTypeUncached(MethodType newType) {
 767         if (!type.isConvertibleTo(newType))
 768             throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
 769         return asTypeCache = convertArguments(newType);
 770     }
 771 
 772     /**
 773      * Makes an <em>array-spreading</em> method handle, which accepts a trailing array argument
 774      * and spreads its elements as positional arguments.
 775      * The new method handle adapts, as its <i>target</i>,
 776      * the current method handle.  The type of the adapter will be
 777      * the same as the type of the target, except that the final
 778      * {@code arrayLength} parameters of the target's type are replaced
 779      * by a single array parameter of type {@code arrayType}.
 780      * <p>
 781      * If the array element type differs from any of the corresponding
 782      * argument types on the original target,
 783      * the original target is adapted to take the array elements directly,
 784      * as if by a call to {@link #asType asType}.
 785      * <p>
 786      * When called, the adapter replaces a trailing array argument
 787      * by the array's elements, each as its own argument to the target.
 788      * (The order of the arguments is preserved.)
 789      * They are converted pairwise by casting and/or unboxing


 962      * }</pre></blockquote>
 963      * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
 964      * @param arrayLength the number of arguments to collect into a new array argument
 965      * @return a new method handle which collects some trailing argument
 966      *         into an array, before calling the original method handle
 967      * @throws NullPointerException if {@code arrayType} is a null reference
 968      * @throws IllegalArgumentException if {@code arrayType} is not an array type
 969      *         or {@code arrayType} is not assignable to this method handle's trailing parameter type,
 970      *         or {@code arrayLength} is not a legal array size,
 971      *         or the resulting method handle's type would have
 972      *         <a href="MethodHandle.html#maxarity">too many parameters</a>
 973      * @throws WrongMethodTypeException if the implied {@code asType} call fails
 974      * @see #asSpreader
 975      * @see #asVarargsCollector
 976      */
 977     public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
 978         asCollectorChecks(arrayType, arrayLength);
 979         int collectArgPos = type().parameterCount()-1;
 980         MethodHandle target = this;
 981         if (arrayType != type().parameterType(collectArgPos))
 982             target = convertArguments(type().changeParameterType(collectArgPos, arrayType));
 983         MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength);
 984         return MethodHandles.collectArguments(target, collectArgPos, collector);
 985     }
 986 
 987     /**
 988      * See if {@code asCollector} can be validly called with the given arguments.
 989      * Return false if the last parameter is not an exact match to arrayType.
 990      */
 991     /*non-public*/ boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
 992         spreadArrayChecks(arrayType, arrayLength);
 993         int nargs = type().parameterCount();
 994         if (nargs != 0) {
 995             Class<?> lastParam = type().parameterType(nargs-1);
 996             if (lastParam == arrayType)  return true;
 997             if (lastParam.isAssignableFrom(arrayType))  return false;
 998         }
 999         throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
1000     }
1001 
1002     /**


1235      * When called, the bound handle inserts the given value {@code x}
1236      * as a new leading argument to the target.  The other arguments are
1237      * also passed unchanged.
1238      * What the target eventually returns is returned unchanged by the bound handle.
1239      * <p>
1240      * The reference {@code x} must be convertible to the first parameter
1241      * type of the target.
1242      * <p>
1243      * (<em>Note:</em>  Because method handles are immutable, the target method handle
1244      * retains its original type and behavior.)
1245      * @param x  the value to bind to the first argument of the target
1246      * @return a new method handle which prepends the given value to the incoming
1247      *         argument list, before calling the original method handle
1248      * @throws IllegalArgumentException if the target does not have a
1249      *         leading parameter type that is a reference type
1250      * @throws ClassCastException if {@code x} cannot be converted
1251      *         to the leading parameter type of the target
1252      * @see MethodHandles#insertArguments
1253      */
1254     public MethodHandle bindTo(Object x) {
1255         Class<?> ptype;
1256         @SuppressWarnings("LocalVariableHidesMemberVariable")
1257         MethodType type = type();
1258         if (type.parameterCount() == 0 ||
1259             (ptype = type.parameterType(0)).isPrimitive())
1260             throw newIllegalArgumentException("no leading reference parameter", x);
1261         x = ptype.cast(x);  // throw CCE if needed
1262         return bindReceiver(x);
1263     }
1264 
1265     /**
1266      * Returns a string representation of the method handle,
1267      * starting with the string {@code "MethodHandle"} and
1268      * ending with the string representation of the method handle's type.
1269      * In other words, this method returns a string equal to the value of:
1270      * <blockquote><pre>{@code
1271      * "MethodHandle" + type().toString()
1272      * }</pre></blockquote>
1273      * <p>
1274      * (<em>Note:</em>  Future releases of this API may add further information
1275      * to the string representation.
1276      * Therefore, the present syntax should not be parsed by applications.)
1277      *
1278      * @return a string representation of the method handle
1279      */
1280     @Override
1281     public String toString() {
1282         if (DEBUG_METHOD_HANDLE_NAMES)  return "MethodHandle"+debugString();
1283         return standardString();
1284     }
1285     String standardString() {
1286         return "MethodHandle"+type;
1287     }
1288     /** Return a string with a several lines describing the method handle structure.
1289      *  This string would be suitable for display in an IDE debugger.
1290      */
1291     String debugString() {
1292         return type+" : "+internalForm()+internalProperties();
1293     }
1294 
1295     //// Implementation methods.
1296     //// Sub-classes can override these default implementations.
1297     //// All these methods assume arguments are already validated.
1298 
1299     // Other transforms to do:  convert, explicitCast, permute, drop, filter, fold, GWT, catch
1300 




1301     /*non-public*/
1302     MethodHandle setVarargs(MemberName member) throws IllegalAccessException {
1303         if (!member.isVarargs())  return this;
1304         Class<?> arrayType = type().lastParameterType();
1305         if (arrayType.isArray()) {
1306             return MethodHandleImpl.makeVarargsCollector(this, arrayType);
1307         }
1308         throw member.makeAccessException("cannot make variable arity", null);
1309     }
1310 
1311     /*non-public*/
1312     MethodHandle viewAsType(MethodType newType) {
1313         // No actual conversions, just a new view of the same method.
1314         return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
1315     }
1316 
1317     // Decoding
1318 
1319     /*non-public*/
1320     LambdaForm internalForm() {


1349     /*non-public*/
1350     boolean isInvokeSpecial() {
1351         return false;  // DMH.Special returns true
1352     }
1353 
1354     /*non-public*/
1355     Object internalValues() {
1356         return null;
1357     }
1358 
1359     /*non-public*/
1360     Object internalProperties() {
1361         // Override to something to follow this.form, like "\n& FOO=bar"
1362         return "";
1363     }
1364 
1365     //// Method handle implementation methods.
1366     //// Sub-classes can override these default implementations.
1367     //// All these methods assume arguments are already validated.
1368 
1369     /*non-public*/ MethodHandle convertArguments(MethodType newType) {
1370         // Override this if it can be improved.
1371         return MethodHandleImpl.makePairwiseConvert(this, newType, 1);
1372     }
1373 
1374     /*non-public*/
1375     MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
1376         // Override this if it can be improved.
1377         return rebind().bindArgument(pos, basicType, value);
1378     }
1379 
1380     /*non-public*/
1381     MethodHandle bindReceiver(Object receiver) {
1382         // Override this if it can be improved.
1383         return bindArgument(0, L_TYPE, receiver);
1384     }
1385 
1386     /*non-public*/
1387     MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
1388         // Override this if it can be improved.
1389         return rebind().dropArguments(srcType, pos, drops);
1390     }
1391 
1392     /*non-public*/
1393     MethodHandle permuteArguments(MethodType newType, int[] reorder) {
1394         // Override this if it can be improved.
1395         return rebind().permuteArguments(newType, reorder);
1396     }
1397 
1398     /*non-public*/
1399     MethodHandle rebind() {
1400         // Bind 'this' into a new invoker, of the known class BMH.
1401         MethodType type2 = type();
1402         LambdaForm form2 = reinvokerForm(this);
1403         // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }
1404         return BoundMethodHandle.bindSingle(type2, form2, this);
1405     }
1406 
1407     /*non-public*/
1408     MethodHandle reinvokerTarget() {
1409         throw new InternalError("not a reinvoker MH: "+this.getClass().getName()+": "+this);
1410     }
1411 
1412     /** Create a LF which simply reinvokes a target of the given basic type.
1413      *  The target MH must override {@link #reinvokerTarget} to provide the target.
1414      */
1415     static LambdaForm reinvokerForm(MethodHandle target) {
1416         MethodType mtype = target.type().basicType();
1417         LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE);
1418         if (reinvoker != null)  return reinvoker;
1419         if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY)




 749      * @see MethodHandles#explicitCastArguments
 750      */
 751     public MethodHandle asType(MethodType newType) {
 752         // Fast path alternative to a heavyweight {@code asType} call.
 753         // Return 'this' if the conversion will be a no-op.
 754         if (newType == type) {
 755             return this;
 756         }
 757         // Return 'this.asTypeCache' if the conversion is already memoized.
 758         MethodHandle atc = asTypeCache;
 759         if (atc != null && newType == atc.type) {
 760             return atc;
 761         }
 762         return asTypeUncached(newType);
 763     }
 764 
 765     /** Override this to change asType behavior. */
 766     /*non-public*/ MethodHandle asTypeUncached(MethodType newType) {
 767         if (!type.isConvertibleTo(newType))
 768             throw new WrongMethodTypeException("cannot convert "+this+" to "+newType);
 769         return asTypeCache = MethodHandleImpl.makePairwiseConvert(this, newType, 1);
 770     }
 771 
 772     /**
 773      * Makes an <em>array-spreading</em> method handle, which accepts a trailing array argument
 774      * and spreads its elements as positional arguments.
 775      * The new method handle adapts, as its <i>target</i>,
 776      * the current method handle.  The type of the adapter will be
 777      * the same as the type of the target, except that the final
 778      * {@code arrayLength} parameters of the target's type are replaced
 779      * by a single array parameter of type {@code arrayType}.
 780      * <p>
 781      * If the array element type differs from any of the corresponding
 782      * argument types on the original target,
 783      * the original target is adapted to take the array elements directly,
 784      * as if by a call to {@link #asType asType}.
 785      * <p>
 786      * When called, the adapter replaces a trailing array argument
 787      * by the array's elements, each as its own argument to the target.
 788      * (The order of the arguments is preserved.)
 789      * They are converted pairwise by casting and/or unboxing


 962      * }</pre></blockquote>
 963      * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
 964      * @param arrayLength the number of arguments to collect into a new array argument
 965      * @return a new method handle which collects some trailing argument
 966      *         into an array, before calling the original method handle
 967      * @throws NullPointerException if {@code arrayType} is a null reference
 968      * @throws IllegalArgumentException if {@code arrayType} is not an array type
 969      *         or {@code arrayType} is not assignable to this method handle's trailing parameter type,
 970      *         or {@code arrayLength} is not a legal array size,
 971      *         or the resulting method handle's type would have
 972      *         <a href="MethodHandle.html#maxarity">too many parameters</a>
 973      * @throws WrongMethodTypeException if the implied {@code asType} call fails
 974      * @see #asSpreader
 975      * @see #asVarargsCollector
 976      */
 977     public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
 978         asCollectorChecks(arrayType, arrayLength);
 979         int collectArgPos = type().parameterCount()-1;
 980         MethodHandle target = this;
 981         if (arrayType != type().parameterType(collectArgPos))
 982             target = MethodHandleImpl.makePairwiseConvert(this, type().changeParameterType(collectArgPos, arrayType), 1);
 983         MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength);
 984         return MethodHandles.collectArguments(target, collectArgPos, collector);
 985     }
 986 
 987     /**
 988      * See if {@code asCollector} can be validly called with the given arguments.
 989      * Return false if the last parameter is not an exact match to arrayType.
 990      */
 991     /*non-public*/ boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
 992         spreadArrayChecks(arrayType, arrayLength);
 993         int nargs = type().parameterCount();
 994         if (nargs != 0) {
 995             Class<?> lastParam = type().parameterType(nargs-1);
 996             if (lastParam == arrayType)  return true;
 997             if (lastParam.isAssignableFrom(arrayType))  return false;
 998         }
 999         throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
1000     }
1001 
1002     /**


1235      * When called, the bound handle inserts the given value {@code x}
1236      * as a new leading argument to the target.  The other arguments are
1237      * also passed unchanged.
1238      * What the target eventually returns is returned unchanged by the bound handle.
1239      * <p>
1240      * The reference {@code x} must be convertible to the first parameter
1241      * type of the target.
1242      * <p>
1243      * (<em>Note:</em>  Because method handles are immutable, the target method handle
1244      * retains its original type and behavior.)
1245      * @param x  the value to bind to the first argument of the target
1246      * @return a new method handle which prepends the given value to the incoming
1247      *         argument list, before calling the original method handle
1248      * @throws IllegalArgumentException if the target does not have a
1249      *         leading parameter type that is a reference type
1250      * @throws ClassCastException if {@code x} cannot be converted
1251      *         to the leading parameter type of the target
1252      * @see MethodHandles#insertArguments
1253      */
1254     public MethodHandle bindTo(Object x) {
1255         x = type.leadingReferenceParameter().cast(x);  // throw CCE if needed
1256         return bindArgumentL(0, x);






1257     }
1258 
1259     /**
1260      * Returns a string representation of the method handle,
1261      * starting with the string {@code "MethodHandle"} and
1262      * ending with the string representation of the method handle's type.
1263      * In other words, this method returns a string equal to the value of:
1264      * <blockquote><pre>{@code
1265      * "MethodHandle" + type().toString()
1266      * }</pre></blockquote>
1267      * <p>
1268      * (<em>Note:</em>  Future releases of this API may add further information
1269      * to the string representation.
1270      * Therefore, the present syntax should not be parsed by applications.)
1271      *
1272      * @return a string representation of the method handle
1273      */
1274     @Override
1275     public String toString() {
1276         if (DEBUG_METHOD_HANDLE_NAMES)  return "MethodHandle"+debugString();
1277         return standardString();
1278     }
1279     String standardString() {
1280         return "MethodHandle"+type;
1281     }
1282     /** Return a string with a several lines describing the method handle structure.
1283      *  This string would be suitable for display in an IDE debugger.
1284      */
1285     String debugString() {
1286         return type+" : "+internalForm()+internalProperties();
1287     }
1288 
1289     //// Implementation methods.
1290     //// Sub-classes can override these default implementations.
1291     //// All these methods assume arguments are already validated.
1292 
1293     // Other transforms to do:  convert, explicitCast, permute, drop, filter, fold, GWT, catch
1294 
1295     BoundMethodHandle bindArgumentL(int pos, Object value) {
1296         return rebind().bindArgumentL(pos, value);
1297     }
1298 
1299     /*non-public*/
1300     MethodHandle setVarargs(MemberName member) throws IllegalAccessException {
1301         if (!member.isVarargs())  return this;
1302         Class<?> arrayType = type().lastParameterType();
1303         if (arrayType.isArray()) {
1304             return MethodHandleImpl.makeVarargsCollector(this, arrayType);
1305         }
1306         throw member.makeAccessException("cannot make variable arity", null);
1307     }
1308 
1309     /*non-public*/
1310     MethodHandle viewAsType(MethodType newType) {
1311         // No actual conversions, just a new view of the same method.
1312         return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
1313     }
1314 
1315     // Decoding
1316 
1317     /*non-public*/
1318     LambdaForm internalForm() {


1347     /*non-public*/
1348     boolean isInvokeSpecial() {
1349         return false;  // DMH.Special returns true
1350     }
1351 
1352     /*non-public*/
1353     Object internalValues() {
1354         return null;
1355     }
1356 
1357     /*non-public*/
1358     Object internalProperties() {
1359         // Override to something to follow this.form, like "\n& FOO=bar"
1360         return "";
1361     }
1362 
1363     //// Method handle implementation methods.
1364     //// Sub-classes can override these default implementations.
1365     //// All these methods assume arguments are already validated.
1366 





























1367     /*non-public*/
1368     BoundMethodHandle rebind() {
1369         // Bind 'this' into a new invoker, of the known class BMH.
1370         MethodType type2 = type();
1371         LambdaForm form2 = reinvokerForm(this);
1372         // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }
1373         return BoundMethodHandle.bindSingle(type2, form2, this);
1374     }
1375 
1376     /*non-public*/
1377     MethodHandle reinvokerTarget() {
1378         throw new InternalError("not a reinvoker MH: "+this.getClass().getName()+": "+this);
1379     }
1380 
1381     /** Create a LF which simply reinvokes a target of the given basic type.
1382      *  The target MH must override {@link #reinvokerTarget} to provide the target.
1383      */
1384     static LambdaForm reinvokerForm(MethodHandle target) {
1385         MethodType mtype = target.type().basicType();
1386         LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE);
1387         if (reinvoker != null)  return reinvoker;
1388         if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY)


src/share/classes/java/lang/invoke/MethodHandle.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File