src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/MethodSubstitutionPlugin.java
changeset 58877 aec7bf35d6f5
parent 58299 6df94ce3ab2f
equal deleted inserted replaced
58876:1a8d65e71a66 58877:aec7bf35d6f5
    40 import org.graalvm.compiler.nodes.StructuredGraph;
    40 import org.graalvm.compiler.nodes.StructuredGraph;
    41 import org.graalvm.compiler.nodes.ValueNode;
    41 import org.graalvm.compiler.nodes.ValueNode;
    42 
    42 
    43 import jdk.vm.ci.meta.MetaAccessProvider;
    43 import jdk.vm.ci.meta.MetaAccessProvider;
    44 import jdk.vm.ci.meta.ResolvedJavaMethod;
    44 import jdk.vm.ci.meta.ResolvedJavaMethod;
       
    45 import jdk.vm.ci.meta.ResolvedJavaType;
    45 
    46 
    46 /**
    47 /**
    47  * An {@link InvocationPlugin} for a method where the implementation of the method is provided by a
    48  * An {@link InvocationPlugin} for a method where the implementation of the method is provided by a
    48  * {@linkplain #getSubstitute(MetaAccessProvider) substitute} method. A substitute method must be
    49  * {@linkplain #getSubstitute(MetaAccessProvider) substitute} method. A substitute method must be
    49  * static even if the substituted method is not.
    50  * static even if the substituted method is not.
    54  * recommended practice is to use {@link MethodSubstitutionPlugin} only for complex
    55  * recommended practice is to use {@link MethodSubstitutionPlugin} only for complex
    55  * intrinsifications which is typically those using non-straight-line control flow.
    56  * intrinsifications which is typically those using non-straight-line control flow.
    56  */
    57  */
    57 public final class MethodSubstitutionPlugin implements InvocationPlugin {
    58 public final class MethodSubstitutionPlugin implements InvocationPlugin {
    58 
    59 
       
    60     private InvocationPlugins.Registration registration;
       
    61 
    59     private ResolvedJavaMethod cachedSubstitute;
    62     private ResolvedJavaMethod cachedSubstitute;
    60 
    63 
    61     /**
    64     /**
    62      * The class in which the substitute method is declared.
    65      * The class in which the substitute method is declared.
    63      */
    66      */
    64     private final Class<?> declaringClass;
    67     private final Class<?> declaringClass;
    65 
    68 
    66     /**
    69     /**
    67      * The name of the original and substitute method.
    70      * The name of the substitute method.
    68      */
    71      */
    69     private final String name;
    72     private final String substituteName;
       
    73 
       
    74     /**
       
    75      * The name of the original method.
       
    76      */
       
    77     private final String originalName;
    70 
    78 
    71     /**
    79     /**
    72      * The parameter types of the substitute method.
    80      * The parameter types of the substitute method.
    73      */
    81      */
    74     private final Type[] parameters;
    82     private final Type[] parameters;
    79 
    87 
    80     /**
    88     /**
    81      * Creates a method substitution plugin.
    89      * Creates a method substitution plugin.
    82      *
    90      *
    83      * @param bytecodeProvider used to get the bytecodes to parse for the substitute method
    91      * @param bytecodeProvider used to get the bytecodes to parse for the substitute method
       
    92      * @param originalName the name of the original method
    84      * @param declaringClass the class in which the substitute method is declared
    93      * @param declaringClass the class in which the substitute method is declared
    85      * @param name the name of the substitute method
    94      * @param substituteName the name of the substitute method
    86      * @param parameters the parameter types of the substitute method. If the original method is not
    95      * @param parameters the parameter types of the substitute method. If the original method is not
    87      *            static, then {@code parameters[0]} must be the {@link Class} value denoting
    96      *            static, then {@code parameters[0]} must be the {@link Class} value denoting
    88      *            {@link InvocationPlugin.Receiver}
    97      *            {@link InvocationPlugin.Receiver}
    89      */
    98      */
    90     public MethodSubstitutionPlugin(BytecodeProvider bytecodeProvider, Class<?> declaringClass, String name, Type... parameters) {
    99     public MethodSubstitutionPlugin(InvocationPlugins.Registration registration, BytecodeProvider bytecodeProvider, String originalName, Class<?> declaringClass, String substituteName,
       
   100                     Type... parameters) {
       
   101         assert bytecodeProvider != null : "Requires a non-null methodSubstitutionBytecodeProvider";
       
   102         this.registration = registration;
    91         this.bytecodeProvider = bytecodeProvider;
   103         this.bytecodeProvider = bytecodeProvider;
       
   104         this.originalName = originalName;
    92         this.declaringClass = declaringClass;
   105         this.declaringClass = declaringClass;
    93         this.name = name;
   106         this.substituteName = substituteName;
    94         this.parameters = parameters;
   107         this.parameters = parameters;
    95         this.originalIsStatic = parameters.length == 0 || parameters[0] != InvocationPlugin.Receiver.class;
   108         this.originalIsStatic = parameters.length == 0 || parameters[0] != InvocationPlugin.Receiver.class;
    96     }
   109     }
    97 
   110 
    98     @Override
   111     @Override
   142 
   155 
   143     /**
   156     /**
   144      * Determines if a given method is the substitute method of this plugin.
   157      * Determines if a given method is the substitute method of this plugin.
   145      */
   158      */
   146     private boolean isSubstitute(Method m) {
   159     private boolean isSubstitute(Method m) {
   147         if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(name)) {
   160         if (Modifier.isStatic(m.getModifiers()) && m.getName().equals(substituteName)) {
   148             if (parameters.length == m.getParameterCount()) {
   161             if (parameters.length == m.getParameterCount()) {
   149                 Class<?>[] mparams = m.getParameterTypes();
   162                 Class<?>[] mparams = m.getParameterTypes();
   150                 int start = 0;
   163                 int start = 0;
   151                 if (!originalIsStatic) {
   164                 if (!originalIsStatic) {
   152                     start = 1;
   165                     start = 1;
   187     }
   200     }
   188 
   201 
   189     @Override
   202     @Override
   190     public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) {
   203     public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] argsIncludingReceiver) {
   191         if (IS_IN_NATIVE_IMAGE || (UseEncodedGraphs.getValue(b.getOptions()) && !b.parsingIntrinsic())) {
   204         if (IS_IN_NATIVE_IMAGE || (UseEncodedGraphs.getValue(b.getOptions()) && !b.parsingIntrinsic())) {
   192             if (!IS_IN_NATIVE_IMAGE && UseEncodedGraphs.getValue(b.getOptions())) {
       
   193                 b.getReplacements().registerMethodSubstitution(this, targetMethod, INLINE_AFTER_PARSING, b.getOptions());
       
   194             }
       
   195             StructuredGraph subst = b.getReplacements().getMethodSubstitution(this,
   205             StructuredGraph subst = b.getReplacements().getMethodSubstitution(this,
   196                             targetMethod,
   206                             targetMethod,
   197                             INLINE_AFTER_PARSING,
   207                             INLINE_AFTER_PARSING,
   198                             StructuredGraph.AllowAssumptions.ifNonNull(b.getAssumptions()),
   208                             StructuredGraph.AllowAssumptions.ifNonNull(b.getAssumptions()),
   199                             null /* cancellable */,
   209                             null /* cancellable */,
   218         throw new GraalError("could not find method named \"execute\" in " + c.getName());
   228         throw new GraalError("could not find method named \"execute\" in " + c.getName());
   219     }
   229     }
   220 
   230 
   221     @Override
   231     @Override
   222     public String toString() {
   232     public String toString() {
   223         return String.format("%s[%s.%s(%s)]", getClass().getSimpleName(), declaringClass.getName(), name,
   233         return String.format("%s[%s.%s(%s)]", getClass().getSimpleName(), declaringClass.getName(), substituteName,
   224                         Arrays.asList(parameters).stream().map(c -> c.getTypeName()).collect(Collectors.joining(", ")));
   234                         Arrays.asList(parameters).stream().map(c -> c.getTypeName()).collect(Collectors.joining(", ")));
   225     }
   235     }
       
   236 
       
   237     public String originalMethodAsString() {
       
   238         return String.format("%s.%s(%s)", declaringClass.getName(), substituteName, Arrays.asList(parameters).stream().map(c -> c.getTypeName()).collect(Collectors.joining(", ")));
       
   239     }
       
   240 
       
   241     public ResolvedJavaMethod getOriginalMethod(MetaAccessProvider metaAccess) {
       
   242         Class<?> clazz = resolveType(registration.getDeclaringType(), false);
       
   243         if (clazz == null) {
       
   244             throw new GraalError("Can't find original class for " + this + " with class " + registration.getDeclaringType());
       
   245         }
       
   246         ResolvedJavaType type = metaAccess.lookupJavaType(clazz);
       
   247         String argumentsDescriptor = InvocationPlugins.toArgumentDescriptor(originalIsStatic, this.parameters);
       
   248         for (ResolvedJavaMethod declared : type.getDeclaredMethods()) {
       
   249             if (declared.getName().equals(originalName) && declared.isStatic() == originalIsStatic &&
       
   250                             declared.getSignature().toMethodDescriptor().startsWith(argumentsDescriptor)) {
       
   251                 return declared;
       
   252             }
       
   253         }
       
   254         throw new GraalError("Can't find original method for " + this + " with class " + registration.getDeclaringType());
       
   255     }
   226 }
   256 }