diff options
author | Neil Fuller <nfuller@google.com> | 2014-03-26 16:59:44 +0000 |
---|---|---|
committer | Neil Fuller <nfuller@google.com> | 2014-03-28 11:19:46 +0000 |
commit | 08da684abe6d5515a9c760a3a33af4f8b426095d (patch) | |
tree | ab1d757261bc97a6b64cb68c4d6c232ec901b4b4 /luni/src | |
parent | f9901b2d274fdc2aab890c1e51e09042605b1370 (diff) | |
download | libcore-08da684abe6d5515a9c760a3a33af4f8b426095d.zip libcore-08da684abe6d5515a9c760a3a33af4f8b426095d.tar.gz libcore-08da684abe6d5515a9c760a3a33af4f8b426095d.tar.bz2 |
Improve the performance of Annotation checks
In the circumstance where the annotated element (field/
method/constructor/class) was loaded from a different Dex file
than the annotation:
The previous code would perform a binary
search to determine the type ID of the annotation in the Dex
file of the annotated element. That type ID would then be
compared against the type IDs of annotations present on the
annotated element. The binary search was quite expensive: it
involved various indirections, many small native method calls
and temporary String creation.
Instead, the code now compares the names of the
annotations on the annotated element with the name of the
annotation being searched for. The name of the annotation
is known and cached on the class and is therefore cheap to
get. The name was previously being used to binary search for
the type ID so this appears to be no less correct.
Also removed some unused methods in order to delete the
getFieldIndex() method.
Change-Id: Ib8fb021ddf1221e3eac983aa87e7aea8174720ef
Diffstat (limited to 'luni/src')
-rw-r--r-- | luni/src/main/java/libcore/reflect/AnnotationAccess.java | 56 |
1 files changed, 12 insertions, 44 deletions
diff --git a/luni/src/main/java/libcore/reflect/AnnotationAccess.java b/luni/src/main/java/libcore/reflect/AnnotationAccess.java index d63ad30..2a72c18 100644 --- a/luni/src/main/java/libcore/reflect/AnnotationAccess.java +++ b/luni/src/main/java/libcore/reflect/AnnotationAccess.java @@ -16,7 +16,6 @@ package libcore.reflect; -import com.android.dex.ClassDef; import com.android.dex.Dex; import com.android.dex.EncodedValueReader; import com.android.dex.FieldId; @@ -167,7 +166,7 @@ public final class AnnotationAccess { */ public static <A extends Annotation> A getDeclaredAnnotation( AnnotatedElement element, Class<A> annotationClass) { - com.android.dex.Annotation a = getMethodAnnotation(element, annotationClass); + com.android.dex.Annotation a = getAnnotation(element, annotationClass); return a != null ? toAnnotationInstance(getDexClass(element), annotationClass, a) : null; @@ -178,10 +177,10 @@ public final class AnnotationAccess { */ public static boolean isDeclaredAnnotationPresent( AnnotatedElement element, Class<? extends Annotation> annotationClass) { - return getMethodAnnotation(element, annotationClass) != null; + return getAnnotation(element, annotationClass) != null; } - private static com.android.dex.Annotation getMethodAnnotation( + private static com.android.dex.Annotation getAnnotation( AnnotatedElement element, Class<? extends Annotation> annotationClass) { int annotationSetOffset = getAnnotationSetOffset(element); if (annotationSetOffset == 0) { @@ -190,17 +189,17 @@ public final class AnnotationAccess { Class<?> dexClass = getDexClass(element); Dex dex = dexClass.getDex(); - int annotationTypeIndex = getTypeIndex(dex, annotationClass); - if (annotationTypeIndex == -1) { - return null; // The dex file doesn't use this annotation. - } - Dex.Section setIn = dex.open(annotationSetOffset); // annotation_set_item + String annotationInternalName = InternalNames.getInternalName(annotationClass); for (int i = 0, size = setIn.readInt(); i < size; i++) { int annotationOffset = setIn.readInt(); Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item + // The internal string name of the annotation is compared here and deliberately not + // the value of annotationClass.getTypeIndex(). The annotationClass may have been + // defined by a different dex file, which would make the indexes incomparable. com.android.dex.Annotation candidate = annotationIn.readAnnotation(); - if (candidate.getTypeIndex() == annotationTypeIndex) { + String candidateInternalName = dex.typeNames().get(candidate.getTypeIndex()); + if (candidateInternalName.equals(annotationInternalName)) { return candidate; } } @@ -268,23 +267,6 @@ public final class AnnotationAccess { : ((Member) element).getDeclaringClass(); } - public static int getFieldIndex(Class<?> declaringClass, Class<?> type, String name) { - Dex dex = declaringClass.getDex(); - int declaringClassIndex = getTypeIndex(dex, declaringClass); - int typeIndex = getTypeIndex(dex, type); - int nameIndex = dex.findStringIndex(name); - FieldId fieldId = new FieldId(dex, declaringClassIndex, typeIndex, nameIndex); - return dex.findFieldIndex(fieldId); - } - - public static int getMethodIndex(Class<?> declaringClass, String name, int protoIndex) { - Dex dex = declaringClass.getDex(); - int declaringClassIndex = getTypeIndex(dex, declaringClass); - int nameIndex = dex.findStringIndex(name); - MethodId methodId = new MethodId(dex, declaringClassIndex, protoIndex, nameIndex); - return dex.findMethodIndex(methodId); - } - /** * Returns the parameter annotations on {@code member}. */ @@ -357,6 +339,8 @@ public final class AnnotationAccess { */ Class<?> annotationClass = method.getDeclaringClass(); + // All lookups of type and string indexes are within the Dex that declares the annotation so + // the indexes can be compared directly. Dex dex = annotationClass.getDex(); EncodedValueReader reader = getOnlyAnnotationValue( dex, annotationClass, "Ldalvik/annotation/AnnotationDefault;"); @@ -365,7 +349,7 @@ public final class AnnotationAccess { } int fieldCount = reader.readAnnotation(); - if (reader.getAnnotationType() != getTypeIndex(dex, annotationClass)) { + if (reader.getAnnotationType() != annotationClass.getDexTypeIndex()) { throw new AssertionError("annotation value type != annotation class"); } @@ -540,22 +524,6 @@ public final class AnnotationAccess { * was derived. */ - /** Find dex's type index for the class c */ - private static int getTypeIndex(Dex dex, Class<?> c) { - if (dex == c.getDex()) { - return c.getDexTypeIndex(); - } - if (dex == null) { - return -1; - } - int typeIndex = dex.findTypeIndex(InternalNames.getInternalName(c)); - if (typeIndex < 0) { - typeIndex = -1; - } - return typeIndex; - } - - private static EncodedValueReader getAnnotationReader( Dex dex, AnnotatedElement element, String annotationName, int expectedFieldCount) { int annotationSetOffset = getAnnotationSetOffset(element); |