This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]