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; |