src/java.base/share/classes/java/lang/invoke/MethodType.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/MethodType.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 10592 : 8050052: Small cleanups in java.lang.invoke code
Reviewed-by: ?
rev 10593 : 8050053: Improve caching of different invokers
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com
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
rev 10601 : imported patch 12.8050884.identity
rev 10604 : 8057656: Improve MethodType.isCastableTo() & MethodType.isConvertibleTo() checks
Reviewed-by: vlivanov, ?
Contributed-by: john.r.rose@oracle.com
rev 10605 : [mq]: 15.8057656.mt_cast.1


 808             return false;
 809         return parametersAreViewableAs(newType, keepInterfaces);
 810     }
 811     /** True if the new parameters can be viewed (w/o casting) under the old parameter types. */
 812     /*non-public*/
 813     boolean parametersAreViewableAs(MethodType newType, boolean keepInterfaces) {
 814         if (form == newType.form && form.erasedType == this)
 815             return true;  // my reference parameters are all Object
 816         if (ptypes == newType.ptypes)
 817             return true;
 818         int argc = parameterCount();
 819         if (argc != newType.parameterCount())
 820             return false;
 821         for (int i = 0; i < argc; i++) {
 822             if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i), keepInterfaces))
 823                 return false;
 824         }
 825         return true;
 826     }
 827     /*non-public*/
 828     boolean isCastableTo(MethodType newType) {
 829         int argc = parameterCount();
 830         if (argc != newType.parameterCount())




 831             return false;



 832         return true;
















 833     }




 834     /*non-public*/
 835     boolean isConvertibleTo(MethodType newType) {
 836         if (!canConvert(returnType(), newType.returnType()))

 837             return false;
 838         int argc = parameterCount();
 839         if (argc != newType.parameterCount())





 840             return false;
 841         for (int i = 0; i < argc; i++) {
 842             if (!canConvert(newType.parameterType(i), parameterType(i)))

 843                 return false;
 844         }















































 845         return true;
 846     }

 847     /*non-public*/
 848     static boolean canConvert(Class<?> src, Class<?> dst) {
 849         // short-circuit a few cases:
 850         if (src == dst || dst == Object.class)  return true;
 851         // the remainder of this logic is documented in MethodHandle.asType
 852         if (src.isPrimitive()) {
 853             // can force void to an explicit null, a la reflect.Method.invoke
 854             // can also force void to a primitive zero, by analogy
 855             if (src == void.class)  return true;  //or !dst.isPrimitive()?
 856             Wrapper sw = Wrapper.forPrimitiveType(src);
 857             if (dst.isPrimitive()) {
 858                 // P->P must widen
 859                 return Wrapper.forPrimitiveType(dst).isConvertibleFrom(sw);
 860             } else {
 861                 // P->R must box and widen
 862                 return dst.isAssignableFrom(sw.wrapperType());
 863             }
 864         } else if (dst.isPrimitive()) {
 865             // any value can be dropped
 866             if (dst == void.class)  return true;
 867             Wrapper dw = Wrapper.forPrimitiveType(dst);
 868             // R->P must be able to unbox (from a dynamically chosen type) and widen
 869             // For example:
 870             //   Byte/Number/Comparable/Object -> dw:Byte -> byte.




 808             return false;
 809         return parametersAreViewableAs(newType, keepInterfaces);
 810     }
 811     /** True if the new parameters can be viewed (w/o casting) under the old parameter types. */
 812     /*non-public*/
 813     boolean parametersAreViewableAs(MethodType newType, boolean keepInterfaces) {
 814         if (form == newType.form && form.erasedType == this)
 815             return true;  // my reference parameters are all Object
 816         if (ptypes == newType.ptypes)
 817             return true;
 818         int argc = parameterCount();
 819         if (argc != newType.parameterCount())
 820             return false;
 821         for (int i = 0; i < argc; i++) {
 822             if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i), keepInterfaces))
 823                 return false;
 824         }
 825         return true;
 826     }
 827     /*non-public*/
 828     boolean isConvertibleTo(MethodType newType) {
 829         MethodTypeForm oldForm = this.form();
 830         MethodTypeForm newForm = newType.form();
 831         if (oldForm == newForm)
 832             // same parameter count, same primitive/object mix
 833             return true;
 834         if (!canConvert(returnType(), newType.returnType()))
 835             return false;
 836         Class<?>[] srcTypes = newType.ptypes;
 837         Class<?>[] dstTypes = ptypes;
 838         if (srcTypes == dstTypes)
 839             return true;
 840         int argc;
 841         if ((argc = srcTypes.length) != dstTypes.length)
 842             return false;
 843         if (argc <= 1) {
 844             if (argc == 1 && !canConvert(srcTypes[0], dstTypes[0]))
 845                 return false;
 846             return true;
 847         }
 848         if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) ||
 849             (newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) {
 850             // Somewhat complicated test to avoid a loop of 2 or more trips.
 851             // If either type has only Object parameters, we know we can convert.
 852             assert(canConvertParameters(srcTypes, dstTypes));
 853             return true;
 854         }
 855         return canConvertParameters(srcTypes, dstTypes);
 856     }
 857 
 858     /** Returns true if MHs.explicitCastArguments produces the same result as MH.asType.
 859      *  If the type conversion is impossible for either, the result should be false.
 860      */
 861     /*non-public*/
 862     boolean explicitCastEquivalentToAsType(MethodType newType) {
 863         if (this == newType)  return true;
 864         if (!explicitCastEquivalentToAsType(rtype, newType.rtype)) {
 865             return false;
 866         }
 867         Class<?>[] srcTypes = newType.ptypes;
 868         Class<?>[] dstTypes = ptypes;
 869         if (dstTypes == srcTypes) {
 870             return true;
 871         }
 872         if (dstTypes.length != srcTypes.length) {
 873             return false;
 874         }
 875         for (int i = 0; i < dstTypes.length; i++) {
 876             if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) {
 877                 return false;
 878             }
 879         }
 880         return true;
 881     }
 882 
 883     /** Reports true if the src can be converted to the dst, by both asType and MHs.eCE,
 884      *  and with the same effect.
 885      *  MHs.eCA has the following "upgrades" to MH.asType:
 886      *  1. interfaces are unchecked (that is, treated as if aliased to Object)
 887      *     Therefore, {@code Object->CharSequence} is possible in both cases but has different semantics
 888      *  2. the full matrix of primitive-to-primitive conversions is supported
 889      *     Narrowing like {@code long->byte} and basic-typing like {@code boolean->int}
 890      *     are not supported by asType, but anything supported by asType is equivalent
 891      *     with MHs.eCE.
 892      *  3a. unboxing conversions can be followed by the full matrix of primitive conversions
 893      *  3b. unboxing of null is permitted (creates a zero primitive value)
 894      *     Most unboxing conversions, like {@code Object->int}, has potentially
 895      *     different behaviors for asType vs. MHs.eCE, because the dynamic value
 896      *     might be a wrapper of a type that requires narrowing, like {@code (Object)1L->byte}.
 897      *     The equivalence is only certain if the static src type is a wrapper,
 898      *     and the conversion will be a widening one.
 899      * Other than interfaces, reference-to-reference conversions are the same.
 900      * Boxing primitives to references is the same for both operators.
 901      */
 902     private static boolean explicitCastEquivalentToAsType(Class<?> src, Class<?> dst) {
 903         if (src == dst || dst == Object.class || dst == void.class)  return true;
 904         if (src.isPrimitive()) {
 905             // Could be a prim/prim conversion, where casting is a strict superset.
 906             // Or a boxing conversion, which is always to an exact wrapper class.
 907             return canConvert(src, dst);
 908         } else if (dst.isPrimitive()) {
 909             Wrapper dw = Wrapper.forPrimitiveType(dst);
 910             // Watch out:  If src is Number or Object, we could get dynamic narrowing conversion.
 911             // The conversion is known to be widening only if the wrapper type is statically visible.
 912             return (Wrapper.isWrapperType(src) &&
 913                     dw.isConvertibleFrom(Wrapper.forWrapperType(src)));
 914         } else {
 915             // R->R always works, but we have to avoid a check-cast to an interface.
 916             return !dst.isInterface() || dst.isAssignableFrom(src);
 917         }
 918     }
 919 
 920     private boolean canConvertParameters(Class<?>[] srcTypes, Class<?>[] dstTypes) {
 921         for (int i = 0; i < srcTypes.length; i++) {
 922             if (!canConvert(srcTypes[i], dstTypes[i])) {
 923                 return false;
 924             }
 925         }
 926         return true;
 927     }
 928 
 929     /*non-public*/
 930     static boolean canConvert(Class<?> src, Class<?> dst) {
 931         // short-circuit a few cases:
 932         if (src == dst || src == Object.class || dst == Object.class)  return true;
 933         // the remainder of this logic is documented in MethodHandle.asType
 934         if (src.isPrimitive()) {
 935             // can force void to an explicit null, a la reflect.Method.invoke
 936             // can also force void to a primitive zero, by analogy
 937             if (src == void.class)  return true;  //or !dst.isPrimitive()?
 938             Wrapper sw = Wrapper.forPrimitiveType(src);
 939             if (dst.isPrimitive()) {
 940                 // P->P must widen
 941                 return Wrapper.forPrimitiveType(dst).isConvertibleFrom(sw);
 942             } else {
 943                 // P->R must box and widen
 944                 return dst.isAssignableFrom(sw.wrapperType());
 945             }
 946         } else if (dst.isPrimitive()) {
 947             // any value can be dropped
 948             if (dst == void.class)  return true;
 949             Wrapper dw = Wrapper.forPrimitiveType(dst);
 950             // R->P must be able to unbox (from a dynamically chosen type) and widen
 951             // For example:
 952             //   Byte/Number/Comparable/Object -> dw:Byte -> byte.


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