diff options
author | Vladimir Marko <vmarko@google.com> | 2015-04-09 14:11:12 +0100 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2015-04-10 18:46:16 +0100 |
commit | 3f58d2cbf86775ac97bddc1a8a0a9658b498d282 (patch) | |
tree | dad85c3f4d8609ea3c2cd828536f67a2f7753c9e /libart | |
parent | 227afa2784b1a78504de22730161b65cc7093fc6 (diff) | |
download | libcore-3f58d2cbf86775ac97bddc1a8a0a9658b498d282.zip libcore-3f58d2cbf86775ac97bddc1a8a0a9658b498d282.tar.gz libcore-3f58d2cbf86775ac97bddc1a8a0a9658b498d282.tar.bz2 |
Avoid using dex cache array pointers in libart.
In preparation for making dex cache arrays native, avoid
using them in Java code.
This causes a performance regression for our reflection
benchmarks. Class_getDeclaredMethod and Class_getMethod
take an up to 30% hit, measured using the Quick compiler.
We accept this hit at this stage and we will tune the
performance after we're done with the larger effort.
Companion art/ change:
https://android-review.googlesource.com/146068
Bug: 20134538
Change-Id: Ibbef3b50043a1311cd40723ed42e1f1c609b8fc1
Diffstat (limited to 'libart')
-rw-r--r-- | libart/src/main/java/java/lang/Class.java | 27 | ||||
-rw-r--r-- | libart/src/main/java/java/lang/DexCache.java | 4 | ||||
-rw-r--r-- | libart/src/main/java/java/lang/reflect/ArtMethod.java | 69 | ||||
-rw-r--r-- | libart/src/main/java/java/lang/reflect/Method.java | 19 |
4 files changed, 50 insertions, 69 deletions
diff --git a/libart/src/main/java/java/lang/Class.java b/libart/src/main/java/java/lang/Class.java index 37b1d7d..5db7cc9 100644 --- a/libart/src/main/java/java/lang/Class.java +++ b/libart/src/main/java/java/lang/Class.java @@ -457,10 +457,10 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @hide */ public String getDexCacheString(Dex dex, int dexStringIndex) { - String s = dexCacheStrings[dexStringIndex]; + String s = dexCache.getResolvedString(dexStringIndex); if (s == null) { s = dex.strings().get(dexStringIndex).intern(); - dexCacheStrings[dexStringIndex] = s; + dexCache.setResolvedString(dexStringIndex, s); } return s; } @@ -472,13 +472,12 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe * @hide */ public Class<?> getDexCacheType(Dex dex, int dexTypeIndex) { - Class<?>[] dexCacheResolvedTypes = dexCache.resolvedTypes; - Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex]; + Class<?> resolvedType = dexCache.getResolvedType(dexTypeIndex); if (resolvedType == null) { int descriptorIndex = dex.typeIds().get(dexTypeIndex); String descriptor = getDexCacheString(dex, descriptorIndex); resolvedType = InternalNames.getClass(getClassLoader(), descriptor); - dexCacheResolvedTypes[dexTypeIndex] = resolvedType; + dexCache.setResolvedType(dexTypeIndex, resolvedType); } return resolvedType; } @@ -707,11 +706,12 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe ArtMethod artMethodResult = null; if (virtualMethods != null) { for (ArtMethod m : virtualMethods) { - String methodName = ArtMethod.getMethodName(m); + ArtMethod nonProxyMethod = Class.findOverriddenMethodIfProxy(m); + String methodName = ArtMethod.getMethodName(nonProxyMethod); if (!name.equals(methodName)) { continue; } - if (!ArtMethod.equalMethodParameters(m, args)) { + if (!ArtMethod.equalMethodParameters(nonProxyMethod, args)) { continue; } int modifiers = m.getAccessFlags(); @@ -731,11 +731,12 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe if (Modifier.isConstructor(modifiers)) { continue; } - String methodName = ArtMethod.getMethodName(m); + ArtMethod nonProxyMethod = Class.findOverriddenMethodIfProxy(m); + String methodName = ArtMethod.getMethodName(nonProxyMethod); if (!name.equals(methodName)) { continue; } - if (!ArtMethod.equalMethodParameters(m, args)) { + if (!ArtMethod.equalMethodParameters(nonProxyMethod, args)) { continue; } if ((modifiers & skipModifiers) == 0) { @@ -754,6 +755,14 @@ public final class Class<T> implements Serializable, AnnotatedElement, GenericDe } /** + * Returns the overridden method if the {@code method} is a proxy method, + * otherwise returns the {@code method}. + * + * @hide + */ + public static native ArtMethod findOverriddenMethodIfProxy(ArtMethod method); + + /** * Returns an array containing {@code Method} objects for all methods * declared in the class represented by this {@code Class}. If there are no * methods or if this {@code Class} represents an array class, a primitive diff --git a/libart/src/main/java/java/lang/DexCache.java b/libart/src/main/java/java/lang/DexCache.java index e4caffa..00b8af9 100644 --- a/libart/src/main/java/java/lang/DexCache.java +++ b/libart/src/main/java/java/lang/DexCache.java @@ -89,6 +89,10 @@ final class DexCache { return result; } + native Class<?> getResolvedType(int typeIndex); + native String getResolvedString(int stringIndex); + native void setResolvedType(int typeIndex, Class<?> type); + native void setResolvedString(int stringIndex, String string); private native Dex getDexNative(); } diff --git a/libart/src/main/java/java/lang/reflect/ArtMethod.java b/libart/src/main/java/java/lang/reflect/ArtMethod.java index 95e03c6..3abcb60 100644 --- a/libart/src/main/java/java/lang/reflect/ArtMethod.java +++ b/libart/src/main/java/java/lang/reflect/ArtMethod.java @@ -76,7 +76,7 @@ public final class ArtMethod { /** Only created by ART directly. */ private ArtMethod() {} - Class getDeclaringClass() { + public Class getDeclaringClass() { return declaringClass; } @@ -89,11 +89,11 @@ public final class ArtMethod { } public static String getMethodName(ArtMethod artMethod) { - artMethod = artMethod.findOverriddenMethodIfProxy(); - Dex dex = artMethod.getDeclaringClass().getDex(); + Class<?> declClass = artMethod.getDeclaringClass(); + Dex dex = declClass.getDex(); int nameIndex = dex.nameIndexFromMethodIndex(artMethod.getDexMethodIndex()); // Note, in the case of a Proxy the dex cache strings are equal. - return artMethod.getDexCacheString(dex, nameIndex); + return declClass.getDexCacheString(dex, nameIndex); } /** @@ -102,13 +102,14 @@ public final class ArtMethod { * @hide */ public static boolean equalConstructorParameters(ArtMethod artMethod, Class<?>[] params) { - Dex dex = artMethod.getDeclaringClass().getDex(); + Class<?> declClass = artMethod.getDeclaringClass(); + Dex dex = declClass.getDex(); short[] types = dex.parameterTypeIndicesFromMethodIndex(artMethod.getDexMethodIndex()); if (types.length != params.length) { return false; } for (int i = 0; i < types.length; i++) { - if (artMethod.getDexCacheType(dex, types[i]) != params[i]) { + if (declClass.getDexCacheType(dex, types[i]) != params[i]) { return false; } } @@ -121,11 +122,12 @@ public final class ArtMethod { * @hide */ public static boolean equalMethodParameters(ArtMethod artMethod, Class<?>[] params) { - return equalConstructorParameters(artMethod.findOverriddenMethodIfProxy(), params); + return equalConstructorParameters(artMethod, params); } Class<?>[] getParameterTypes() { - Dex dex = getDeclaringClass().getDex(); + Class<?> declClass = getDeclaringClass(); + Dex dex = declClass.getDex(); short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); if (types.length == 0) { return EmptyArray.CLASS; @@ -133,16 +135,17 @@ public final class ArtMethod { Class<?>[] parametersArray = new Class[types.length]; for (int i = 0; i < types.length; i++) { // Note, in the case of a Proxy the dex cache types are equal. - parametersArray[i] = getDexCacheType(dex, types[i]); + parametersArray[i] = declClass.getDexCacheType(dex, types[i]); } return parametersArray; } Class<?> getReturnType() { - Dex dex = declaringClass.getDex(); + Class<?> declClass = getDeclaringClass(); + Dex dex = declClass.getDex(); int returnTypeIndex = dex.returnTypeIndexFromMethodIndex(dexMethodIndex); // Note, in the case of a Proxy the dex cache types are equal. - return getDexCacheType(dex, returnTypeIndex); + return declClass.getDexCacheType(dex, returnTypeIndex); } /** @@ -151,11 +154,12 @@ public final class ArtMethod { * @hide */ int compareParameters(Class<?>[] params) { - Dex dex = getDeclaringClass().getDex(); + Class<?> declClass = getDeclaringClass(); + Dex dex = declClass.getDex(); short[] types = dex.parameterTypeIndicesFromMethodIndex(dexMethodIndex); int length = Math.min(types.length, params.length); for (int i = 0; i < length; i++) { - Class<?> aType = getDexCacheType(dex, types[i]); + Class<?> aType = declClass.getDexCacheType(dex, types[i]); Class<?> bType = params[i]; if (aType != bType) { int comparison = aType.getName().compareTo(bType.getName()); @@ -170,43 +174,4 @@ public final class ArtMethod { Annotation[][] getParameterAnnotations() { return AnnotationAccess.getParameterAnnotations(declaringClass, dexMethodIndex); } - - /** - * Returns a string from the dex cache, computing the string from the dex file if necessary. - * Note this method replicates {@link java.lang.Class#getDexCacheString(Dex, int)}, but in - * Method we can avoid one indirection. - */ - private String getDexCacheString(Dex dex, int dexStringIndex) { - return declaringClass.getDexCacheString(dex, dexStringIndex); - } - - /** - * Returns a resolved type from the dex cache, computing the string from the dex file if - * necessary. Note this method delegates to {@link java.lang.Class#getDexCacheType(Dex, int)}, - * but in Method we can avoid one indirection. - */ - private Class<?> getDexCacheType(Dex dex, int dexTypeIndex) { - Class<?> resolvedType = dexCacheResolvedTypes[dexTypeIndex]; - if (resolvedType == null) { - resolvedType = declaringClass.getDexCacheType(dex, dexTypeIndex); - } - return resolvedType; - } - - /** - * Returns the {@code ArtMethod} that this method overrides for - * proxy methods, otherwise returns this method. Used to determine - * the interface method overridden by a proxy method (as the proxy - * method doesn't directly support operations such as {@link - * Method#getName}). - */ - ArtMethod findOverriddenMethodIfProxy() { - if (declaringClass.isProxy()) { - // Proxy method's declaring class' dex cache refers to that of Proxy. The local cache in - // Method refers to the original interface's dex cache and is ensured to be resolved by - // proxy generation. - return dexCacheResolvedMethods[dexMethodIndex]; - } - return this; - } } diff --git a/libart/src/main/java/java/lang/reflect/Method.java b/libart/src/main/java/java/lang/reflect/Method.java index f0e4f5c..c70e34e 100644 --- a/libart/src/main/java/java/lang/reflect/Method.java +++ b/libart/src/main/java/java/lang/reflect/Method.java @@ -57,8 +57,8 @@ public final class Method extends AbstractMethod implements GenericDeclaration, } int comparison = a.getName().compareTo(b.getName()); if (comparison == 0) { - comparison = a.artMethod.findOverriddenMethodIfProxy().compareParameters( - b.getParameterTypes()); + comparison = Class.findOverriddenMethodIfProxy(a.artMethod).compareParameters( + Class.findOverriddenMethodIfProxy(b.artMethod).getParameterTypes()); if (comparison == 0) { // This is necessary for methods that have covariant return types. Class<?> aReturnType = a.getReturnType(); @@ -136,7 +136,8 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @return the name of this method */ @Override public String getName() { - return ArtMethod.getMethodName(artMethod); + ArtMethod nonProxyMethod = Class.findOverriddenMethodIfProxy(artMethod); + return ArtMethod.getMethodName(nonProxyMethod); } /** @@ -171,7 +172,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @return the parameter types */ @Override public Class<?>[] getParameterTypes() { - return artMethod.findOverriddenMethodIfProxy().getParameterTypes(); + return Class.findOverriddenMethodIfProxy(artMethod).getParameterTypes(); } /** @@ -181,7 +182,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @return the return type */ public Class<?> getReturnType() { - return artMethod.findOverriddenMethodIfProxy().getReturnType(); + return Class.findOverriddenMethodIfProxy(artMethod).getReturnType(); } /** @@ -209,8 +210,10 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @hide needed by Proxy */ boolean equalNameAndParameters(Method m) { - return getName().equals(m.getName()) && - ArtMethod.equalMethodParameters(artMethod,m.getParameterTypes()); + ArtMethod nonProxyThis = Class.findOverriddenMethodIfProxy(this.artMethod); + ArtMethod nonProxyM = Class.findOverriddenMethodIfProxy(m.artMethod); + return ArtMethod.getMethodName(nonProxyThis).equals(ArtMethod.getMethodName(nonProxyM)) && + ArtMethod.equalMethodParameters(nonProxyThis, nonProxyM.getParameterTypes()); } /** @@ -310,7 +313,7 @@ public final class Method extends AbstractMethod implements GenericDeclaration, * @return an array of arrays of {@code Annotation} instances */ public Annotation[][] getParameterAnnotations() { - return artMethod.findOverriddenMethodIfProxy().getParameterAnnotations(); + return Class.findOverriddenMethodIfProxy(artMethod).getParameterAnnotations(); } /** |