jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java
changeset 9752 88ab34b6da6d
parent 9731 d0f7a3e441c4
child 9780 6fc3b49cfee4
equal deleted inserted replaced
9731:d0f7a3e441c4 9752:88ab34b6da6d
    80             Class<?> recvType = method.getDeclaringClass();
    80             Class<?> recvType = method.getDeclaringClass();
    81             mtype = mtype.insertParameterTypes(0, recvType);
    81             mtype = mtype.insertParameterTypes(0, recvType);
    82         }
    82         }
    83         DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
    83         DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
    84         if (!mh.isValid())
    84         if (!mh.isValid())
    85             throw method.makeAccessException("no access", lookupClass);
    85             throw method.makeAccessException("no direct method handle", lookupClass);
    86         assert(mh.type() == mtype);
    86         assert(mh.type() == mtype);
    87         if (!method.isVarargs())
    87         if (!method.isVarargs())
    88             return mh;
    88             return mh;
    89         else
    89         int argc = mtype.parameterCount();
    90             return mh.asVarargsCollector(mtype.parameterType(mtype.parameterCount()-1));
    90         if (argc != 0) {
       
    91             Class<?> arrayType = mtype.parameterType(argc-1);
       
    92             if (arrayType.isArray())
       
    93                 return AdapterMethodHandle.makeVarargsCollector(mh, arrayType);
       
    94         }
       
    95         throw method.makeAccessException("cannot make variable arity", null);
    91     }
    96     }
    92 
    97 
    93     static
    98     static
    94     MethodHandle makeAllocator(MethodHandle rawConstructor) {
    99     MethodHandle makeAllocator(MethodHandle rawConstructor) {
    95         MethodType rawConType = rawConstructor.type();
   100         MethodType rawConType = rawConstructor.type();
   483      * @param receiver Receiver (or first static method argument) to pre-bind.
   488      * @param receiver Receiver (or first static method argument) to pre-bind.
   484      * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
   489      * @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
   485      */
   490      */
   486     static
   491     static
   487     MethodHandle bindReceiver(MethodHandle target, Object receiver) {
   492     MethodHandle bindReceiver(MethodHandle target, Object receiver) {
       
   493         if (receiver == null)  return null;
   488         if (target instanceof AdapterMethodHandle &&
   494         if (target instanceof AdapterMethodHandle &&
   489             ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
   495             ((AdapterMethodHandle)target).conversionOp() == MethodHandleNatives.Constants.OP_RETYPE_ONLY
   490             ) {
   496             ) {
   491             Object info = MethodHandleNatives.getTargetInfo(target);
   497             Object info = MethodHandleNatives.getTargetInfo(target);
   492             if (info instanceof DirectMethodHandle) {
   498             if (info instanceof DirectMethodHandle) {
   493                 DirectMethodHandle dmh = (DirectMethodHandle) info;
   499                 DirectMethodHandle dmh = (DirectMethodHandle) info;
   494                 if (receiver == null ||
   500                 if (dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
   495                     dmh.type().parameterType(0).isAssignableFrom(receiver.getClass())) {
       
   496                     MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
   501                     MethodHandle bmh = new BoundMethodHandle(dmh, receiver, 0);
   497                     MethodType newType = target.type().dropParameterTypes(0, 1);
   502                     MethodType newType = target.type().dropParameterTypes(0, 1);
   498                     return convertArguments(bmh, newType, bmh.type(), 0);
   503                     return convertArguments(bmh, newType, bmh.type(), 0);
   499                 }
   504                 }
   500             }
   505             }
   696             MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes);
   701             MethodType dropType = oldType.insertParameterTypes(dropArgPos, dropTypes);
   697             target = AdapterMethodHandle.makeDropArguments(dropType, target, dropArgPos, dropArgCount);
   702             target = AdapterMethodHandle.makeDropArguments(dropType, target, dropArgPos, dropArgCount);
   698             if (target == null)  throw newIllegalArgumentException("cannot drop");
   703             if (target == null)  throw newIllegalArgumentException("cannot drop");
   699             oldType = target.type();
   704             oldType = target.type();
   700         }
   705         }
   701         return convertArguments(target, newType, oldType, 0);
   706         target = convertArguments(target, newType, oldType, 0);
       
   707         assert(target != null);
       
   708         return target;
   702     }
   709     }
   703 
   710 
   704     /*non-public*/ static
   711     /*non-public*/ static
   705     MethodHandle convertArguments(MethodHandle target, MethodType newType, int level) {
   712     MethodHandle convertArguments(MethodHandle target, MethodType newType, int level) {
   706         MethodType oldType = target.type();
   713         MethodType oldType = target.type();
   905                               MethodHandle test, MethodHandle target, MethodHandle fallback) {
   912                               MethodHandle test, MethodHandle target, MethodHandle fallback) {
   906             super(invoker);
   913             super(invoker);
   907             this.test = test;
   914             this.test = test;
   908             this.target = target;
   915             this.target = target;
   909             this.fallback = fallback;
   916             this.fallback = fallback;
   910             assert(MethodHandleNatives.workaroundWithoutRicochetFrames());  // this code is deprecated
   917         }
   911         }
   918         static boolean preferRicochetFrame(MethodType type) {
   912         // FIXME: Build the control flow out of foldArguments.
   919             return (type.parameterCount() >= INVOKES.length || type.hasPrimitives());
       
   920         }
   913         static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
   921         static MethodHandle make(MethodHandle test, MethodHandle target, MethodHandle fallback) {
   914             assert(MethodHandleNatives.workaroundWithoutRicochetFrames());  // this code is deprecated
       
   915             MethodType type = target.type();
   922             MethodType type = target.type();
   916             int nargs = type.parameterCount();
   923             int nargs = type.parameterCount();
   917             if (nargs < INVOKES.length) {
   924             if (nargs < INVOKES.length) {
       
   925                 if (preferRicochetFrame(type))
       
   926                     assert(MethodHandleNatives.workaroundWithoutRicochetFrames());  // this code is deprecated
   918                 MethodHandle invoke = INVOKES[nargs];
   927                 MethodHandle invoke = INVOKES[nargs];
   919                 MethodType gtype = type.generic();
   928                 MethodType gtype = type.generic();
   920                 assert(invoke.type().dropParameterTypes(0,1) == gtype);
   929                 assert(invoke.type().dropParameterTypes(0,1) == gtype);
   921                 MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), 0);
   930                 MethodHandle gtest = convertArguments(test, gtype.changeReturnType(boolean.class), test.type(), 0);
   922                 MethodHandle gtarget = convertArguments(target, gtype, type, 0);
   931                 MethodHandle gtarget = convertArguments(target, gtype, type, 0);
   923                 MethodHandle gfallback = convertArguments(fallback, gtype, type, 0);
   932                 MethodHandle gfallback = convertArguments(fallback, gtype, type, 0);
   924                 if (gtest == null || gtarget == null || gfallback == null)  return null;
   933                 if (gtest == null || gtarget == null || gfallback == null)  return null;
   925                 MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
   934                 MethodHandle gguard = new GuardWithTest(invoke, gtest, gtarget, gfallback);
   926                 return convertArguments(gguard, type, gtype, 0);
   935                 return convertArguments(gguard, type, gtype, 0);
   927             } else {
   936             } else {
       
   937                 assert(MethodHandleNatives.workaroundWithoutRicochetFrames());  // this code is deprecated
   928                 MethodHandle invoke = VARARGS_INVOKE;
   938                 MethodHandle invoke = VARARGS_INVOKE;
   929                 MethodType gtype = MethodType.genericMethodType(1);
   939                 MethodType gtype = MethodType.genericMethodType(1);
   930                 assert(invoke.type().dropParameterTypes(0,1) == gtype);
   940                 assert(invoke.type().dropParameterTypes(0,1) == gtype);
   931                 MethodHandle gtest = spreadArgumentsFromPos(test, gtype.changeReturnType(boolean.class), 0);
   941                 MethodHandle gtest = spreadArgumentsFromPos(test, gtype.changeReturnType(boolean.class), 0);
   932                 MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
   942                 MethodHandle gtarget = spreadArgumentsFromPos(target, gtype, 0);
  1046         // [fold]=> continueAfterTest(z=test(arg...), arg...)
  1056         // [fold]=> continueAfterTest(z=test(arg...), arg...)
  1047         // [filter]=> (tf=select(z))(arg...)
  1057         // [filter]=> (tf=select(z))(arg...)
  1048         //    where select(z) = select(z, t, f).bindTo(t, f) => z ? t f
  1058         //    where select(z) = select(z, t, f).bindTo(t, f) => z ? t f
  1049         // [tailcall]=> tf(arg...)
  1059         // [tailcall]=> tf(arg...)
  1050         assert(test.type().returnType() == boolean.class);
  1060         assert(test.type().returnType() == boolean.class);
  1051         MethodType foldTargetType = target.type().insertParameterTypes(0, boolean.class);
  1061         MethodType targetType = target.type();
  1052         if (AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true)) {
  1062         MethodType foldTargetType = targetType.insertParameterTypes(0, boolean.class);
       
  1063         if (AdapterMethodHandle.canCollectArguments(foldTargetType, test.type(), 0, true)
       
  1064             && GuardWithTest.preferRicochetFrame(targetType)) {
  1053             // working backwards, as usual:
  1065             // working backwards, as usual:
  1054             assert(target.type().equals(fallback.type()));
  1066             assert(target.type().equals(fallback.type()));
  1055             MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
  1067             MethodHandle tailcall = MethodHandles.exactInvoker(target.type());
  1056             MethodHandle select = selectAlternative();
  1068             MethodHandle select = selectAlternative();
  1057             select = bindArgument(select, 2, fallback);
  1069             select = bindArgument(select, 2, fallback);
  1060             MethodHandle filter = filterArgument(tailcall, 0, select);
  1072             MethodHandle filter = filterArgument(tailcall, 0, select);
  1061             assert(filter.type().parameterType(0) == boolean.class);
  1073             assert(filter.type().parameterType(0) == boolean.class);
  1062             MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
  1074             MethodHandle fold = foldArguments(filter, filter.type().dropParameterTypes(0, 1), 0, test);
  1063             return fold;
  1075             return fold;
  1064         }
  1076         }
  1065         assert(MethodHandleNatives.workaroundWithoutRicochetFrames());  // this code is deprecated
       
  1066         return GuardWithTest.make(test, target, fallback);
  1077         return GuardWithTest.make(test, target, fallback);
  1067     }
  1078     }
  1068 
  1079 
  1069     private static class GuardWithCatch extends BoundMethodHandle {
  1080     private static class GuardWithCatch extends BoundMethodHandle {
  1070         private final MethodHandle target;
  1081         private final MethodHandle target;