1.1 --- a/src/jdk/internal/dynalink/support/TypeConverterFactory.java Thu Nov 06 17:06:56 2014 +0100 1.2 +++ b/src/jdk/internal/dynalink/support/TypeConverterFactory.java Mon Nov 03 09:49:52 2014 +0100 1.3 @@ -97,6 +97,7 @@ 1.4 import jdk.internal.dynalink.linker.GuardedTypeConversion; 1.5 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; 1.6 import jdk.internal.dynalink.linker.LinkerServices; 1.7 +import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; 1.8 1.9 /** 1.10 * A factory for type converters. This class is the main implementation behind the 1.11 @@ -109,6 +110,7 @@ 1.12 1.13 private final GuardingTypeConverterFactory[] factories; 1.14 private final ConversionComparator[] comparators; 1.15 + private final MethodTypeConversionStrategy autoConversionStrategy; 1.16 1.17 private final ClassValue<ClassMap<MethodHandle>> converterMap = new ClassValue<ClassMap<MethodHandle>>() { 1.18 @Override 1.19 @@ -177,8 +179,24 @@ 1.20 * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances. 1.21 * 1.22 * @param factories the {@link GuardingTypeConverterFactory} instances to compose. 1.23 + * @param autoConversionStrategy conversion strategy for automatic type conversions. After 1.24 + * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom 1.25 + * conversions to a method handle, it still needs to effect 1.26 + * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that 1.27 + * can usually be automatically applied as per 1.28 + * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. 1.29 + * However, sometimes language runtimes will want to customize even those conversions for their own call 1.30 + * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by 1.31 + * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom 1.32 + * automatic conversion strategy, that can deal with null values. Note that when the strategy's 1.33 + * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} 1.34 + * is invoked, the custom language conversions will already have been applied to the method handle, so by 1.35 + * design the difference between the handle's current method type and the desired final type will always 1.36 + * only be ones that can be subjected to method invocation conversions. Can be null, in which case no 1.37 + * custom strategy is employed. 1.38 */ 1.39 - public TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories) { 1.40 + public TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories, 1.41 + final MethodTypeConversionStrategy autoConversionStrategy) { 1.42 final List<GuardingTypeConverterFactory> l = new LinkedList<>(); 1.43 final List<ConversionComparator> c = new LinkedList<>(); 1.44 for(final GuardingTypeConverterFactory factory: factories) { 1.45 @@ -189,20 +207,24 @@ 1.46 } 1.47 this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]); 1.48 this.comparators = c.toArray(new ConversionComparator[c.size()]); 1.49 - 1.50 + this.autoConversionStrategy = autoConversionStrategy; 1.51 } 1.52 1.53 /** 1.54 * Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by 1.55 * {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of 1.56 - * parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive, 1.57 - * wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions, 1.58 - * it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters 1.59 - * provided by {@link GuardingTypeConverterFactory} implementations. 1.60 + * parameters. For all conversions that are not a JLS method invocation conversion it'll insert 1.61 + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters 1.62 + * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation 1.63 + * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first 1.64 + * if an automatic conversion strategy was specified in the 1.65 + * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply 1.66 + * {@link MethodHandle#asType(MethodType)} for any remaining conversions. 1.67 * 1.68 * @param handle target method handle 1.69 * @param fromType the types of source arguments 1.70 - * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and 1.71 + * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, 1.72 + * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and 1.73 * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with 1.74 * {@link GuardingTypeConverterFactory} produced type converters as filters. 1.75 */ 1.76 @@ -246,8 +268,12 @@ 1.77 } 1.78 } 1.79 1.80 - // Take care of automatic conversions 1.81 - return newHandle.asType(fromType); 1.82 + // Give change to automatic conversion strategy, if one is present. 1.83 + final MethodHandle autoConvertedHandle = 1.84 + autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle; 1.85 + 1.86 + // Do a final asType for any conversions that remain. 1.87 + return autoConvertedHandle.asType(fromType); 1.88 } 1.89 1.90 private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List<MethodHandle> converters) {