1 /*
   2  * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package jdk.internal.jvmci.meta;
  24 
  25 import java.lang.annotation.*;
  26 import java.lang.invoke.*;
  27 import java.lang.reflect.*;
  28 import java.util.*;
  29 
  30 /**
  31  * Represents a resolved Java method. Methods, like fields and types, are resolved through
  32  * {@link ConstantPool constant pools}.
  33  */
  34 public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersProvider {
  35 
  36     /**
  37      * Returns the bytecode of this method, if the method has code. The returned byte array does not
  38      * contain breakpoints or non-Java bytecodes. This may return null if the
  39      * {@link #getDeclaringClass() holder} is not {@link ResolvedJavaType#isLinked() linked}.
  40      *
  41      * The contained constant pool indices may not be the ones found in the original class file but
  42      * they can be used with the JVMCI API (e.g. methods in {@link ConstantPool}).
  43      *
  44      * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} or if the
  45      *         code is not ready.
  46      */
  47     byte[] getCode();
  48 
  49     /**
  50      * Returns the size of the bytecode of this method, if the method has code. This is equivalent
  51      * to {@link #getCode()}. {@code length} if the method has code.
  52      *
  53      * @return the size of the bytecode in bytes, or 0 if no bytecode is available
  54      */
  55     int getCodeSize();
  56 
  57     /**
  58      * Returns the {@link ResolvedJavaType} object representing the class or interface that declares
  59      * this method.
  60      */
  61     ResolvedJavaType getDeclaringClass();
  62 
  63     /**
  64      * Returns the maximum number of locals used in this method's bytecodes.
  65      */
  66     int getMaxLocals();
  67 
  68     /**
  69      * Returns the maximum number of stack slots used in this method's bytecodes.
  70      */
  71     int getMaxStackSize();
  72 
  73     /**
  74      * {@inheritDoc}
  75      * <p>
  76      * Only the {@linkplain Modifier#methodModifiers() method flags} specified in the JVM
  77      * specification will be included in the returned mask.
  78      */
  79     int getModifiers();
  80 
  81     default boolean isFinal() {
  82         return ModifiersProvider.super.isFinalFlagSet();
  83     }
  84 
  85     /**
  86      * Determines if this method is a synthetic method as defined by the Java Language
  87      * Specification.
  88      */
  89     default boolean isSynthetic() {
  90         return (SYNTHETIC & getModifiers()) == SYNTHETIC;
  91     }
  92 
  93     /**
  94      * Checks that the method is a <a
  95      * href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">varargs</a>
  96      * method.
  97      *
  98      * @return whether the method is a varargs method
  99      */
 100     default boolean isVarArgs() {
 101         return (VARARGS & getModifiers()) == VARARGS;
 102     }
 103 
 104     /**
 105      * Checks that the method is a <a
 106      * href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6">bridge</a>
 107      * method.
 108      *
 109      * @return whether the method is a bridge method
 110      */
 111     default boolean isBridge() {
 112         return (BRIDGE & getModifiers()) == BRIDGE;
 113     }
 114 
 115     /**
 116      * Returns {@code true} if this method is a default method; returns {@code false} otherwise.
 117      *
 118      * A default method is a public non-abstract instance method, that is, a non-static method with
 119      * a body, declared in an interface type.
 120      *
 121      * @return true if and only if this method is a default method as defined by the Java Language
 122      *         Specification.
 123      */
 124     boolean isDefault();
 125 
 126     /**
 127      * Checks whether this method is a class initializer.
 128      *
 129      * @return {@code true} if the method is a class initializer
 130      */
 131     boolean isClassInitializer();
 132 
 133     /**
 134      * Checks whether this method is a constructor.
 135      *
 136      * @return {@code true} if the method is a constructor
 137      */
 138     boolean isConstructor();
 139 
 140     /**
 141      * Checks whether this method can be statically bound (usually, that means it is final or
 142      * private or static, but not abstract, or the declaring class is final).
 143      *
 144      * @return {@code true} if this method can be statically bound
 145      */
 146     boolean canBeStaticallyBound();
 147 
 148     /**
 149      * Returns the list of exception handlers for this method.
 150      */
 151     ExceptionHandler[] getExceptionHandlers();
 152 
 153     /**
 154      * Returns a stack trace element for this method and a given bytecode index.
 155      */
 156     StackTraceElement asStackTraceElement(int bci);
 157 
 158     /**
 159      * Returns an object that provides access to the profiling information recorded for this method.
 160      */
 161     default ProfilingInfo getProfilingInfo() {
 162         return getProfilingInfo(true, true);
 163     }
 164 
 165     /**
 166      * Returns an object that provides access to the profiling information recorded for this method.
 167      *
 168      * @param includeNormal if true,
 169      *            {@linkplain ProfilingInfo#getDeoptimizationCount(DeoptimizationReason)
 170      *            deoptimization counts} will include deoptimization that happened during execution
 171      *            of standard non-osr methods.
 172      * @param includeOSR if true,
 173      *            {@linkplain ProfilingInfo#getDeoptimizationCount(DeoptimizationReason)
 174      *            deoptimization counts} will include deoptimization that happened during execution
 175      *            of on-stack-replacement methods.
 176      */
 177     ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR);
 178 
 179     /**
 180      * Invalidates the profiling information and restarts profiling upon the next invocation.
 181      */
 182     void reprofile();
 183 
 184     /**
 185      * Returns the constant pool of this method.
 186      */
 187     ConstantPool getConstantPool();
 188 
 189     /**
 190      * Returns all annotations of this method. If no annotations are present, an array of length 0
 191      * is returned.
 192      */
 193     Annotation[] getAnnotations();
 194 
 195     /**
 196      * Returns the annotation for the specified type of this method, if such an annotation is
 197      * present.
 198      *
 199      * @param annotationClass the Class object corresponding to the annotation type
 200      * @return this element's annotation for the specified annotation type if present on this
 201      *         method, else {@code null}
 202      */
 203     <T extends Annotation> T getAnnotation(Class<T> annotationClass);
 204 
 205     /**
 206      * Returns an array of arrays that represent the annotations on the formal parameters, in
 207      * declaration order, of this method.
 208      *
 209      * @see Method#getParameterAnnotations()
 210      */
 211     Annotation[][] getParameterAnnotations();
 212 
 213     /**
 214      * Returns an array of {@link Type} objects that represent the formal parameter types, in
 215      * declaration order, of this method.
 216      *
 217      * @see Method#getGenericParameterTypes()
 218      */
 219     Type[] getGenericParameterTypes();
 220 
 221     /**
 222      * Returns {@code true} if this method is not excluded from inlining and has associated Java
 223      * bytecodes (@see {@link ResolvedJavaMethod#hasBytecodes()}).
 224      */
 225     boolean canBeInlined();
 226 
 227     /**
 228      * Returns {@code true} if the inlining of this method should be forced.
 229      */
 230     boolean shouldBeInlined();
 231 
 232     /**
 233      * Returns the LineNumberTable of this method or null if this method does not have a line
 234      * numbers table.
 235      */
 236     LineNumberTable getLineNumberTable();
 237 
 238     /**
 239      * Returns the local variable table of this method or null if this method does not have a local
 240      * variable table.
 241      */
 242     LocalVariableTable getLocalVariableTable();
 243 
 244     /**
 245      * Invokes the underlying method represented by this object, on the specified object with the
 246      * specified parameters. This method is similar to a reflective method invocation by
 247      * {@link Method#invoke}.
 248      *
 249      * @param receiver The receiver for the invocation, or {@code null} if it is a static method.
 250      * @param arguments The arguments for the invocation.
 251      * @return The value returned by the method invocation, or {@code null} if the return type is
 252      *         {@code void}.
 253      */
 254     JavaConstant invoke(JavaConstant receiver, JavaConstant[] arguments);
 255 
 256     /**
 257      * Gets the encoding of (that is, a constant representing the value of) this method.
 258      *
 259      * @return a constant representing a reference to this method
 260      */
 261     Constant getEncoding();
 262 
 263     /**
 264      * Checks if this method is present in the virtual table for subtypes of the specified
 265      * {@linkplain ResolvedJavaType type}.
 266      *
 267      * @return true is this method is present in the virtual table for subtypes of this type.
 268      */
 269     boolean isInVirtualMethodTable(ResolvedJavaType resolved);
 270 
 271     /**
 272      * Gets the annotation of a particular type for a formal parameter of this method.
 273      *
 274      * @param annotationClass the Class object corresponding to the annotation type
 275      * @param parameterIndex the index of a formal parameter of {@code method}
 276      * @return the annotation of type {@code annotationClass} for the formal parameter present, else
 277      *         null
 278      * @throws IndexOutOfBoundsException if {@code parameterIndex} does not denote a formal
 279      *             parameter
 280      */
 281     default <T extends Annotation> T getParameterAnnotation(Class<T> annotationClass, int parameterIndex) {
 282         if (parameterIndex >= 0) {
 283             Annotation[][] parameterAnnotations = getParameterAnnotations();
 284             for (Annotation a : parameterAnnotations[parameterIndex]) {
 285                 if (a.annotationType() == annotationClass) {
 286                     return annotationClass.cast(a);
 287                 }
 288             }
 289         }
 290         return null;
 291     }
 292 
 293     default JavaType[] toParameterTypes() {
 294         JavaType receiver = isStatic() || isConstructor() ? null : getDeclaringClass();
 295         return getSignature().toParameterTypes(receiver);
 296     }
 297 
 298     /**
 299      * Gets the annotations of a particular type for the formal parameters of this method.
 300      *
 301      * @param annotationClass the Class object corresponding to the annotation type
 302      * @return the annotation of type {@code annotationClass} (if any) for each formal parameter
 303      *         present
 304      */
 305     @SuppressWarnings("unchecked")
 306     default <T extends Annotation> T[] getParameterAnnotations(Class<T> annotationClass) {
 307         Annotation[][] parameterAnnotations = getParameterAnnotations();
 308         T[] result = (T[]) Array.newInstance(annotationClass, parameterAnnotations.length);
 309         for (int i = 0; i < parameterAnnotations.length; i++) {
 310             for (Annotation a : parameterAnnotations[i]) {
 311                 if (a.annotationType() == annotationClass) {
 312                     result[i] = annotationClass.cast(a);
 313                 }
 314             }
 315         }
 316         return result;
 317     }
 318 
 319     /**
 320      * Checks whether the method has bytecodes associated with it. Methods without bytecodes are
 321      * either abstract or native methods.
 322      *
 323      * @return whether the definition of this method is Java bytecodes
 324      */
 325     default boolean hasBytecodes() {
 326         return isConcrete() && !isNative();
 327     }
 328 
 329     /**
 330      * Checks whether the method has a receiver parameter - i.e., whether it is not static.
 331      *
 332      * @return whether the method has a receiver parameter
 333      */
 334     default boolean hasReceiver() {
 335         return !isStatic();
 336     }
 337 
 338     /**
 339      * Determines if this method is {@link java.lang.Object#Object()}.
 340      */
 341     default boolean isJavaLangObjectInit() {
 342         return getDeclaringClass().isJavaLangObject() && getName().equals("<init>");
 343     }
 344 
 345     SpeculationLog getSpeculationLog();
 346 
 347     /**
 348      * Determines if the method identified by its holder and name is a <a
 349      * href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.9">signature
 350      * polymorphic</a> method.
 351      */
 352     static boolean isSignaturePolymorphic(JavaType holder, String name, MetaAccessProvider metaAccess) {
 353         if (!holder.getName().equals("Ljava/lang/invoke/MethodHandle;")) {
 354             return false;
 355         }
 356         ResolvedJavaType methodHandleType = metaAccess.lookupJavaType(MethodHandle.class);
 357         Signature signature = metaAccess.parseMethodDescriptor("([Ljava/lang/Object;)Ljava/lang/Object;");
 358         ResolvedJavaMethod method = methodHandleType.findMethod(name, signature);
 359         if (method == null) {
 360             return false;
 361         }
 362         return method.isNative() && method.isVarArgs();
 363     }
 364 }