95 import jdk.internal.dynalink.linker.ConversionComparator.Comparison; |
95 import jdk.internal.dynalink.linker.ConversionComparator.Comparison; |
96 import jdk.internal.dynalink.linker.GuardedInvocation; |
96 import jdk.internal.dynalink.linker.GuardedInvocation; |
97 import jdk.internal.dynalink.linker.GuardedTypeConversion; |
97 import jdk.internal.dynalink.linker.GuardedTypeConversion; |
98 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; |
98 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; |
99 import jdk.internal.dynalink.linker.LinkerServices; |
99 import jdk.internal.dynalink.linker.LinkerServices; |
|
100 import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; |
100 |
101 |
101 /** |
102 /** |
102 * A factory for type converters. This class is the main implementation behind the |
103 * A factory for type converters. This class is the main implementation behind the |
103 * {@link LinkerServices#asType(MethodHandle, MethodType)}. It manages the known {@link GuardingTypeConverterFactory} |
104 * {@link LinkerServices#asType(MethodHandle, MethodType)}. It manages the known {@link GuardingTypeConverterFactory} |
104 * instances and creates appropriate converters for method handles. |
105 * instances and creates appropriate converters for method handles. |
175 |
177 |
176 /** |
178 /** |
177 * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances. |
179 * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances. |
178 * |
180 * |
179 * @param factories the {@link GuardingTypeConverterFactory} instances to compose. |
181 * @param factories the {@link GuardingTypeConverterFactory} instances to compose. |
180 */ |
182 * @param autoConversionStrategy conversion strategy for automatic type conversions. After |
181 public TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories) { |
183 * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom |
|
184 * conversions to a method handle, it still needs to effect |
|
185 * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that |
|
186 * can usually be automatically applied as per |
|
187 * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. |
|
188 * However, sometimes language runtimes will want to customize even those conversions for their own call |
|
189 * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by |
|
190 * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom |
|
191 * automatic conversion strategy, that can deal with null values. Note that when the strategy's |
|
192 * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} |
|
193 * is invoked, the custom language conversions will already have been applied to the method handle, so by |
|
194 * design the difference between the handle's current method type and the desired final type will always |
|
195 * only be ones that can be subjected to method invocation conversions. Can be null, in which case no |
|
196 * custom strategy is employed. |
|
197 */ |
|
198 public TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories, |
|
199 final MethodTypeConversionStrategy autoConversionStrategy) { |
182 final List<GuardingTypeConverterFactory> l = new LinkedList<>(); |
200 final List<GuardingTypeConverterFactory> l = new LinkedList<>(); |
183 final List<ConversionComparator> c = new LinkedList<>(); |
201 final List<ConversionComparator> c = new LinkedList<>(); |
184 for(final GuardingTypeConverterFactory factory: factories) { |
202 for(final GuardingTypeConverterFactory factory: factories) { |
185 l.add(factory); |
203 l.add(factory); |
186 if(factory instanceof ConversionComparator) { |
204 if(factory instanceof ConversionComparator) { |
187 c.add((ConversionComparator)factory); |
205 c.add((ConversionComparator)factory); |
188 } |
206 } |
189 } |
207 } |
190 this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]); |
208 this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]); |
191 this.comparators = c.toArray(new ConversionComparator[c.size()]); |
209 this.comparators = c.toArray(new ConversionComparator[c.size()]); |
192 |
210 this.autoConversionStrategy = autoConversionStrategy; |
193 } |
211 } |
194 |
212 |
195 /** |
213 /** |
196 * Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by |
214 * Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by |
197 * {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of |
215 * {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of |
198 * parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive, |
216 * parameters. For all conversions that are not a JLS method invocation conversion it'll insert |
199 * wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions, |
217 * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters |
200 * it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters |
218 * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation |
201 * provided by {@link GuardingTypeConverterFactory} implementations. |
219 * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first |
|
220 * if an automatic conversion strategy was specified in the |
|
221 * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply |
|
222 * {@link MethodHandle#asType(MethodType)} for any remaining conversions. |
202 * |
223 * |
203 * @param handle target method handle |
224 * @param handle target method handle |
204 * @param fromType the types of source arguments |
225 * @param fromType the types of source arguments |
205 * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and |
226 * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, |
|
227 * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and |
206 * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with |
228 * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with |
207 * {@link GuardingTypeConverterFactory} produced type converters as filters. |
229 * {@link GuardingTypeConverterFactory} produced type converters as filters. |
208 */ |
230 */ |
209 public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { |
231 public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { |
210 MethodHandle newHandle = handle; |
232 MethodHandle newHandle = handle; |