67 // Trigger selected static initializations.
68 MemberName.Factory.INSTANCE.getClass();
69 }
70
71 static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
72 if (arrayClass == Object[].class)
73 return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
74 if (!arrayClass.isArray())
75 throw newIllegalArgumentException("not an array: "+arrayClass);
76 MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
77 int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX);
78 MethodHandle mh = cache[cacheIndex];
79 if (mh != null) return mh;
80 mh = ArrayAccessor.getAccessor(arrayClass, isSetter);
81 MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter);
82 if (mh.type() != correctType) {
83 assert(mh.type().parameterType(0) == Object[].class);
84 assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class);
85 assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType());
86 // safe to view non-strictly, because element type follows from array type
87 mh = mh.viewAsType(correctType);
88 }
89 // Atomically update accessor cache.
90 synchronized(cache) {
91 if (cache[cacheIndex] == null) {
92 cache[cacheIndex] = mh;
93 } else {
94 // Throw away newly constructed accessor and use cached version.
95 mh = cache[cacheIndex];
96 }
97 }
98 return mh;
99 }
100
101 static final class ArrayAccessor {
102 /// Support for array element access
103 static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2;
104 static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
105 = new ClassValue<MethodHandle[]>() {
106 @Override
107 protected MethodHandle[] computeValue(Class<?> type) {
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;
397 MethodHandle collector;
398 try {
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 MethodHandle setVarargs(MemberName member) {
410 if (member.isVarargs()) return this;
411 return asFixedArity();
412 }
413
414 @Override
415 MethodHandle viewAsType(MethodType newType) {
416 if (newType.lastParameterType() != type().lastParameterType())
417 throw new InternalError();
418 MethodHandle newTarget = asFixedArity().viewAsType(newType);
419 // put back the varargs bit:
420 return new AsVarargsCollector(newTarget, newType, arrayType);
421 }
422
423 @Override
424 MemberName internalMemberName() {
425 return asFixedArity().internalMemberName();
426 }
427 @Override
428 Class<?> internalCallerClass() {
429 return asFixedArity().internalCallerClass();
430 }
431
432 /*non-public*/
433 @Override
434 boolean isInvokeSpecial() {
435 return asFixedArity().isInvokeSpecial();
436 }
437 }
438
439 /** Factory method: Spread selected argument. */
440 static MethodHandle makeSpreadArguments(MethodHandle target,
441 Class<?> spreadArgType, int spreadArgPos, int spreadArgCount) {
442 MethodType targetType = target.type();
443
444 for (int i = 0; i < spreadArgCount; i++) {
445 Class<?> arg = VerifyType.spreadArgElementType(spreadArgType, i);
446 if (arg == null) arg = Object.class;
447 targetType = targetType.changeParameterType(spreadArgPos + i, arg);
448 }
449 target = target.asType(targetType);
450
451 MethodType srcType = targetType
452 .replaceParameterTypes(spreadArgPos, spreadArgPos + spreadArgCount, spreadArgType);
453 // Now build a LambdaForm.
454 MethodType lambdaType = srcType.invokerType();
455 Name[] names = arguments(spreadArgCount + 2, lambdaType);
456 int nameCursor = lambdaType.parameterCount();
979 return target;
980 }
981 @Override
982 public MethodHandle asTypeUncached(MethodType newType) {
983 // This MH is an alias for target, except for the MemberName
984 // Drop the MemberName if there is any conversion.
985 return asTypeCache = target.asType(newType);
986 }
987 @Override
988 MemberName internalMemberName() {
989 return member;
990 }
991 @Override
992 Class<?> internalCallerClass() {
993 return callerClass;
994 }
995 @Override
996 boolean isInvokeSpecial() {
997 return target.isInvokeSpecial();
998 }
999 @Override
1000 MethodHandle viewAsType(MethodType newType) {
1001 return new WrappedMember(target, newType, member, callerClass);
1002 }
1003 }
1004
1005 static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
1006 if (member.equals(target.internalMemberName()))
1007 return target;
1008 return new WrappedMember(target, target.type(), member, null);
1009 }
1010
1011 /// Collection of multiple arguments.
1012
1013 private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
1014 MethodType type = MethodType.genericMethodType(nargs)
1015 .changeReturnType(rtype)
1016 .insertParameterTypes(0, ptypes);
1017 try {
1018 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type);
1019 } catch (ReflectiveOperationException ex) {
1020 return null;
1021 }
|
67 // Trigger selected static initializations.
68 MemberName.Factory.INSTANCE.getClass();
69 }
70
71 static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
72 if (arrayClass == Object[].class)
73 return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
74 if (!arrayClass.isArray())
75 throw newIllegalArgumentException("not an array: "+arrayClass);
76 MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass);
77 int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX);
78 MethodHandle mh = cache[cacheIndex];
79 if (mh != null) return mh;
80 mh = ArrayAccessor.getAccessor(arrayClass, isSetter);
81 MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter);
82 if (mh.type() != correctType) {
83 assert(mh.type().parameterType(0) == Object[].class);
84 assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class);
85 assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType());
86 // safe to view non-strictly, because element type follows from array type
87 mh = mh.viewAsType(correctType, false);
88 }
89 // Atomically update accessor cache.
90 synchronized(cache) {
91 if (cache[cacheIndex] == null) {
92 cache[cacheIndex] = mh;
93 } else {
94 // Throw away newly constructed accessor and use cached version.
95 mh = cache[cacheIndex];
96 }
97 }
98 return mh;
99 }
100
101 static final class ArrayAccessor {
102 /// Support for array element access
103 static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2;
104 static final ClassValue<MethodHandle[]> TYPED_ACCESSORS
105 = new ClassValue<MethodHandle[]>() {
106 @Override
107 protected MethodHandle[] computeValue(Class<?> type) {
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;
397 MethodHandle collector;
398 try {
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();
987 return target;
988 }
989 @Override
990 public MethodHandle asTypeUncached(MethodType newType) {
991 // This MH is an alias for target, except for the MemberName
992 // Drop the MemberName if there is any conversion.
993 return asTypeCache = target.asType(newType);
994 }
995 @Override
996 MemberName internalMemberName() {
997 return member;
998 }
999 @Override
1000 Class<?> internalCallerClass() {
1001 return callerClass;
1002 }
1003 @Override
1004 boolean isInvokeSpecial() {
1005 return target.isInvokeSpecial();
1006 }
1007
1008 @Override
1009 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
1010 throw newIllegalArgumentException("do not use this");
1011 }
1012 }
1013
1014 static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
1015 if (member.equals(target.internalMemberName()))
1016 return target;
1017 return new WrappedMember(target, target.type(), member, null);
1018 }
1019
1020 /// Collection of multiple arguments.
1021
1022 private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) {
1023 MethodType type = MethodType.genericMethodType(nargs)
1024 .changeReturnType(rtype)
1025 .insertParameterTypes(0, ptypes);
1026 try {
1027 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type);
1028 } catch (ReflectiveOperationException ex) {
1029 return null;
1030 }
|