This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[ecj] Cache Annotations
- From: Andrew Haley <aph at redhat dot com>
- To: java-patches at gcc dot gnu dot org
- Date: Wed, 20 Dec 2006 15:38:56 +0000
- Subject: [ecj] Cache Annotations
This is an optimization for annotation handling. Once created, all
annotations are kept in a cache by the class loader.
Andrew.
2006-12-20 Andrew Haley <aph@redhat.com>
* java/lang/natClass.cc (getDeclaredAnnotations): Call
ClassLoader.getDeclaredAnnotations and
ClassLoader.putDeclaredAnnotations.
(_Jv_IsAssignableFrom): Another shortcut for a.type == b.type.
* java/lang/ClassLoader.java (AnnotationsKey): New class.
(getDeclaredAnnotations, putDeclaredAnnotations): New.
Index: java/lang/ClassLoader.java
===================================================================
--- java/lang/ClassLoader.java (revision 120053)
+++ java/lang/ClassLoader.java (working copy)
@@ -55,6 +55,9 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.lang.annotation.Annotation;
+
/**
* The ClassLoader is a way of customizing the way Java gets its classes
* and loads them into memory. The verifier and other standard Java things
@@ -159,6 +162,85 @@
static final ClassLoader systemClassLoader =
VMClassLoader.getSystemClassLoader();
+ /**
+ * This cache maps from a Class to its associated annotations. It's
+ * declared here so that when this class loader becomes unreachable,
+ * so will the corresponding cache.
+ */
+
+ private final ConcurrentHashMap<AnnotationsKey,Object[]>
+ declaredAnnotations
+ = new ConcurrentHashMap<AnnotationsKey,Object[]>();
+
+ static final class AnnotationsKey
+ {
+ final int /* jv_attr_type */ member_type;
+ final int member_index;
+ final int /* jv_attr_kind */ kind_req;
+ final Class declaringClass;
+ final int hashCode;
+
+ public AnnotationsKey (Class declaringClass,
+ int member_type,
+ int member_index,
+ int kind_req)
+ {
+ this.member_type = member_type;
+ this.member_index = member_index;
+ this.kind_req = kind_req;
+ this.declaringClass = declaringClass;
+ hashCode = (member_type ^ member_index ^ kind_req
+ ^ declaringClass.hashCode());
+ }
+
+ public boolean equals(Object obj)
+ {
+ AnnotationsKey other = (AnnotationsKey)obj;
+ return (this.member_type == other.member_type
+ && this.member_index == other.member_index
+ && this.kind_req == other.kind_req
+ && this.declaringClass == other.declaringClass);
+ }
+
+ public int hashCode()
+ {
+ return hashCode;
+ }
+
+ public static final Annotation[] NIL = new Annotation[0];
+ }
+
+ final Object[] getDeclaredAnnotations(Class declaringClass,
+ int member_type,
+ int member_index,
+ int kind_req)
+ {
+ Object[] result
+ = declaredAnnotations.get (new AnnotationsKey
+ (declaringClass,
+ member_type,
+ member_index,
+ kind_req));
+ if (result != AnnotationsKey.NIL && result != null)
+ return (Object[])result.clone();
+ return null;
+ }
+
+ final Object[] putDeclaredAnnotations(Class declaringClass,
+ int member_type,
+ int member_index,
+ int kind_req,
+ Object[] annotations)
+ {
+ declaredAnnotations.put
+ (new AnnotationsKey
+ (declaringClass, member_type,
+ member_index, kind_req),
+ annotations == null ? AnnotationsKey.NIL : annotations);
+
+ return annotations == null ? null : (Object[])annotations.clone();
+ }
+
static
{
// Find out if we have to install a default security manager. Note
Index: java/lang/natClass.cc
===================================================================
--- java/lang/natClass.cc (revision 120053)
+++ java/lang/natClass.cc (working copy)
@@ -1311,13 +1311,23 @@
jint member_index,
jint /* jv_attr_kind */ kind_req)
{
- // FIXME: could cache the value here...
+ using namespace java::lang::annotation;
+ jobjectArray result;
unsigned char *bytes = reflection_data;
if (bytes == NULL)
return 0;
- while (true)
+ ClassLoader *trueLoader = loader;
+ if (trueLoader == NULL)
+ trueLoader = (ClassLoader *)VMClassLoader::bootLoader;
+
+ result = (loader->getDeclaredAnnotations
+ (this, member_type, member_index, kind_req));
+ if (result)
+ return result;
+
+ for (;;)
{
int type = read_u1 (bytes);
if (type == JV_DONE_ATTR)
@@ -1345,12 +1355,16 @@
}
}
- // FIXME: could cache here. If we do then we have to clone any
- // array result.
if (kind_req == JV_PARAMETER_ANNOTATIONS_KIND)
- return parseParameterAnnotations (this, &this->constants, bytes, next);
- return parseAnnotations (this, &this->constants, bytes, next);
+ result = ((parseParameterAnnotations
+ (this, &this->constants, bytes, next)));
+ else
+ result = ((parseAnnotations (this, &this->constants, bytes, next)));
+ break;
}
+
+ return (loader->putDeclaredAnnotations
+ (this, member_type, member_index, kind_req, result));
}
jobjectArray
@@ -1729,6 +1743,9 @@
source = source->getComponentType();
}
+ if (source == target)
+ return true;
+
if (target->isInterface())
{
// Abstract classes have no IDT, and IDTs provide no way to check