44 import jdk.internal.vm.compiler.collections.MapCursor; |
44 import jdk.internal.vm.compiler.collections.MapCursor; |
45 import jdk.internal.vm.compiler.collections.Pair; |
45 import jdk.internal.vm.compiler.collections.Pair; |
46 import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap; |
46 import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap; |
47 import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor; |
47 import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor; |
48 import org.graalvm.compiler.api.replacements.MethodSubstitution; |
48 import org.graalvm.compiler.api.replacements.MethodSubstitution; |
49 import org.graalvm.compiler.api.replacements.MethodSubstitutionRegistry; |
|
50 import org.graalvm.compiler.bytecode.BytecodeProvider; |
49 import org.graalvm.compiler.bytecode.BytecodeProvider; |
51 import org.graalvm.compiler.core.common.SuppressFBWarnings; |
50 import org.graalvm.compiler.core.common.SuppressFBWarnings; |
52 import org.graalvm.compiler.debug.Assertions; |
51 import org.graalvm.compiler.debug.Assertions; |
53 import org.graalvm.compiler.debug.GraalError; |
52 import org.graalvm.compiler.debug.GraalError; |
54 import org.graalvm.compiler.graph.Node; |
53 import org.graalvm.compiler.graph.Node; |
55 import org.graalvm.compiler.graph.iterators.NodeIterable; |
54 import org.graalvm.compiler.graph.iterators.NodeIterable; |
56 import org.graalvm.compiler.nodes.ValueNode; |
55 import org.graalvm.compiler.nodes.ValueNode; |
57 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; |
56 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; |
|
57 import org.graalvm.compiler.nodes.spi.Replacements; |
58 |
58 |
59 import jdk.vm.ci.meta.MetaUtil; |
59 import jdk.vm.ci.meta.MetaUtil; |
60 import jdk.vm.ci.meta.ResolvedJavaMethod; |
60 import jdk.vm.ci.meta.ResolvedJavaMethod; |
61 import jdk.vm.ci.meta.ResolvedJavaType; |
61 import jdk.vm.ci.meta.ResolvedJavaType; |
62 import jdk.vm.ci.meta.Signature; |
62 import jdk.vm.ci.meta.Signature; |
199 * via this object |
203 * via this object |
200 */ |
204 */ |
201 public Registration(InvocationPlugins plugins, Type declaringType) { |
205 public Registration(InvocationPlugins plugins, Type declaringType) { |
202 this.plugins = plugins; |
206 this.plugins = plugins; |
203 this.declaringType = declaringType; |
207 this.declaringType = declaringType; |
204 this.methodSubstitutionBytecodeProvider = null; |
208 this.replacements = null; |
|
209 this.bytecodeProvider = null; |
205 } |
210 } |
206 |
211 |
207 /** |
212 /** |
208 * Creates an object for registering {@link InvocationPlugin}s for methods declared by a |
213 * Creates an object for registering {@link InvocationPlugin}s for methods declared by a |
209 * given class. |
214 * given class. |
210 * |
215 * |
211 * @param plugins where to register the plugins |
216 * @param plugins where to register the plugins |
212 * @param declaringType the class declaring the methods for which plugins will be registered |
217 * @param declaringType the class declaring the methods for which plugins will be registered |
213 * via this object |
218 * via this object |
214 * @param methodSubstitutionBytecodeProvider provider used to get the bytecodes to parse for |
219 * @param replacements the current Replacements provider |
215 * method substitutions |
220 */ |
216 */ |
221 public Registration(InvocationPlugins plugins, Type declaringType, Replacements replacements) { |
217 public Registration(InvocationPlugins plugins, Type declaringType, BytecodeProvider methodSubstitutionBytecodeProvider) { |
|
218 this.plugins = plugins; |
222 this.plugins = plugins; |
219 this.declaringType = declaringType; |
223 this.declaringType = declaringType; |
220 this.methodSubstitutionBytecodeProvider = methodSubstitutionBytecodeProvider; |
224 this.replacements = replacements; |
|
225 this.bytecodeProvider = replacements != null ? replacements.getDefaultReplacementBytecodeProvider() : null; |
|
226 } |
|
227 |
|
228 /** |
|
229 * Creates an object for registering {@link InvocationPlugin}s for methods declared by a |
|
230 * given class. |
|
231 * |
|
232 * @param plugins where to register the plugins |
|
233 * @param declaringType the class declaring the methods for which plugins will be registered |
|
234 * via this object |
|
235 * @param replacements the current Replacements provider |
|
236 */ |
|
237 public Registration(InvocationPlugins plugins, Type declaringType, Replacements replacements, BytecodeProvider bytecodeProvider) { |
|
238 this.plugins = plugins; |
|
239 this.declaringType = declaringType; |
|
240 this.replacements = replacements; |
|
241 this.bytecodeProvider = bytecodeProvider; |
221 } |
242 } |
222 |
243 |
223 /** |
244 /** |
224 * Creates an object for registering {@link InvocationPlugin}s for methods declared by a |
245 * Creates an object for registering {@link InvocationPlugin}s for methods declared by a |
225 * given class. |
246 * given class. |
229 * plugins will be registered via this object |
250 * plugins will be registered via this object |
230 */ |
251 */ |
231 public Registration(InvocationPlugins plugins, String declaringClassName) { |
252 public Registration(InvocationPlugins plugins, String declaringClassName) { |
232 this.plugins = plugins; |
253 this.plugins = plugins; |
233 this.declaringType = new OptionalLazySymbol(declaringClassName); |
254 this.declaringType = new OptionalLazySymbol(declaringClassName); |
234 this.methodSubstitutionBytecodeProvider = null; |
255 this.replacements = null; |
|
256 this.bytecodeProvider = null; |
235 } |
257 } |
236 |
258 |
237 /** |
259 /** |
238 * Creates an object for registering {@link InvocationPlugin}s for methods declared by a |
260 * Creates an object for registering {@link InvocationPlugin}s for methods declared by a |
239 * given class. |
261 * given class. |
240 * |
262 * |
241 * @param plugins where to register the plugins |
263 * @param plugins where to register the plugins |
242 * @param declaringClassName the name of the class class declaring the methods for which |
264 * @param declaringClassName the name of the class class declaring the methods for which |
243 * plugins will be registered via this object |
265 * plugins will be registered via this object |
244 * @param methodSubstitutionBytecodeProvider provider used to get the bytecodes to parse for |
266 * @param replacements the current Replacements provider |
245 * method substitutions |
267 */ |
246 */ |
268 public Registration(InvocationPlugins plugins, String declaringClassName, Replacements replacements) { |
247 public Registration(InvocationPlugins plugins, String declaringClassName, BytecodeProvider methodSubstitutionBytecodeProvider) { |
|
248 this.plugins = plugins; |
269 this.plugins = plugins; |
249 this.declaringType = new OptionalLazySymbol(declaringClassName); |
270 this.declaringType = new OptionalLazySymbol(declaringClassName); |
250 this.methodSubstitutionBytecodeProvider = methodSubstitutionBytecodeProvider; |
271 this.replacements = replacements; |
|
272 this.bytecodeProvider = replacements != null ? replacements.getDefaultReplacementBytecodeProvider() : null; |
251 } |
273 } |
252 |
274 |
253 /** |
275 /** |
254 * Configures this registration to allow or disallow overwriting of invocation plugins. |
276 * Configures this registration to allow or disallow overwriting of invocation plugins. |
255 */ |
277 */ |
334 * @param name the name of the method |
356 * @param name the name of the method |
335 * @param plugin the plugin to be registered |
357 * @param plugin the plugin to be registered |
336 */ |
358 */ |
337 public void register7(String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, Type arg7, InvocationPlugin plugin) { |
359 public void register7(String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, Type arg7, InvocationPlugin plugin) { |
338 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
360 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
|
361 } |
|
362 |
|
363 /** |
|
364 * Registers a plugin for a method with no arguments that is conditionally enabled. This |
|
365 * ensures that {@code Replacements} is aware of this plugin. |
|
366 * |
|
367 * @param name the name of the method |
|
368 * @param plugin the plugin to be registered |
|
369 */ |
|
370 public void registerConditional0(boolean isEnabled, String name, InvocationPlugin plugin) { |
|
371 replacements.registerConditionalPlugin(plugin); |
|
372 if (isEnabled) { |
|
373 plugins.register(plugin, false, allowOverwrite, declaringType, name); |
|
374 } |
|
375 } |
|
376 |
|
377 /** |
|
378 * Registers a plugin for a method with 1 argument that is conditionally enabled. This |
|
379 * ensures that {@code Replacements} is aware of this plugin. |
|
380 * |
|
381 * @param name the name of the method |
|
382 * @param plugin the plugin to be registered |
|
383 */ |
|
384 public void registerConditional1(boolean isEnabled, String name, Type arg, InvocationPlugin plugin) { |
|
385 replacements.registerConditionalPlugin(plugin); |
|
386 if (isEnabled) { |
|
387 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg); |
|
388 } |
|
389 } |
|
390 |
|
391 /** |
|
392 * Registers a plugin for a method with 2 arguments that is conditionally enabled. This |
|
393 * ensures that {@code Replacements} is aware of this plugin. |
|
394 * |
|
395 * @param name the name of the method |
|
396 * @param plugin the plugin to be registered |
|
397 */ |
|
398 public void registerConditional2(boolean isEnabled, String name, Type arg1, Type arg2, InvocationPlugin plugin) { |
|
399 replacements.registerConditionalPlugin(plugin); |
|
400 if (isEnabled) { |
|
401 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2); |
|
402 } |
|
403 } |
|
404 |
|
405 /** |
|
406 * Registers a plugin for a method with 3 arguments that is conditionally enabled. This |
|
407 * ensures that {@code Replacements} is aware of this plugin. |
|
408 * |
|
409 * @param name the name of the method |
|
410 * @param plugin the plugin to be registered |
|
411 */ |
|
412 public void registerConditional3(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, InvocationPlugin plugin) { |
|
413 replacements.registerConditionalPlugin(plugin); |
|
414 if (isEnabled) { |
|
415 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3); |
|
416 } |
|
417 } |
|
418 |
|
419 /** |
|
420 * Registers a plugin for a method with 4 arguments that is conditionally enabled. This |
|
421 * ensures that {@code Replacements} is aware of this plugin. |
|
422 * |
|
423 * @param name the name of the method |
|
424 * @param plugin the plugin to be registered |
|
425 */ |
|
426 public void registerConditional4(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, InvocationPlugin plugin) { |
|
427 replacements.registerConditionalPlugin(plugin); |
|
428 if (isEnabled) { |
|
429 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4); |
|
430 } |
|
431 } |
|
432 |
|
433 /** |
|
434 * Registers a plugin for a method with 5 arguments that is conditionally enabled. This |
|
435 * ensures that {@code Replacements} is aware of this plugin. |
|
436 * |
|
437 * @param name the name of the method |
|
438 * @param plugin the plugin to be registered |
|
439 */ |
|
440 public void registerConditional5(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, InvocationPlugin plugin) { |
|
441 replacements.registerConditionalPlugin(plugin); |
|
442 if (isEnabled) { |
|
443 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5); |
|
444 } |
|
445 } |
|
446 |
|
447 /** |
|
448 * Registers a plugin for a method with 6 arguments that is conditionally enabled. This |
|
449 * ensures that {@code Replacements} is aware of this plugin. |
|
450 * |
|
451 * @param name the name of the method |
|
452 * @param plugin the plugin to be registered |
|
453 */ |
|
454 public void registerConditional6(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, InvocationPlugin plugin) { |
|
455 replacements.registerConditionalPlugin(plugin); |
|
456 if (isEnabled) { |
|
457 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6); |
|
458 } |
|
459 } |
|
460 |
|
461 /** |
|
462 * Registers a plugin for a method with 7 arguments that is conditionally enabled. This |
|
463 * ensures that {@code Replacements} is aware of this plugin. |
|
464 * |
|
465 * @param name the name of the method |
|
466 * @param plugin the plugin to be registered |
|
467 */ |
|
468 public void registerConditional7(boolean isEnabled, String name, Type arg1, Type arg2, Type arg3, Type arg4, Type arg5, Type arg6, Type arg7, InvocationPlugin plugin) { |
|
469 replacements.registerConditionalPlugin(plugin); |
|
470 if (isEnabled) { |
|
471 plugins.register(plugin, false, allowOverwrite, declaringType, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7); |
|
472 } |
339 } |
473 } |
340 |
474 |
341 /** |
475 /** |
342 * Registers a plugin for an optional method with no arguments. |
476 * Registers a plugin for an optional method with no arguments. |
343 * |
477 * |
396 * @param argumentTypes the argument types of the method. Element 0 of this array must be |
530 * @param argumentTypes the argument types of the method. Element 0 of this array must be |
397 * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method |
531 * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method |
398 * is non-static. Upon returning, element 0 will have been rewritten to |
532 * is non-static. Upon returning, element 0 will have been rewritten to |
399 * {@code declaringClass} |
533 * {@code declaringClass} |
400 */ |
534 */ |
401 @Override |
|
402 public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, Type... argumentTypes) { |
535 public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, Type... argumentTypes) { |
403 registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes); |
536 registerMethodSubstitution(substituteDeclaringClass, name, name, argumentTypes); |
404 } |
537 } |
405 |
538 |
406 /** |
539 /** |
407 * Registers a plugin that implements a method based on the bytecode of a substitute method. |
540 * Registers a plugin that implements a method based on the bytecode of a substitute method. |
408 * |
541 * |
409 * @param substituteDeclaringClass the class declaring the substitute method |
542 * @param substituteDeclaringClass the class declaring the substitute method |
410 * @param name the name of both the original method |
543 * @param name the name of the original method |
411 * @param substituteName the name of the substitute method |
544 * @param substituteName the name of the substitute method |
412 * @param argumentTypes the argument types of the method. Element 0 of this array must be |
545 * @param argumentTypes the argument types of the method. Element 0 of this array must be |
413 * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method |
546 * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method |
414 * is non-static. Upon returning, element 0 will have been rewritten to |
547 * is non-static. Upon returning, element 0 will have been rewritten to |
415 * {@code declaringClass} |
548 * {@code declaringClass} |
416 */ |
549 */ |
417 @Override |
|
418 public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, String substituteName, Type... argumentTypes) { |
550 public void registerMethodSubstitution(Class<?> substituteDeclaringClass, String name, String substituteName, Type... argumentTypes) { |
419 MethodSubstitutionPlugin plugin = createMethodSubstitution(substituteDeclaringClass, substituteName, argumentTypes); |
551 doMethodSubstitutionRegistration(false, true, substituteDeclaringClass, name, substituteName, argumentTypes); |
420 plugins.register(plugin, false, allowOverwrite, declaringType, name, argumentTypes); |
552 } |
421 } |
553 |
422 |
554 /** |
423 public MethodSubstitutionPlugin createMethodSubstitution(Class<?> substituteDeclaringClass, String substituteName, Type... argumentTypes) { |
555 * Registers a plugin that implements a method based on the bytecode of a substitute method |
424 assert methodSubstitutionBytecodeProvider != null : "Registration used for method substitutions requires a non-null methodSubstitutionBytecodeProvider"; |
556 * that is conditinally enabled. This ensures that {@code Replacements} is aware of this |
425 MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(methodSubstitutionBytecodeProvider, substituteDeclaringClass, substituteName, argumentTypes); |
557 * plugin. |
426 return plugin; |
558 * |
427 } |
559 * @param isEnabled whether the plugin is enabled in the current compiler |
428 |
560 * @param substituteDeclaringClass the class declaring the substitute method |
|
561 * @param name the name of both the original and substitute method |
|
562 * @param argumentTypes the argument types of the method. Element 0 of this array must be |
|
563 * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method |
|
564 * is non-static. Upon returning, element 0 will have been rewritten to |
|
565 * {@code declaringClass} |
|
566 */ |
|
567 public void registerConditionalMethodSubstitution(boolean isEnabled, Class<?> substituteDeclaringClass, String name, Type... argumentTypes) { |
|
568 registerConditionalMethodSubstitution(isEnabled, substituteDeclaringClass, name, name, argumentTypes); |
|
569 } |
|
570 |
|
571 /** |
|
572 * Registers a plugin that implements a method based on the bytecode of a substitute method |
|
573 * that is conditinally enabled. This ensures that {@code Replacements} is aware of this |
|
574 * plugin. |
|
575 * |
|
576 * @param isEnabled whether the plugin is enabled in the current compiler |
|
577 * @param substituteDeclaringClass the class declaring the substitute method |
|
578 * @param name the name of the original method |
|
579 * @param substituteName the name of the substitute method |
|
580 * @param argumentTypes the argument types of the method. Element 0 of this array must be |
|
581 * the {@link Class} value for {@link InvocationPlugin.Receiver} iff the method |
|
582 * is non-static. Upon returning, element 0 will have been rewritten to |
|
583 * {@code declaringClass} |
|
584 */ |
|
585 public void registerConditionalMethodSubstitution(boolean isEnabled, Class<?> substituteDeclaringClass, String name, String substituteName, Type... argumentTypes) { |
|
586 doMethodSubstitutionRegistration(true, isEnabled, substituteDeclaringClass, name, substituteName, argumentTypes); |
|
587 } |
|
588 |
|
589 private void doMethodSubstitutionRegistration(boolean isConditional, boolean isEnabled, Class<?> substituteDeclaringClass, String name, String substituteName, Type[] argumentTypes) { |
|
590 MethodSubstitutionPlugin plugin = new MethodSubstitutionPlugin(this, bytecodeProvider, name, substituteDeclaringClass, substituteName, argumentTypes); |
|
591 replacements.registerMethodSubstitution(plugin); |
|
592 if (isConditional) { |
|
593 // Notify Replacements about the plugin even if it's not current enabled |
|
594 replacements.registerConditionalPlugin(plugin); |
|
595 } |
|
596 if (isEnabled) { |
|
597 plugins.register(plugin, false, allowOverwrite, declaringType, name, argumentTypes); |
|
598 } |
|
599 } |
429 } |
600 } |
430 |
601 |
431 /** |
602 /** |
432 * Utility for registering plugins after Graal may have been initialized. Registrations made via |
603 * Utility for registering plugins after Graal may have been initialized. Registrations made via |
433 * this class are not finalized until {@link #close} is called. |
604 * this class are not finalized until {@link #close} is called. |