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

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

Print this page
rev 10271 : 8037209: Improvements and cleanups to bytecode assembly for lambda forms
Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
rev 10272 : 8038261: JSR292: cache and reuse typed array accessors
Reviewed-by: vlivanov, psandoz
Contributed-by: john.r.rose@oracle.com
rev 10273 : 8049555: Move varargsArray from sun.invoke.util package to java.lang.invoke
Reviewed-by: ?
rev 10274 : 8050052: Small cleanups in java.lang.invoke code
Reviewed-by: ?
rev 10276 : 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 10277 : 8050173: Add j.l.i.MethodHandle.copyWith(MethodType, LambdaForm)
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com
rev 10278 : imported patch isInvokeSpecial
rev 10279 : 8050057: Improve caching of MethodHandle reinvokers
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com


 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         }


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