Home | History | Annotate | Download | only in reflect
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 /*
     18  * Copyright (C) 2012 The Android Open Source Project
     19  *
     20  * Licensed under the Apache License, Version 2.0 (the "License");
     21  * you may not use this file except in compliance with the License.
     22  * You may obtain a copy of the License at
     23  *
     24  *      http://www.apache.org/licenses/LICENSE-2.0
     25  *
     26  * Unless required by applicable law or agreed to in writing, software
     27  * distributed under the License is distributed on an "AS IS" BASIS,
     28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     29  * See the License for the specific language governing permissions and
     30  * limitations under the License.
     31  */
     32 
     33 package java.lang.reflect;
     34 
     35 import com.android.dex.Dex;
     36 import java.lang.annotation.Annotation;
     37 import libcore.reflect.AnnotationAccess;
     38 import libcore.util.EmptyArray;
     39 
     40 /**
     41  * This class represents methods and constructors.
     42  * @hide
     43  */
     44 public final class ArtMethod {
     45 
     46     /** Method's declaring class */
     47     private Class<?> declaringClass;
     48     /** Method access flags (modifiers) */
     49     private int accessFlags;
     50     /** DexFile index */
     51     private int methodDexIndex;
     52     /** Dispatch table entry */
     53     private int methodIndex;
     54     /** DexFile offset of CodeItem for this Method */
     55     private int codeItemOffset;
     56     /* ART compiler meta-data */
     57     private int frameSizeInBytes;
     58     private int coreSpillMask;
     59     private int fpSpillMask;
     60     private int mappingTable;
     61     private int gcMap;
     62     private int vmapTable;
     63     /** ART: compiled managed code associated with this Method */
     64     private int entryPointFromCompiledCode;
     65     /** ART: entry point from interpreter associated with this Method */
     66     private int entryPointFromInterpreter;
     67     /** ART: if this is a native method, the native code that will be invoked */
     68     private int nativeMethod;
     69     /* ART: dex cache fast access */
     70     private String[] dexCacheStrings;
     71     Class<?>[] dexCacheResolvedTypes;
     72     private ArtMethod[] dexCacheResolvedMethods;
     73     private Object[] dexCacheInitializedStaticStorage;
     74 
     75     /**
     76      * Only created by art directly.
     77      */
     78     private ArtMethod() {}
     79 
     80     Class getDeclaringClass() {
     81         return declaringClass;
     82     }
     83 
     84     public int getAccessFlags() {
     85         return accessFlags;
     86     }
     87 
     88     int getDexMethodIndex() {
     89         return methodDexIndex;
     90     }
     91 
     92     public static String getMethodName(ArtMethod artMethod) {
     93         artMethod = artMethod.findOverriddenMethodIfProxy();
     94         Dex dex = artMethod.getDeclaringClass().getDex();
     95         int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex());
     96         // Note, in the case of a Proxy the dex cache strings are equal.
     97         return artMethod.getDexCacheString(dex, nameIndex);
     98     }
     99 
    100     /**
    101      * Returns true if the given parameters match those of the method in the given order.
    102      *
    103      * @hide
    104      */
    105     public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) {
    106         Dex dex = artMethod.getDeclaringClass().getDex();
    107         short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex());
    108         if (types.length != params.length) {
    109             return false;
    110         }
    111         for (int i = 0; i < types.length; i++) {
    112             if (artMethod.getDexCacheType(dex, types[i]) != params[i]) {
    113                 return false;
    114             }
    115         }
    116         return true;
    117     }
    118 
    119     /**
    120      * Returns true if the given parameters match those of this method in the given order.
    121      *
    122      * @hide
    123      */
    124     public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) {
    125         return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params);
    126     }
    127 
    128     Class<?>[] getParameterTypes() {
    129         Dex dex = getDeclaringClass().getDex();
    130         short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
    131         if (types.length == 0) {
    132             return EmptyArray.CLASS;
    133         }
    134         Class<?>[] parametersArray = new Class[types.length];
    135         for (int i = 0; i < types.length; i++) {
    136             // Note, in the case of a Proxy the dex cache types are equal.
    137             parametersArray[i] = getDexCacheType(dex, types[i]);
    138         }
    139         return parametersArray;
    140     }
    141 
    142     Class<?> getReturnType() {
    143         Dex dex = declaringClass.getDex();
    144         int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(methodDexIndex);
    145         // Note, in the case of a Proxy the dex cache types are equal.
    146         return getDexCacheType(dex, returnTypeIndex);
    147     }
    148 
    149     /**
    150      * Performs a comparison of the parameters to this method with the given parameters.
    151      *
    152      * @hide
    153      */
    154     int compareParameters(Class<?>[] params) {
    155         Dex dex = getDeclaringClass().getDex();
    156         short[] types = dex.parameterTypeIndicesFromMethodIndex(methodDexIndex);
    157         int length = Math.min(types.length, params.length);
    158         for (int i = 0; i < length; i++) {
    159             Class<?> aType = getDexCacheType(dex, types[i]);
    160             Class<?> bType = params[i];
    161             if (aType != bType) {
    162                 int comparison = aType.getName().compareTo(bType.getName());
    163                 if (comparison != 0) {
    164                     return comparison;
    165                 }
    166             }
    167         }
    168         return types.length - params.length;
    169     }
    170 
    171     Annotation[][] getParameterAnnotations() {
    172         return AnnotationAccess.getParameterAnnotations(declaringClass, methodDexIndex);
    173     }
    174 
    175     /**
    176      * Returns a string from the dex cache, computing the string from the dex file if necessary.
    177      * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in
    178      * Method we can avoid one indirection.
    179      */
    180     private String getDexCacheString(Dex dex, int dexStringIndex) {
    181         String s = (String) dexCacheStrings[dexStringIndex];
    182         if (s == null) {
    183             s = dex.strings().get(dexStringIndex).intern();
    184             dexCacheStrings[dexStringIndex] = s;
    185         }
    186         return s;
    187     }
    188 
    189     /**
    190      * Returns a resolved type from the dex cache, computing the string from the dex file if
    191      * necessary. Note this method delegates to {@link java.lang.Class#getDexCacheType(Dex, int)},
    192      * but in Method we can avoid one indirection.
    193      */
    194     private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) {
    195         Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex];
    196         if (resolvedType == null) {
    197             resolvedType = declaringClass.getDexCacheType(dex, dexTypeIndex);
    198         }
    199         return resolvedType;
    200     }
    201 
    202     /**
    203      * Returns the {@code ArtMethod} that this method overrides for
    204      * proxy methods, otherwise returns this method. Used to determine
    205      * the interface method overridden by a proxy method (as the proxy
    206      * method doesn't directly support operations such as {@link
    207      * Method#getName}).
    208      */
    209     ArtMethod findOverriddenMethodIfProxy() {
    210         if (declaringClass.isProxy()) {
    211             // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in
    212             // Method refers to the original interface's dex cache and is ensured to be resolved by
    213             // proxy generation.
    214             return dexCacheResolvedMethods[methodDexIndex];
    215         }
    216         return this;
    217     }
    218 }
    219