src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File jdk Sdiff src/java.base/share/classes/java/lang/invoke

src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java

Print this page
rev 10589 : 8037209: Improvements and cleanups to bytecode assembly for lambda forms
Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
rev 10590 : 8038261: JSR292: cache and reuse typed array accessors
Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
rev 10591 : 8049555: Move varargsArray from sun.invoke.util package to java.lang.invoke
Reviewed-by: ?
rev 10592 : 8050052: Small cleanups in java.lang.invoke code
Reviewed-by: ?
rev 10594 : 8050166: Get rid of some package-private methods on arguments in j.l.i.MethodHandle
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com
rev 10595 : 8050173: Add j.l.i.MethodHandle.copyWith(MethodType, LambdaForm)
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com


  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         }


src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File