81 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
81 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
82 */ |
82 */ |
83 |
83 |
84 package jdk.internal.dynalink.linker; |
84 package jdk.internal.dynalink.linker; |
85 |
85 |
86 import static jdk.nashorn.internal.lookup.Lookup.MH; |
|
87 |
|
88 import java.lang.invoke.MethodHandle; |
86 import java.lang.invoke.MethodHandle; |
89 import java.lang.invoke.MethodHandles; |
87 import java.lang.invoke.MethodHandles; |
90 import java.lang.invoke.MethodType; |
88 import java.lang.invoke.MethodType; |
91 import java.lang.invoke.SwitchPoint; |
89 import java.lang.invoke.SwitchPoint; |
92 import java.lang.invoke.WrongMethodTypeException; |
|
93 import java.util.List; |
90 import java.util.List; |
94 import java.util.Objects; |
91 import java.util.Objects; |
95 import jdk.internal.dynalink.CallSiteDescriptor; |
92 import jdk.internal.dynalink.CallSiteDescriptor; |
96 import jdk.internal.dynalink.support.Guards; |
93 import jdk.internal.dynalink.support.Guards; |
97 |
94 |
98 /** |
95 /** |
99 * Represents a conditionally valid method handle. It is an immutable triple of an invocation method handle, a guard |
96 * Represents a conditionally valid method handle. Usually produced as a return |
100 * method handle that defines the applicability of the invocation handle, and a switch point that can be used for |
97 * value of |
101 * external invalidation of the invocation handle. The invocation handle is suitable for invocation if the guard |
98 * {@link GuardingDynamicLinker#getGuardedInvocation(LinkRequest, LinkerServices)} |
102 * handle returns true for its arguments, and as long as the switch point is not invalidated. Both the guard and the |
99 * and {@link GuardingTypeConverterFactory#convertToType(Class, Class)}. It is |
103 * switch point are optional; neither, one, or both can be present. |
100 * an immutable tuple of an invocation method handle, a guard method handle that |
|
101 * defines the applicability of the invocation handle, zero or more switch |
|
102 * points that can be used for external invalidation of the invocation handle, |
|
103 * and an exception type that if thrown during an invocation of the method |
|
104 * handle also invalidates it. The invocation handle is suitable for invocation |
|
105 * if the guard handle returns true for its arguments, and as long as any of the |
|
106 * switch points are not invalidated, and as long as it does not throw an |
|
107 * exception of the designated type. The guard, the switch point, and the |
|
108 * exception type are all optional (a guarded invocation having none of them is |
|
109 * unconditionally valid). |
104 */ |
110 */ |
105 public class GuardedInvocation { |
111 public class GuardedInvocation { |
106 private final MethodHandle invocation; |
112 private final MethodHandle invocation; |
107 private final MethodHandle guard; |
113 private final MethodHandle guard; |
108 private final Class<? extends Throwable> exception; |
114 private final Class<? extends Throwable> exception; |
109 private final SwitchPoint[] switchPoints; |
115 private final SwitchPoint[] switchPoints; |
110 |
116 |
111 /** |
117 /** |
112 * Creates a new guarded invocation. This invocation is unconditional as it has no invalidations. |
118 * Creates a new unconditional guarded invocation. It is unconditional as it |
113 * |
119 * has no invalidations. |
114 * @param invocation the method handle representing the invocation. Must not be null. |
120 * |
|
121 * @param invocation the method handle representing the invocation. Must not |
|
122 * be null. |
115 * @throws NullPointerException if invocation is null. |
123 * @throws NullPointerException if invocation is null. |
116 */ |
124 */ |
117 public GuardedInvocation(final MethodHandle invocation) { |
125 public GuardedInvocation(final MethodHandle invocation) { |
118 this(invocation, null, (SwitchPoint)null, null); |
126 this(invocation, null, (SwitchPoint)null, null); |
119 } |
127 } |
120 |
128 |
121 /** |
129 /** |
122 * Creates a new guarded invocation. |
130 * Creates a new guarded invocation, with a guard method handle. |
123 * |
131 * |
124 * @param invocation the method handle representing the invocation. Must not be null. |
132 * @param invocation the method handle representing the invocation. Must not |
125 * @param guard the method handle representing the guard. Must have the same method type as the invocation, except |
133 * be null. |
126 * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null to represent |
134 * @param guard the method handle representing the guard. Must have be |
127 * an unconditional invocation, although that is unusual. |
135 * compatible with the {@code invocation} handle as per |
|
136 * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. |
|
137 * For some useful guards, check out the {@link Guards} class. It can be |
|
138 * null to represent an unconditional invocation. |
128 * @throws NullPointerException if invocation is null. |
139 * @throws NullPointerException if invocation is null. |
129 */ |
140 */ |
130 public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard) { |
141 public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard) { |
131 this(invocation, guard, (SwitchPoint)null, null); |
142 this(invocation, guard, (SwitchPoint)null, null); |
132 } |
143 } |
133 |
144 |
134 /** |
145 /** |
135 * Creates a new guarded invocation. |
146 * Creates a new guarded invocation that can be invalidated by a switch |
136 * |
147 * point. |
137 * @param invocation the method handle representing the invocation. Must not be null. |
148 * |
138 * @param switchPoint the optional switch point that can be used to invalidate this linkage. |
149 * @param invocation the method handle representing the invocation. Must |
|
150 * not be null. |
|
151 * @param switchPoint the optional switch point that can be used to |
|
152 * invalidate this linkage. It can be null. If it is null, this represents |
|
153 * an unconditional invocation. |
139 * @throws NullPointerException if invocation is null. |
154 * @throws NullPointerException if invocation is null. |
140 */ |
155 */ |
141 public GuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint) { |
156 public GuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint) { |
142 this(invocation, null, switchPoint, null); |
157 this(invocation, null, switchPoint, null); |
143 } |
158 } |
144 |
159 |
145 /** |
160 /** |
146 * Creates a new guarded invocation. |
161 * Creates a new guarded invocation, with both a guard method handle and a |
147 * |
162 * switch point that can be used to invalidate it. |
148 * @param invocation the method handle representing the invocation. Must not be null. |
163 * |
149 * @param guard the method handle representing the guard. Must have the same method type as the invocation, except |
164 * @param invocation the method handle representing the invocation. Must |
150 * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it |
165 * not be null. |
151 * and the switch point are null, this represents an unconditional invocation, which is legal but unusual. |
166 * @param guard the method handle representing the guard. Must have be |
152 * @param switchPoint the optional switch point that can be used to invalidate this linkage. |
167 * compatible with the {@code invocation} handle as per |
|
168 * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. |
|
169 * For some useful guards, check out the {@link Guards} class. It can be |
|
170 * null. If both it and the switch point are null, this represents an |
|
171 * unconditional invocation. |
|
172 * @param switchPoint the optional switch point that can be used to |
|
173 * invalidate this linkage. |
153 * @throws NullPointerException if invocation is null. |
174 * @throws NullPointerException if invocation is null. |
154 */ |
175 */ |
155 public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint) { |
176 public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint) { |
156 this(invocation, guard, switchPoint, null); |
177 this(invocation, guard, switchPoint, null); |
157 } |
178 } |
158 |
179 |
159 /** |
180 /** |
160 * Creates a new guarded invocation. |
181 * Creates a new guarded invocation, with a guard method handle, a |
161 * |
182 * switch point that can be used to invalidate it, and an exception that if |
162 * @param invocation the method handle representing the invocation. Must not be null. |
183 * thrown when invoked also invalidates it. |
163 * @param guard the method handle representing the guard. Must have the same method type as the invocation, except |
184 * |
164 * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it |
185 * @param invocation the method handle representing the invocation. Must not |
165 * and the switch point are null, this represents an unconditional invocation, which is legal but unusual. |
186 * be null. |
166 * @param switchPoint the optional switch point that can be used to invalidate this linkage. |
187 * @param guard the method handle representing the guard. Must have be |
167 * @param exception the optional exception type that is expected to be thrown by the invocation and that also |
188 * compatible with the {@code invocation} handle as per |
168 * invalidates the linkage. |
189 * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. |
|
190 * For some useful guards, check out the {@link Guards} class. It can be |
|
191 * null. If it and the switch point and the exception are all null, this |
|
192 * represents an unconditional invocation. |
|
193 * @param switchPoint the optional switch point that can be used to |
|
194 * invalidate this linkage. |
|
195 * @param exception the optional exception type that is when thrown by the |
|
196 * invocation also invalidates it. |
169 * @throws NullPointerException if invocation is null. |
197 * @throws NullPointerException if invocation is null. |
170 */ |
198 */ |
171 public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class<? extends Throwable> exception) { |
199 public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class<? extends Throwable> exception) { |
172 this.invocation = Objects.requireNonNull(invocation); |
200 this.invocation = Objects.requireNonNull(invocation); |
173 this.guard = guard; |
201 this.guard = guard; |
174 this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint }; |
202 this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint }; |
175 this.exception = exception; |
203 this.exception = exception; |
176 } |
204 } |
177 |
205 |
178 /** |
206 /** |
179 * Creates a new guarded invocation |
207 * Creates a new guarded invocation, with a guard method handle, any number |
180 * |
208 * of switch points that can be used to invalidate it, and an exception that |
181 * @param invocation the method handle representing the invocation. Must not be null. |
209 * if thrown when invoked also invalidates it. |
182 * @param guard the method handle representing the guard. Must have the same method type as the invocation, except |
210 * |
183 * it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it |
211 * @param invocation the method handle representing the invocation. Must not |
184 * and the switch point are null, this represents an unconditional invocation, which is legal but unusual. |
212 * be null. |
185 * @param switchPoints the optional switch points that can be used to invalidate this linkage. |
213 * @param guard the method handle representing the guard. Must have be |
186 * @param exception the optional exception type that is expected to be thrown by the invocation and that also |
214 * compatible with the {@code invocation} handle as per |
187 * invalidates the linkage. |
215 * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. |
|
216 * For some useful guards, check out the {@link Guards} class. It can be |
|
217 * null. If it and the exception are both null, and no switch points were |
|
218 * specified, this represents an unconditional invocation. |
|
219 * @param switchPoints optional switch points that can be used to |
|
220 * invalidate this linkage. |
|
221 * @param exception the optional exception type that is when thrown by the |
|
222 * invocation also invalidates it. |
188 * @throws NullPointerException if invocation is null. |
223 * @throws NullPointerException if invocation is null. |
189 */ |
224 */ |
190 public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class<? extends Throwable> exception) { |
225 public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class<? extends Throwable> exception) { |
191 this.invocation = Objects.requireNonNull(invocation); |
226 this.invocation = Objects.requireNonNull(invocation); |
192 this.guard = guard; |
227 this.guard = guard; |
299 } |
327 } |
300 return replaceMethods(newInvocation, newGuard); |
328 return replaceMethods(newInvocation, newGuard); |
301 } |
329 } |
302 |
330 |
303 /** |
331 /** |
304 * Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation |
332 * Changes the type of the invocation, as if |
305 * and its guard, if it has one (with return type changed to boolean, and parameter count potentially truncated for |
333 * {@link MethodHandle#asType(MethodType)} was applied to its invocation |
306 * the guard). If the invocation already is of the required type, returns this object. |
334 * and its guard, if it has one (with return type changed to boolean, and |
|
335 * parameter count potentially truncated for the guard). If the invocation |
|
336 * already is of the required type, returns this object. |
307 * @param newType the new type of the invocation. |
337 * @param newType the new type of the invocation. |
308 * @return a guarded invocation with the new type applied to it. |
338 * @return a guarded invocation with the new type applied to it. |
309 */ |
339 */ |
310 public GuardedInvocation asType(final MethodType newType) { |
340 public GuardedInvocation asType(final MethodType newType) { |
311 return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType)); |
341 return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType)); |
312 } |
342 } |
313 |
343 |
314 /** |
344 /** |
315 * Changes the type of the invocation, as if {@link LinkerServices#asType(MethodHandle, MethodType)} was applied to |
345 * Changes the type of the invocation, as if |
316 * its invocation and its guard, if it has one (with return type changed to boolean, and parameter count potentially |
346 * {@link LinkerServices#asType(MethodHandle, MethodType)} was applied to |
317 * truncated for the guard). If the invocation already is of the required type, returns this object. |
347 * its invocation and its guard, if it has one (with return type changed to |
|
348 * boolean, and parameter count potentially truncated for the guard). If the |
|
349 * invocation already is of the required type, returns this object. |
318 * @param linkerServices the linker services to use for the conversion |
350 * @param linkerServices the linker services to use for the conversion |
319 * @param newType the new type of the invocation. |
351 * @param newType the new type of the invocation. |
320 * @return a guarded invocation with the new type applied to it. |
352 * @return a guarded invocation with the new type applied to it. |
321 */ |
353 */ |
322 public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) { |
354 public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) { |
323 return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null : |
355 return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null : |
324 Guards.asType(linkerServices, guard, newType)); |
356 Guards.asType(linkerServices, guard, newType)); |
325 } |
357 } |
326 |
358 |
327 /** |
359 /** |
328 * Changes the type of the invocation, as if {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was |
360 * Changes the type of the invocation, as if |
329 * applied to its invocation and {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its guard, if it |
361 * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was |
330 * has one (with return type changed to boolean, and parameter count potentially truncated for the guard). If the |
362 * applied to its invocation and |
331 * invocation doesn't change its type, returns this object. |
363 * {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its |
|
364 * guard, if it has one (with return type changed to boolean, and parameter |
|
365 * count potentially truncated for the guard). If the invocation doesn't |
|
366 * change its type, returns this object. |
332 * @param linkerServices the linker services to use for the conversion |
367 * @param linkerServices the linker services to use for the conversion |
333 * @param newType the new type of the invocation. |
368 * @param newType the new type of the invocation. |
334 * @return a guarded invocation with the new type applied to it. |
369 * @return a guarded invocation with the new type applied to it. |
335 */ |
370 */ |
336 public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) { |
371 public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) { |
337 return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null : |
372 return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null : |
338 Guards.asType(linkerServices, guard, newType)); |
373 Guards.asType(linkerServices, guard, newType)); |
339 } |
374 } |
340 |
375 |
341 /** |
376 /** |
342 * Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation |
377 * Changes the type of the invocation, as if |
343 * and its guard, if it has one (with return type changed to boolean for guard). If the invocation already is of the |
378 * {@link MethodHandle#asType(MethodType)} was applied to its invocation |
344 * required type, returns this object. |
379 * and its guard, if it has one (with return type changed to boolean for |
|
380 * guard). If the invocation already is of the required type, returns this |
|
381 * object. |
345 * @param desc a call descriptor whose method type is adapted. |
382 * @param desc a call descriptor whose method type is adapted. |
346 * @return a guarded invocation with the new type applied to it. |
383 * @return a guarded invocation with the new type applied to it. |
347 */ |
384 */ |
348 public GuardedInvocation asType(final CallSiteDescriptor desc) { |
385 public GuardedInvocation asType(final CallSiteDescriptor desc) { |
349 return asType(desc.getMethodType()); |
386 return asType(desc.getMethodType()); |
350 } |
387 } |
351 |
388 |
352 /** |
389 /** |
353 * Applies argument filters to both the invocation and the guard (if there is one). |
390 * Applies argument filters to both the invocation and the guard (if there |
|
391 * is one) with {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}. |
354 * @param pos the position of the first argument being filtered |
392 * @param pos the position of the first argument being filtered |
355 * @param filters the argument filters |
393 * @param filters the argument filters |
356 * @return a filtered invocation |
394 * @return a filtered invocation |
357 */ |
395 */ |
358 public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) { |
396 public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) { |
359 return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null : |
397 return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null : |
360 MethodHandles.filterArguments(guard, pos, filters)); |
398 MethodHandles.filterArguments(guard, pos, filters)); |
361 } |
399 } |
362 |
400 |
363 /** |
401 /** |
364 * Makes an invocation that drops arguments in both the invocation and the guard (if there is one). |
402 * Makes an invocation that drops arguments in both the invocation and the |
|
403 * guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, List)}. |
365 * @param pos the position of the first argument being dropped |
404 * @param pos the position of the first argument being dropped |
366 * @param valueTypes the types of the values being dropped |
405 * @param valueTypes the types of the values being dropped |
367 * @return an invocation that drops arguments |
406 * @return an invocation that drops arguments |
368 */ |
407 */ |
369 public GuardedInvocation dropArguments(final int pos, final List<Class<?>> valueTypes) { |
408 public GuardedInvocation dropArguments(final int pos, final List<Class<?>> valueTypes) { |
370 return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null : |
409 return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null : |
371 MethodHandles.dropArguments(guard, pos, valueTypes)); |
410 MethodHandles.dropArguments(guard, pos, valueTypes)); |
372 } |
411 } |
373 |
412 |
374 /** |
413 /** |
375 * Makes an invocation that drops arguments in both the invocation and the guard (if there is one). |
414 * Makes an invocation that drops arguments in both the invocation and the |
|
415 * guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, Class...)}. |
376 * @param pos the position of the first argument being dropped |
416 * @param pos the position of the first argument being dropped |
377 * @param valueTypes the types of the values being dropped |
417 * @param valueTypes the types of the values being dropped |
378 * @return an invocation that drops arguments |
418 * @return an invocation that drops arguments |
379 */ |
419 */ |
380 public GuardedInvocation dropArguments(final int pos, final Class<?>... valueTypes) { |
420 public GuardedInvocation dropArguments(final int pos, final Class<?>... valueTypes) { |