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: ?


 974      * @throws NullPointerException if {@code arrayType} is a null reference
 975      * @throws IllegalArgumentException if {@code arrayType} is not an array type
 976      *         or {@code arrayType} is not assignable to this method handle's trailing parameter type,
 977      *         or {@code arrayLength} is not a legal array size,
 978      *         or the resulting method handle's type would have
 979      *         <a href="MethodHandle.html#maxarity">too many parameters</a>
 980      * @throws WrongMethodTypeException if the implied {@code asType} call fails
 981      * @see #asSpreader
 982      * @see #asVarargsCollector
 983      */
 984     public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
 985         asCollectorChecks(arrayType, arrayLength);
 986         int collectArgPos = type().parameterCount()-1;
 987         MethodHandle target = this;
 988         if (arrayType != type().parameterType(collectArgPos))
 989             target = convertArguments(type().changeParameterType(collectArgPos, arrayType));
 990         MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength);
 991         return MethodHandles.collectArguments(target, collectArgPos, collector);
 992     }
 993 
 994     // private API: return true if last param exactly matches arrayType
 995     private boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {



 996         spreadArrayChecks(arrayType, arrayLength);
 997         int nargs = type().parameterCount();
 998         if (nargs != 0) {
 999             Class<?> lastParam = type().parameterType(nargs-1);
1000             if (lastParam == arrayType)  return true;
1001             if (lastParam.isAssignableFrom(arrayType))  return false;
1002         }
1003         throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
1004     }
1005 
1006     /**
1007      * Makes a <em>variable arity</em> adapter which is able to accept
1008      * any number of trailing positional arguments and collect them
1009      * into an array argument.
1010      * <p>
1011      * The type and behavior of the adapter will be the same as
1012      * the type and behavior of the target, except that certain
1013      * {@code invoke} and {@code asType} requests can lead to
1014      * trailing positional arguments being collected into target's
1015      * trailing parameter.


1137      * pre-collected arrays of any length.  Users should be aware of the
1138      * special role of the final argument, and of the effect of a
1139      * type match on that final argument, which determines whether
1140      * or not a single trailing argument is interpreted as a whole
1141      * array or a single element of an array to be collected.
1142      * Note that the dynamic type of the trailing argument has no
1143      * effect on this decision, only a comparison between the symbolic
1144      * type descriptor of the call site and the type descriptor of the method handle.)
1145      *
1146      * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
1147      * @return a new method handle which can collect any number of trailing arguments
1148      *         into an array, before calling the original method handle
1149      * @throws NullPointerException if {@code arrayType} is a null reference
1150      * @throws IllegalArgumentException if {@code arrayType} is not an array type
1151      *         or {@code arrayType} is not assignable to this method handle's trailing parameter type
1152      * @see #asCollector
1153      * @see #isVarargsCollector
1154      * @see #asFixedArity
1155      */
1156     public MethodHandle asVarargsCollector(Class<?> arrayType) {
1157         Class<?> arrayElement = arrayType.getComponentType();
1158         boolean lastMatch = asCollectorChecks(arrayType, 0);
1159         if (isVarargsCollector() && lastMatch)
1160             return this;
1161         return MethodHandleImpl.makeVarargsCollector(this, arrayType);
1162     }
1163 
1164     /**
1165      * Determines if this method handle
1166      * supports {@linkplain #asVarargsCollector variable arity} calls.
1167      * Such method handles arise from the following sources:
1168      * <ul>
1169      * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
1170      * <li>a call to a {@linkplain java.lang.invoke.MethodHandles.Lookup lookup method}
1171      *     which resolves to a variable arity Java method or constructor
1172      * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
1173      *     which resolves to a variable arity Java method or constructor
1174      * </ul>
1175      * @return true if this method handle accepts more than one arity of plain, inexact {@code invoke} calls
1176      * @see #asVarargsCollector
1177      * @see #asFixedArity


1294     }
1295 
1296     //// Implementation methods.
1297     //// Sub-classes can override these default implementations.
1298     //// All these methods assume arguments are already validated.
1299 
1300     // Other transforms to do:  convert, explicitCast, permute, drop, filter, fold, GWT, catch
1301 
1302     /*non-public*/
1303     MethodHandle setVarargs(MemberName member) throws IllegalAccessException {
1304         if (!member.isVarargs())  return this;
1305         int argc = type().parameterCount();
1306         if (argc != 0) {
1307             Class<?> arrayType = type().parameterType(argc-1);
1308             if (arrayType.isArray()) {
1309                 return MethodHandleImpl.makeVarargsCollector(this, arrayType);
1310             }
1311         }
1312         throw member.makeAccessException("cannot make variable arity", null);
1313     }

1314     /*non-public*/
1315     MethodHandle viewAsType(MethodType newType) {
1316         // No actual conversions, just a new view of the same method.
1317         return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
1318     }
1319 
1320     // Decoding
1321 
1322     /*non-public*/
1323     LambdaForm internalForm() {
1324         return form;
1325     }
1326 
1327     /*non-public*/
1328     MemberName internalMemberName() {
1329         return null;  // DMH returns DMH.member
1330     }
1331 
1332     /*non-public*/
1333     Class<?> internalCallerClass() {


1452     private static final LambdaForm.NamedFunction NF_reinvokerTarget;
1453     static {
1454         try {
1455             NF_reinvokerTarget = new LambdaForm.NamedFunction(MethodHandle.class
1456                 .getDeclaredMethod("reinvokerTarget"));
1457         } catch (ReflectiveOperationException ex) {
1458             throw newInternalError(ex);
1459         }
1460     }
1461 
1462     /**
1463      * Replace the old lambda form of this method handle with a new one.
1464      * The new one must be functionally equivalent to the old one.
1465      * Threads may continue running the old form indefinitely,
1466      * but it is likely that the new one will be preferred for new executions.
1467      * Use with discretion.
1468      */
1469     /*non-public*/
1470     void updateForm(LambdaForm newForm) {
1471         if (form == newForm)  return;

1472         // ISSUE: Should we have a memory fence here?
1473         UNSAFE.putObject(this, FORM_OFFSET, newForm);
1474         this.form.prepare();  // as in MethodHandle.<init>
1475     }
1476 
1477     private static final long FORM_OFFSET;
1478     static {
1479         try {
1480             FORM_OFFSET = UNSAFE.objectFieldOffset(MethodHandle.class.getDeclaredField("form"));
1481         } catch (ReflectiveOperationException ex) {
1482             throw newInternalError(ex);
1483         }
1484     }
1485 }


 974      * @throws NullPointerException if {@code arrayType} is a null reference
 975      * @throws IllegalArgumentException if {@code arrayType} is not an array type
 976      *         or {@code arrayType} is not assignable to this method handle's trailing parameter type,
 977      *         or {@code arrayLength} is not a legal array size,
 978      *         or the resulting method handle's type would have
 979      *         <a href="MethodHandle.html#maxarity">too many parameters</a>
 980      * @throws WrongMethodTypeException if the implied {@code asType} call fails
 981      * @see #asSpreader
 982      * @see #asVarargsCollector
 983      */
 984     public MethodHandle asCollector(Class<?> arrayType, int arrayLength) {
 985         asCollectorChecks(arrayType, arrayLength);
 986         int collectArgPos = type().parameterCount()-1;
 987         MethodHandle target = this;
 988         if (arrayType != type().parameterType(collectArgPos))
 989             target = convertArguments(type().changeParameterType(collectArgPos, arrayType));
 990         MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength);
 991         return MethodHandles.collectArguments(target, collectArgPos, collector);
 992     }
 993 
 994     /**
 995      * See if {@code asCollector} can be validly called with the given arguments.
 996      * Return false if the last parameter is not an exact match to arrayType.
 997      */
 998     /*non-public*/ boolean asCollectorChecks(Class<?> arrayType, int arrayLength) {
 999         spreadArrayChecks(arrayType, arrayLength);
1000         int nargs = type().parameterCount();
1001         if (nargs != 0) {
1002             Class<?> lastParam = type().parameterType(nargs-1);
1003             if (lastParam == arrayType)  return true;
1004             if (lastParam.isAssignableFrom(arrayType))  return false;
1005         }
1006         throw newIllegalArgumentException("array type not assignable to trailing argument", this, arrayType);
1007     }
1008 
1009     /**
1010      * Makes a <em>variable arity</em> adapter which is able to accept
1011      * any number of trailing positional arguments and collect them
1012      * into an array argument.
1013      * <p>
1014      * The type and behavior of the adapter will be the same as
1015      * the type and behavior of the target, except that certain
1016      * {@code invoke} and {@code asType} requests can lead to
1017      * trailing positional arguments being collected into target's
1018      * trailing parameter.


1140      * pre-collected arrays of any length.  Users should be aware of the
1141      * special role of the final argument, and of the effect of a
1142      * type match on that final argument, which determines whether
1143      * or not a single trailing argument is interpreted as a whole
1144      * array or a single element of an array to be collected.
1145      * Note that the dynamic type of the trailing argument has no
1146      * effect on this decision, only a comparison between the symbolic
1147      * type descriptor of the call site and the type descriptor of the method handle.)
1148      *
1149      * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
1150      * @return a new method handle which can collect any number of trailing arguments
1151      *         into an array, before calling the original method handle
1152      * @throws NullPointerException if {@code arrayType} is a null reference
1153      * @throws IllegalArgumentException if {@code arrayType} is not an array type
1154      *         or {@code arrayType} is not assignable to this method handle's trailing parameter type
1155      * @see #asCollector
1156      * @see #isVarargsCollector
1157      * @see #asFixedArity
1158      */
1159     public MethodHandle asVarargsCollector(Class<?> arrayType) {
1160         arrayType.getClass(); // explicit NPE
1161         boolean lastMatch = asCollectorChecks(arrayType, 0);
1162         if (isVarargsCollector() && lastMatch)
1163             return this;
1164         return MethodHandleImpl.makeVarargsCollector(this, arrayType);
1165     }
1166 
1167     /**
1168      * Determines if this method handle
1169      * supports {@linkplain #asVarargsCollector variable arity} calls.
1170      * Such method handles arise from the following sources:
1171      * <ul>
1172      * <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
1173      * <li>a call to a {@linkplain java.lang.invoke.MethodHandles.Lookup lookup method}
1174      *     which resolves to a variable arity Java method or constructor
1175      * <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
1176      *     which resolves to a variable arity Java method or constructor
1177      * </ul>
1178      * @return true if this method handle accepts more than one arity of plain, inexact {@code invoke} calls
1179      * @see #asVarargsCollector
1180      * @see #asFixedArity


1297     }
1298 
1299     //// Implementation methods.
1300     //// Sub-classes can override these default implementations.
1301     //// All these methods assume arguments are already validated.
1302 
1303     // Other transforms to do:  convert, explicitCast, permute, drop, filter, fold, GWT, catch
1304 
1305     /*non-public*/
1306     MethodHandle setVarargs(MemberName member) throws IllegalAccessException {
1307         if (!member.isVarargs())  return this;
1308         int argc = type().parameterCount();
1309         if (argc != 0) {
1310             Class<?> arrayType = type().parameterType(argc-1);
1311             if (arrayType.isArray()) {
1312                 return MethodHandleImpl.makeVarargsCollector(this, arrayType);
1313             }
1314         }
1315         throw member.makeAccessException("cannot make variable arity", null);
1316     }
1317 
1318     /*non-public*/
1319     MethodHandle viewAsType(MethodType newType) {
1320         // No actual conversions, just a new view of the same method.
1321         return MethodHandleImpl.makePairwiseConvert(this, newType, 0);
1322     }
1323 
1324     // Decoding
1325 
1326     /*non-public*/
1327     LambdaForm internalForm() {
1328         return form;
1329     }
1330 
1331     /*non-public*/
1332     MemberName internalMemberName() {
1333         return null;  // DMH returns DMH.member
1334     }
1335 
1336     /*non-public*/
1337     Class<?> internalCallerClass() {


1456     private static final LambdaForm.NamedFunction NF_reinvokerTarget;
1457     static {
1458         try {
1459             NF_reinvokerTarget = new LambdaForm.NamedFunction(MethodHandle.class
1460                 .getDeclaredMethod("reinvokerTarget"));
1461         } catch (ReflectiveOperationException ex) {
1462             throw newInternalError(ex);
1463         }
1464     }
1465 
1466     /**
1467      * Replace the old lambda form of this method handle with a new one.
1468      * The new one must be functionally equivalent to the old one.
1469      * Threads may continue running the old form indefinitely,
1470      * but it is likely that the new one will be preferred for new executions.
1471      * Use with discretion.
1472      */
1473     /*non-public*/
1474     void updateForm(LambdaForm newForm) {
1475         if (form == newForm)  return;
1476         assert(this instanceof DirectMethodHandle && this.internalMemberName().isStatic());
1477         // ISSUE: Should we have a memory fence here?
1478         UNSAFE.putObject(this, FORM_OFFSET, newForm);
1479         this.form.prepare();  // as in MethodHandle.<init>
1480     }
1481 
1482     private static final long FORM_OFFSET;
1483     static {
1484         try {
1485             FORM_OFFSET = UNSAFE.objectFieldOffset(MethodHandle.class.getDeclaredField("form"));
1486         } catch (ReflectiveOperationException ex) {
1487             throw newInternalError(ex);
1488         }
1489     }
1490 }
src/share/classes/java/lang/invoke/MethodHandle.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File