1 /*
   2  * Copyright (c) 2009, 2016, 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.vm.ci.meta;
  24 
  25 import java.lang.reflect.AnnotatedElement;
  26 
  27 import jdk.vm.ci.meta.Assumptions.AssumptionResult;
  28 
  29 /**
  30  * Represents a resolved Java type. Types include primitives, objects, {@code void}, and arrays
  31  * thereof. Types, like fields and methods, are resolved through {@link ConstantPool constant pools}
  32  * .
  33  */
  34 public interface ResolvedJavaType extends JavaType, ModifiersProvider, AnnotatedElement {
  35     /**
  36      * Checks whether this type has a finalizer method.
  37      *
  38      * @return {@code true} if this class has a finalizer
  39      */
  40     boolean hasFinalizer();
  41 
  42     /**
  43      * Checks whether this type has any finalizable subclasses so far. Any decisions based on this
  44      * information require the registration of a dependency, since this information may change.
  45      *
  46      * @return {@code true} if this class has any subclasses with finalizers
  47      */
  48     AssumptionResult<Boolean> hasFinalizableSubclass();
  49 
  50     /**
  51      * Checks whether this type is an interface.
  52      *
  53      * @return {@code true} if this type is an interface
  54      */
  55     boolean isInterface();
  56 
  57     /**
  58      * Checks whether this type is an instance class.
  59      *
  60      * @return {@code true} if this type is an instance class
  61      */
  62     boolean isInstanceClass();
  63 
  64     /**
  65      * Checks whether this type is primitive.
  66      *
  67      * @return {@code true} if this type is primitive
  68      */
  69     boolean isPrimitive();
  70 
  71     /*
  72      * The setting of the final bit for types is a bit confusing since arrays are marked as final.
  73      * This method provides a semantically equivalent test that appropriate for types.
  74      */
  75     default boolean isLeaf() {
  76         return getElementalType().isFinalFlagSet();
  77     }
  78 
  79     /**
  80      * Checks whether this type is initialized. If a type is initialized it implies that it was
  81      * {@link #isLinked() linked} and that the static initializer has run.
  82      *
  83      * @return {@code true} if this type is initialized
  84      */
  85     boolean isInitialized();
  86 
  87     /**
  88      * Initializes this type.
  89      */
  90     void initialize();
  91 
  92     /**
  93      * Checks whether this type is linked and verified. When a type is linked the static initializer
  94      * has not necessarily run. An {@link #isInitialized() initialized} type is always linked.
  95      *
  96      * @return {@code true} if this type is linked
  97      */
  98     boolean isLinked();
  99 
 100     /**
 101      * Determines if this type is either the same as, or is a superclass or superinterface of, the
 102      * type represented by the specified parameter. This method is identical to
 103      * {@link Class#isAssignableFrom(Class)} in terms of the value return for this type.
 104      */
 105     boolean isAssignableFrom(ResolvedJavaType other);
 106 
 107     /**
 108      * Returns true if this type is exactly the type {@link java.lang.Object}.
 109      */
 110     default boolean isJavaLangObject() {
 111         // Removed assertion due to https://bugs.eclipse.org/bugs/show_bug.cgi?id=434442
 112         return getSuperclass() == null && !isInterface() && getJavaKind() == JavaKind.Object;
 113     }
 114 
 115     /**
 116      * Checks whether the specified object is an instance of this type.
 117      *
 118      * @param obj the object to test
 119      * @return {@code true} if the object is an instance of this type
 120      */
 121     boolean isInstance(JavaConstant obj);
 122 
 123     /**
 124      * Gets the super class of this type. If this type represents either the {@code Object} class,
 125      * an interface, a primitive type, or void, then null is returned. If this object represents an
 126      * array class then the type object representing the {@code Object} class is returned.
 127      */
 128     ResolvedJavaType getSuperclass();
 129 
 130     /**
 131      * Gets the interfaces implemented or extended by this type. This method is analogous to
 132      * {@link Class#getInterfaces()} and as such, only returns the interfaces directly implemented
 133      * or extended by this type.
 134      */
 135     ResolvedJavaType[] getInterfaces();
 136 
 137     /**
 138      * Gets the single implementor of this type. Calling this method on a non-interface type causes
 139      * an exception.
 140      * <p>
 141      * If the compiler uses the result of this method for its compilation, the usage must be guarded
 142      * because the verifier can not guarantee that the assigned type really implements this
 143      * interface. Additionally, class loading can invalidate the result of this method.
 144      *
 145      * @return {@code null} if there is no implementor, the implementor if there is only one, or
 146      *         {@code this} if there are more than one.
 147      */
 148     ResolvedJavaType getSingleImplementor();
 149 
 150     /**
 151      * Walks the class hierarchy upwards and returns the least common class that is a superclass of
 152      * both the current and the given type.
 153      *
 154      * @return the least common type that is a super type of both the current and the given type, or
 155      *         {@code null} if primitive types are involved.
 156      */
 157     ResolvedJavaType findLeastCommonAncestor(ResolvedJavaType otherType);
 158 
 159     /**
 160      * Attempts to get a leaf concrete subclass of this type.
 161      * <p>
 162      * For an {@linkplain #isArray() array} type A, the leaf concrete subclass is A if the
 163      * {@linkplain #getElementalType() elemental} type of A is final (which includes primitive
 164      * types). Otherwise {@code null} is returned for A.
 165      * <p>
 166      * For a non-array type T, the result is the leaf concrete type in the current hierarchy of T.
 167      * <p>
 168      * A runtime may decide not to manage or walk a large hierarchy and so the result is
 169      * conservative. That is, a non-null result is guaranteed to be the leaf concrete class in T's
 170      * hierarchy <b>at the current point in time</b> but a null result does not necessarily imply
 171      * that there is no leaf concrete class in T's hierarchy.
 172      * <p>
 173      * If the compiler uses the result of this method for its compilation, it must register the
 174      * {@link AssumptionResult} in its {@link Assumptions} because dynamic class loading can
 175      * invalidate the result of this method.
 176      *
 177      * @return an {@link AssumptionResult} containing the leaf concrete subclass for this type as
 178      *         described above
 179      */
 180     AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype();
 181 
 182     ResolvedJavaType getComponentType();
 183 
 184     default ResolvedJavaType getElementalType() {
 185         ResolvedJavaType t = this;
 186         while (t.isArray()) {
 187             t = t.getComponentType();
 188         }
 189         return t;
 190     }
 191 
 192     ResolvedJavaType getArrayClass();
 193 
 194     /**
 195      * Resolves the method implementation for virtual dispatches on objects of this dynamic type.
 196      * This resolution process only searches "up" the class hierarchy of this type. A broader search
 197      * that also walks "down" the hierarchy is implemented by
 198      * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}. For interface types it returns null
 199      * since no concrete object can be an interface.
 200      *
 201      * @param method the method to select the implementation of
 202      * @param callerType the caller or context type used to perform access checks
 203      * @return the link-time resolved method (might be abstract) or {@code null} if it is either a
 204      *         signature polymorphic method or can not be linked.
 205      */
 206     ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType);
 207 
 208     /**
 209      * A convenience wrapper for {@link #resolveMethod(ResolvedJavaMethod, ResolvedJavaType)} that
 210      * only returns non-abstract methods.
 211      *
 212      * @param method the method to select the implementation of
 213      * @param callerType the caller or context type used to perform access checks
 214      * @return the concrete method that would be selected at runtime, or {@code null} if there is no
 215      *         concrete implementation of {@code method} in this type or any of its superclasses
 216      */
 217     default ResolvedJavaMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
 218         ResolvedJavaMethod resolvedMethod = resolveMethod(method, callerType);
 219         if (resolvedMethod == null || resolvedMethod.isAbstract()) {
 220             return null;
 221         }
 222         return resolvedMethod;
 223     }
 224 
 225     /**
 226      * Given a {@link ResolvedJavaMethod} A, returns a concrete {@link ResolvedJavaMethod} B that is
 227      * the only possible unique target for a virtual call on A(). Returns {@code null} if either no
 228      * such concrete method or more than one such method exists. Returns the method A if A is a
 229      * concrete method that is not overridden.
 230      * <p>
 231      * If the compiler uses the result of this method for its compilation, it must register an
 232      * assumption because dynamic class loading can invalidate the result of this method.
 233      *
 234      * @param method the method A for which a unique concrete target is searched
 235      * @return the unique concrete target or {@code null} if no such target exists or assumptions
 236      *         are not supported by this runtime
 237      */
 238     AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method);
 239 
 240     /**
 241      * Returns the instance fields of this class, including
 242      * {@linkplain ResolvedJavaField#isInternal() internal} fields. A zero-length array is returned
 243      * for array and primitive types. The order of fields returned by this method is stable. That
 244      * is, for a single JVM execution the same order is returned each time this method is called. It
 245      * is also the "natural" order, which means that the JVM would expect the fields in this order
 246      * if no specific order is given.
 247      *
 248      * @param includeSuperclasses if true, then instance fields for the complete hierarchy of this
 249      *            type are included in the result
 250      * @return an array of instance fields
 251      */
 252     ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses);
 253 
 254     /**
 255      * Returns the static fields of this class, including {@linkplain ResolvedJavaField#isInternal()
 256      * internal} fields. A zero-length array is returned for array and primitive types. The order of
 257      * fields returned by this method is stable. That is, for a single JVM execution the same order
 258      * is returned each time this method is called.
 259      */
 260     ResolvedJavaField[] getStaticFields();
 261 
 262     /**
 263      * Returns the instance field of this class (or one of its super classes) at the given offset,
 264      * or {@code null} if there is no such field.
 265      *
 266      * @param offset the offset of the field to look for
 267      * @return the field with the given offset, or {@code null} if there is no such field.
 268      */
 269     ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedKind);
 270 
 271     /**
 272      * Returns name of source file of this type.
 273      */
 274     String getSourceFileName();
 275 
 276     /**
 277      * Returns {@code true} if the type is a local type.
 278      */
 279     boolean isLocal();
 280 
 281     /**
 282      * Returns {@code true} if the type is a member type.
 283      */
 284     boolean isMember();
 285 
 286     /**
 287      * Returns the enclosing type of this type, if it exists, or {@code null}.
 288      */
 289     ResolvedJavaType getEnclosingType();
 290 
 291     /**
 292      * Returns an array reflecting all the constructors declared by this type. This method is
 293      * similar to {@link Class#getDeclaredConstructors()} in terms of returned constructors.
 294      */
 295     ResolvedJavaMethod[] getDeclaredConstructors();
 296 
 297     /**
 298      * Returns an array reflecting all the methods declared by this type. This method is similar to
 299      * {@link Class#getDeclaredMethods()} in terms of returned methods.
 300      */
 301     ResolvedJavaMethod[] getDeclaredMethods();
 302 
 303     /**
 304      * Returns the {@code <clinit>} method for this class if there is one.
 305      */
 306     ResolvedJavaMethod getClassInitializer();
 307 
 308     default ResolvedJavaMethod findMethod(String name, Signature signature) {
 309         for (ResolvedJavaMethod method : getDeclaredMethods()) {
 310             if (method.getName().equals(name) && method.getSignature().equals(signature)) {
 311                 return method;
 312             }
 313         }
 314         return null;
 315     }
 316 
 317     /**
 318      * Returns true if this type is {@link Cloneable} and can be safely cloned by creating a normal
 319      * Java allocation and populating it from the fields returned by
 320      * {@link #getInstanceFields(boolean)}. Some types may require special handling by the platform
 321      * so they would to go through the normal {@link Object#clone} path.
 322      */
 323     boolean isCloneableWithAllocation();
 324 }