src/jdk/internal/dynalink/support/TypeConverterFactory.java

changeset 1090
99571b7922c0
parent 963
e2497b11a021
child 1205
4112748288bb
     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) {

mercurial