334 }
335
336 private static ClassCastException newClassCastException(Class<?> t, Object obj) {
337 return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
338 }
339
340 static MethodHandle makeReferenceIdentity(Class<?> refType) {
341 MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
342 Name[] names = arguments(1, lambdaType);
343 names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
344 LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
345 return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
346 }
347
348 static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
349 MethodType type = target.type();
350 int last = type.parameterCount() - 1;
351 if (type.parameterType(last) != arrayType)
352 target = target.asType(type.changeParameterType(last, arrayType));
353 target = target.asFixedArity(); // make sure this attribute is turned off
354 return new AsVarargsCollector(target, target.type(), arrayType);
355 }
356
357 static class AsVarargsCollector extends MethodHandle {
358 private final MethodHandle target;
359 private final Class<?> arrayType;
360 private /*@Stable*/ MethodHandle asCollectorCache;
361
362 AsVarargsCollector(MethodHandle target, MethodType type, Class<?> arrayType) {
363 super(type, reinvokerForm(target));
364 this.target = target;
365 this.arrayType = arrayType;
366 this.asCollectorCache = target.asCollector(arrayType, 0);
367 }
368
369 @Override MethodHandle reinvokerTarget() { return target; }
370
371 @Override
372 public boolean isVarargsCollector() {
373 return true;
374 }
375
376 @Override
377 public MethodHandle asFixedArity() {
378 return target;
379 }
380
381 @Override
382 public MethodHandle asTypeUncached(MethodType newType) {
383 MethodType type = this.type();
384 int collectArg = type.parameterCount() - 1;
385 int newArity = newType.parameterCount();
386 if (newArity == collectArg+1 &&
387 type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
388 // if arity and trailing parameter are compatible, do normal thing
389 return asTypeCache = asFixedArity().asType(newType);
390 }
391 // check cache
392 MethodHandle acc = asCollectorCache;
393 if (acc != null && acc.type().parameterCount() == newArity)
394 return asTypeCache = acc.asType(newType);
395 // build and cache a collector
396 int arrayLength = newArity - collectArg;
399 collector = asFixedArity().asCollector(arrayType, arrayLength);
400 assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector;
401 } catch (IllegalArgumentException ex) {
402 throw new WrongMethodTypeException("cannot build collector", ex);
403 }
404 asCollectorCache = collector;
405 return asTypeCache = collector.asType(newType);
406 }
407
408 @Override
409 boolean viewAsTypeChecks(MethodType newType, boolean strict) {
410 super.viewAsTypeChecks(newType, true);
411 if (strict) return true;
412 // extra assertion for non-strict checks:
413 assert (type().lastParameterType().getComponentType()
414 .isAssignableFrom(
415 newType.lastParameterType().getComponentType()))
416 : Arrays.asList(this, newType);
417 return true;
418 }
419
420 @Override
421 MethodHandle setVarargs(MemberName member) {
422 if (member.isVarargs()) return this;
423 return asFixedArity();
424 }
425
426 @Override
427 MemberName internalMemberName() {
428 return asFixedArity().internalMemberName();
429 }
430 @Override
431 Class<?> internalCallerClass() {
432 return asFixedArity().internalCallerClass();
433 }
434
435 /*non-public*/
436 @Override
437 boolean isInvokeSpecial() {
438 return asFixedArity().isInvokeSpecial();
439 }
440
441 @Override
442 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
443 throw newIllegalArgumentException("do not use this");
444 }
445 }
446
447 /** Factory method: Spread selected argument. */
448 static MethodHandle makeSpreadArguments(MethodHandle target,
449 Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
450 MethodType targetType = target.type();
451
452 for (int i = 0; i < spreadArgCount; i++) {
453 Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
454 if (arg == null) arg = Object.class;
455 targetType = targetType.changeParameterType(spreadArgPos + i, arg);
456 }
457 target = target.asType(targetType);
458
459 MethodType srcType = targetType
460 .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
461 // Now build a LambdaForm.
462 MethodType lambdaType = srcType.invokerType();
463 Name[] names = arguments(spreadArgCount + 2, lambdaType);
464 int nameCursor = lambdaType.parameterCount();
955 } catch (java.io.IOException ex) {
956 throw new InternalError(ex);
957 }
958 return null;
959 }
960 });
961 T_BYTES = (byte[]) values[0];
962 }
963
964 // The following class is used as a template for Unsafe.defineAnonymousClass:
965 private static class T {
966 static void init() { } // side effect: initializes this class
967 static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
968 return vamh.invokeExact(args);
969 }
970 }
971 }
972
973
974 /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
975 static class WrappedMember extends MethodHandle {
976 private final MethodHandle target;
977 private final MemberName member;
978 private final Class<?> callerClass;
979 private final boolean isInvokeSpecial;
980
981 private WrappedMember(MethodHandle target, MethodType type,
982 MemberName member, boolean isInvokeSpecial,
983 Class<?> callerClass) {
984 super(type, reinvokerForm(target));
985 this.target = target;
986 this.member = member;
987 this.callerClass = callerClass;
988 this.isInvokeSpecial = isInvokeSpecial;
989 }
990
991 @Override
992 MethodHandle reinvokerTarget() {
993 return target;
994 }
995 @Override
996 public MethodHandle asTypeUncached(MethodType newType) {
997 // This MH is an alias for target, except for the MemberName
998 // Drop the MemberName if there is any conversion.
999 return asTypeCache = target.asType(newType);
1000 }
1001 @Override
1002 MemberName internalMemberName() {
1003 return member;
1004 }
1005 @Override
1006 Class<?> internalCallerClass() {
1007 return callerClass;
1008 }
1009 @Override
1010 boolean isInvokeSpecial() {
1011 return isInvokeSpecial;
1012 }
1013
1014 @Override
1015 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
1016 throw newIllegalArgumentException("do not use this");
1017 }
1018 }
1019
1020 static MethodHandle makeWrappedMember(MethodHandle target, MemberName member, boolean isInvokeSpecial) {
1021 if (member.equals(target.internalMemberName()) && isInvokeSpecial == target.isInvokeSpecial())
1022 return target;
1023 return new WrappedMember(target, target.type(), member, isInvokeSpecial, null);
1024 }
1025
1026 /// Collection of multiple arguments.
1027
1028 private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
1029 MethodType type = MethodType.genericMethodType(nargs)
1030 .changeReturnType(rtype)
1031 .insertParameterTypes(0, ptypes);
1032 try {
1033 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type);
1034 } catch (ReflectiveOperationException ex) {
1035 return null;
1036 }
|
334 }
335
336 private static ClassCastException newClassCastException(Class<?> t, Object obj) {
337 return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName());
338 }
339
340 static MethodHandle makeReferenceIdentity(Class<?> refType) {
341 MethodType lambdaType = MethodType.genericMethodType(1).invokerType();
342 Name[] names = arguments(1, lambdaType);
343 names[names.length - 1] = new Name(ValueConversions.identity(), names[1]);
344 LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names);
345 return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form);
346 }
347
348 static MethodHandle makeVarargsCollector(MethodHandle target, Class<?> arrayType) {
349 MethodType type = target.type();
350 int last = type.parameterCount() - 1;
351 if (type.parameterType(last) != arrayType)
352 target = target.asType(type.changeParameterType(last, arrayType));
353 target = target.asFixedArity(); // make sure this attribute is turned off
354 return new AsVarargsCollector(target, arrayType);
355 }
356
357 private static final class AsVarargsCollector extends DelegatingMethodHandle {
358 private final MethodHandle target;
359 private final Class<?> arrayType;
360 private /*@Stable*/ MethodHandle asCollectorCache;
361
362 AsVarargsCollector(MethodHandle target, Class<?> arrayType) {
363 this(target.type(), target, arrayType);
364 }
365 AsVarargsCollector(MethodType type, MethodHandle target, Class<?> arrayType) {
366 super(type, target);
367 this.target = target;
368 this.arrayType = arrayType;
369 this.asCollectorCache = target.asCollector(arrayType, 0);
370 }
371
372 @Override
373 public boolean isVarargsCollector() {
374 return true;
375 }
376
377 @Override
378 protected MethodHandle getTarget() {
379 return target;
380 }
381
382 @Override
383 public MethodHandle asFixedArity() {
384 return target;
385 }
386
387 @Override
388 public MethodHandle asTypeUncached(MethodType newType) {
389 MethodType type = this.type();
390 int collectArg = type.parameterCount() - 1;
391 int newArity = newType.parameterCount();
392 if (newArity == collectArg+1 &&
393 type.parameterType(collectArg).isAssignableFrom(newType.parameterType(collectArg))) {
394 // if arity and trailing parameter are compatible, do normal thing
395 return asTypeCache = asFixedArity().asType(newType);
396 }
397 // check cache
398 MethodHandle acc = asCollectorCache;
399 if (acc != null && acc.type().parameterCount() == newArity)
400 return asTypeCache = acc.asType(newType);
401 // build and cache a collector
402 int arrayLength = newArity - collectArg;
405 collector = asFixedArity().asCollector(arrayType, arrayLength);
406 assert(collector.type().parameterCount() == newArity) : "newArity="+newArity+" but collector="+collector;
407 } catch (IllegalArgumentException ex) {
408 throw new WrongMethodTypeException("cannot build collector", ex);
409 }
410 asCollectorCache = collector;
411 return asTypeCache = collector.asType(newType);
412 }
413
414 @Override
415 boolean viewAsTypeChecks(MethodType newType, boolean strict) {
416 super.viewAsTypeChecks(newType, true);
417 if (strict) return true;
418 // extra assertion for non-strict checks:
419 assert (type().lastParameterType().getComponentType()
420 .isAssignableFrom(
421 newType.lastParameterType().getComponentType()))
422 : Arrays.asList(this, newType);
423 return true;
424 }
425 }
426
427 /** Factory method: Spread selected argument. */
428 static MethodHandle makeSpreadArguments(MethodHandle target,
429 Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
430 MethodType targetType = target.type();
431
432 for (int i = 0; i < spreadArgCount; i++) {
433 Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
434 if (arg == null) arg = Object.class;
435 targetType = targetType.changeParameterType(spreadArgPos + i, arg);
436 }
437 target = target.asType(targetType);
438
439 MethodType srcType = targetType
440 .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
441 // Now build a LambdaForm.
442 MethodType lambdaType = srcType.invokerType();
443 Name[] names = arguments(spreadArgCount + 2, lambdaType);
444 int nameCursor = lambdaType.parameterCount();
935 } catch (java.io.IOException ex) {
936 throw new InternalError(ex);
937 }
938 return null;
939 }
940 });
941 T_BYTES = (byte[]) values[0];
942 }
943
944 // The following class is used as a template for Unsafe.defineAnonymousClass:
945 private static class T {
946 static void init() { } // side effect: initializes this class
947 static Object invoke_V(MethodHandle vamh, Object[] args) throws Throwable {
948 return vamh.invokeExact(args);
949 }
950 }
951 }
952
953
954 /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
955 private static final class WrappedMember extends DelegatingMethodHandle {
956 private final MethodHandle target;
957 private final MemberName member;
958 private final Class<?> callerClass;
959 private final boolean isInvokeSpecial;
960
961 private WrappedMember(MethodHandle target, MethodType type,
962 MemberName member, boolean isInvokeSpecial,
963 Class<?> callerClass) {
964 super(type, target);
965 this.target = target;
966 this.member = member;
967 this.callerClass = callerClass;
968 this.isInvokeSpecial = isInvokeSpecial;
969 }
970
971 @Override
972 MemberName internalMemberName() {
973 return member;
974 }
975 @Override
976 Class<?> internalCallerClass() {
977 return callerClass;
978 }
979 @Override
980 boolean isInvokeSpecial() {
981 return isInvokeSpecial;
982 }
983 @Override
984 protected MethodHandle getTarget() {
985 return target;
986 }
987 @Override
988 public MethodHandle asTypeUncached(MethodType newType) {
989 // This MH is an alias for target, except for the MemberName
990 // Drop the MemberName if there is any conversion.
991 return asTypeCache = target.asType(newType);
992 }
993 }
994
995 static MethodHandle makeWrappedMember(MethodHandle target, MemberName member, boolean isInvokeSpecial) {
996 if (member.equals(target.internalMemberName()) && isInvokeSpecial == target.isInvokeSpecial())
997 return target;
998 return new WrappedMember(target, target.type(), member, isInvokeSpecial, null);
999 }
1000
1001 /// Collection of multiple arguments.
1002
1003 private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
1004 MethodType type = MethodType.genericMethodType(nargs)
1005 .changeReturnType(rtype)
1006 .insertParameterTypes(0, ptypes);
1007 try {
1008 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type);
1009 } catch (ReflectiveOperationException ex) {
1010 return null;
1011 }
|