[ecj] Runtime visible annotations

Andrew Haley aph@redhat.com
Wed Nov 1 16:51:00 GMT 2006


This is the last major missing piece of gcj support for Version 5 of
the Java language: runtime visible annotations.

I'll post the runtime library support for this as a separate patch.

Andrew.



2006-11-01  Andrew Haley  <aph@redhat.com>

	* jcf-parse.c (field_offsets, bit_obstack): New variables.
	(jcf_parse): Write end marker to annotation_data.
	(java_parse_file): Create field_offsets bitmap.  Destroy it.
	(annotation_grow, annotation_rewrite_byte) 
	(annotation_rewrite_short, annotation_rewrite_int) 
	(annotation_read_short, annotation_write_byte) 
	(annotation_write_short, annotation_write_int) 
	(handle_long_constant, handle_constant, handle_element_value) 
	(handle_annotation, handle_annotations) 
	(handle_annotation_attribute, rewrite_reflection_indexes) 
	(handle_member_annotations, handle_parameter_annotations) 
	(handle_default_annotation): New functions.
	(HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE) 
	(HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE) 
	(HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE) 
	(HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE) 
	(HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE): New definitions.
	* java-tree.h (enum jv_attr_type, enum jv_attr_kind): New. 
	(TYPE_REFLECTION_DATA): New.
	(TYPE_REFLECTION_DATASIZE): New.
	* jcf.h (enum cpool_tag): Convert a bunch of #define constants to
	an enum.
	* jcf-reader.c (get_attribute): Pass field/method index and
	attribute type to get_attribute().
	* constants.c (find_class_or_string_constant): Make nonstatic.
	(cpool_for_class): Likewise.
	(build_constants_constructor): Separate string and scalar types.
	* class.c (make_class_data): Generate field_indexes permutation.
	Pass it to rewrite_reflection_indexes().
	(make_class_data): Generate constructor for reflection_data field.

Index: java/class.c
===================================================================
--- java/class.c	(revision 117853)
+++ java/class.c	(working copy)
@@ -46,6 +46,7 @@
 #include "cgraph.h"
 #include "tree-iterator.h"
 #include "cgraph.h"
+#include "vecprim.h"
 
 /* DOS brain-damage */
 #ifndef O_BINARY
@@ -1641,6 +1642,8 @@
       to where objects actually point at, following new g++ ABI. */
   tree dtable_start_offset = build_int_cst (NULL_TREE,
 					    2 * POINTER_SIZE / BITS_PER_UNIT);
+  VEC(int, heap) *field_indexes;
+  tree first_real_field;
 
   this_class_addr = build_static_class_ref (type);
   decl = TREE_OPERAND (this_class_addr, 0);
@@ -1681,7 +1684,54 @@
     field = TREE_CHAIN (field);  /* Skip dummy fields.  */
   if (field && DECL_NAME (field) == NULL_TREE)
     field = TREE_CHAIN (field);  /* Skip dummy field for inherited data. */
-  for ( ;  field != NULL_TREE;  field = TREE_CHAIN (field))
+  first_real_field = field;
+
+  /* First count static and instance fields.  */
+  for ( ; field != NULL_TREE; field = TREE_CHAIN (field))
+    {
+      if (! DECL_ARTIFICIAL (field))
+	{
+	  if (FIELD_STATIC (field))
+	    static_field_count++;
+	  else if (uses_jv_markobj || !flag_reduced_reflection)
+	    instance_field_count++;
+	}
+    }
+  field_count = static_field_count + instance_field_count;
+  field_indexes = VEC_alloc (int, heap, field_count);
+  
+  /* gcj sorts fields so that static fields come first, followed by
+     instance fields.  Unfortunately, by the time this takes place we
+     have already generated the reflection_data for this class, and
+     that data contians indexes into the fields.  So, we generate a
+     permutation that maps each original field index to its final
+     position.  Then we pass this permutation to
+     rewrite_reflection_indexes(), which fixes up the reflection
+     data.  */
+  {
+    int i;
+    int static_count = 0;
+    int instance_count = static_field_count;
+    int field_index;
+
+    for (i = 0, field = first_real_field; 
+	 field != NULL_TREE; 
+	 field = TREE_CHAIN (field), i++)
+    {
+      if (! DECL_ARTIFICIAL (field))
+	{
+	  field_index = 0;
+	  if (FIELD_STATIC (field))
+	    field_index = static_count++;
+	  else if (uses_jv_markobj || !flag_reduced_reflection)
+	    field_index = instance_count++;
+	  VEC_quick_push (int, field_indexes, field_index);
+	}
+    }
+  }
+
+  for (field = first_real_field; field != NULL_TREE; 
+       field = TREE_CHAIN (field))
     {
       if (! DECL_ARTIFICIAL (field))
 	{
@@ -1691,7 +1741,6 @@
                  as it is used in the creation of the field itself. */
               tree init = make_field_value (field);
 	      tree initial = DECL_INITIAL (field);
-	      static_field_count++;
 	      static_fields = tree_cons (NULL_TREE, init, static_fields);
 	      /* If the initial value is a string constant,
 		 prevent output_constant from trying to assemble the value. */
@@ -1704,12 +1753,11 @@
 	  else if (uses_jv_markobj || !flag_reduced_reflection)
 	    {
               tree init = make_field_value (field);
-	      instance_field_count++;
 	      instance_fields = tree_cons (NULL_TREE, init, instance_fields);
 	    }
 	}
     }
-  field_count = static_field_count + instance_field_count;
+
   if (field_count > 0)
     {
       static_fields = nreverse (static_fields);
@@ -2008,7 +2056,48 @@
   PUSH_FIELD_VALUE (cons, "chain", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "aux_info", null_pointer_node);
   PUSH_FIELD_VALUE (cons, "engine", null_pointer_node);
-  PUSH_FIELD_VALUE (cons, "reflection_data", null_pointer_node);
+
+  if (TYPE_REFLECTION_DATA (current_class))
+    {
+      int i;
+      int count = TYPE_REFLECTION_DATASIZE (current_class);
+      VEC (constructor_elt, gc) *v
+	= VEC_alloc (constructor_elt, gc, count);
+      unsigned char *data = TYPE_REFLECTION_DATA (current_class);
+      tree max_index = build_int_cst (sizetype, count);
+      tree index = build_index_type (max_index);
+      tree type = build_array_type (unsigned_byte_type_node, index);
+      char buf[64];
+      tree array;
+      static int reflection_data_count;
+
+      sprintf (buf, "_reflection_data_%d", reflection_data_count++);
+      array = build_decl (VAR_DECL, get_identifier (buf), type);
+
+      rewrite_reflection_indexes (field_indexes);
+
+      for (i = 0; i < count; i++)
+	{
+	  constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
+ 	  elt->index = build_int_cst (sizetype, i);
+	  elt->value = build_int_cstu (byte_type_node, data[i]);
+	}
+
+      DECL_INITIAL (array) = build_constructor (type, v);
+      TREE_STATIC (array) = 1;
+      DECL_ARTIFICIAL (array) = 1;
+      DECL_IGNORED_P (array) = 1;
+      TREE_READONLY (array) = 1;
+      TREE_CONSTANT (array) = 1;
+      rest_of_decl_compilation (array, 1, 0);
+      
+      PUSH_FIELD_VALUE (cons, "reflection_data", build_address_of (array));
+
+      free (data);
+      TYPE_REFLECTION_DATA (current_class) = NULL;
+    }
+  else
+    PUSH_FIELD_VALUE (cons, "reflection_data", null_pointer_node);
 
   FINISH_RECORD_CONSTRUCTOR (cons);
 
Index: java/jcf-parse.c
===================================================================
--- java/jcf-parse.c	(revision 117853)
+++ java/jcf-parse.c	(working copy)
@@ -35,6 +35,7 @@
 #include "flags.h"
 #include "java-except.h"
 #include "input.h"
+#include "javaop.h"
 #include "java-tree.h"
 #include "toplev.h"
 #include "parse.h"
@@ -43,6 +44,7 @@
 #include "assert.h"
 #include "tm_p.h"
 #include "cgraph.h"
+#include "vecprim.h"
 
 #ifdef HAVE_LOCALE_H
 #include <locale.h>
@@ -96,6 +98,11 @@
 
 static struct ZipFile *localToFile;
 
+/* A map of byte offsets in the reflection data that are fields which
+   need renumbering.  */
+bitmap field_offsets;
+bitmap_obstack bit_obstack;
+
 /* Declarations of some functions used here.  */
 static void handle_innerclass_attribute (int count, JCF *);
 static tree give_name_to_class (JCF *jcf, int index);
@@ -111,6 +118,7 @@
 static void set_source_filename (JCF *, int);
 static void jcf_parse (struct JCF*);
 static void load_inner_classes (tree);
+static void handle_annotation (JCF *jcf, int level);
 
 /* Handle "Deprecated" attribute.  */
 static void
@@ -369,6 +377,439 @@
   if (current_class == main_class) main_input_filename = sfname;
 }
 
+
+
+
+/* Annotation handling.  
+
+   The technique we use here is to copy the annotation data directly
+   from the input class file into the ouput file.  We don't decode the
+   data at all, merely rewriting constant indexes whenever we come
+   across them: this is necessary becasue the constant pool in the
+   output file isn't the same as the constant pool in in the input.
+
+   The main advantage of this technique is that the resulting
+   annotation data is pointer-free, so it doesn't have to be relocated
+   at startup time.  As a consequence of this, annotations have no
+   peformance impact unless they are used.  Also, this representation
+   is very dense.  */
+
+
+/* Expand TYPE_REFLECTION_DATA by DELTA bytes.  Return the address of
+   the start of the newly allocated region.  */
+
+static unsigned char*
+annotation_grow (int delta)
+{
+  unsigned char **data = &TYPE_REFLECTION_DATA (current_class);
+  long *datasize = &TYPE_REFLECTION_DATASIZE (current_class);
+  long len = *datasize;
+
+  if (*data == NULL)
+    {
+      *data = xmalloc (delta);
+    }
+  else
+    {
+      int newlen = *datasize + delta;
+      if (floor_log2 (newlen) != floor_log2 (*datasize))
+	*data = xrealloc (*data,  2 << (floor_log2 (newlen)));
+    }
+  *datasize += delta;
+  return *data + len;
+}
+
+/* annotation_rewrite_TYPE.  Rewrite various int types at p.  Use Java
+   byte order (i.e. big endian.)  */
+
+static void
+annotation_rewrite_byte (unsigned int n, unsigned char *p)
+{
+  p[0] = n;
+}
+
+static void
+annotation_rewrite_short (unsigned int n, unsigned char *p)
+{
+  p[0] = n>>8;
+  p[1] = n;
+}
+
+static void
+annotation_rewrite_int (unsigned int n, unsigned char *p)
+{
+  p[0] = n>>24;
+  p[1] = n>>16;
+  p[2] = n>>8;
+  p[3] = n;
+}
+
+/* Read a 16-bit unsigned int in Java byte order (i.e. big
+   endian.)  */
+
+static uint16
+annotation_read_short (unsigned char *p)
+{
+  uint16 tmp = p[0];
+  tmp = (tmp << 8) | p[1];
+  return tmp;
+}
+
+/* annotation_write_TYPE.  Rewrite various int types, appending them
+   to TYPE_REFLECTION_DATA.  Use Java byte order (i.e. big
+   endian.)  */
+
+static void
+annotation_write_byte (unsigned int n)
+{
+  annotation_rewrite_byte (n, annotation_grow (1));
+}
+
+static void
+annotation_write_short (unsigned int n)
+{
+  annotation_rewrite_short (n, annotation_grow (2));
+}
+
+static void
+annotation_write_int (unsigned int n)
+{
+  annotation_rewrite_int (n, annotation_grow (4));
+}
+
+/* Create a 64-bit constant in the constant pool.
+
+   This is used for both integer and floating-point types.  As a
+   consequence, it will not work if the target floating-point format
+   is anything other than IEEE-754.  While this is arguably a bug, the
+   runtime library makes exactly the same assumption and it's unlikely
+   that Java will ever run on a non-IEEE machine.  */
+
+static int 
+handle_long_constant (JCF *jcf, CPool *cpool, enum cpool_tag kind,
+		    int index, bool big_endian)
+{
+  /* If we're on a 64-bit platform we can fit a long or double
+     into the same space as a jword.  */
+  if (POINTER_SIZE >= 64)
+    index = find_constant1 (cpool, kind, JPOOL_LONG (jcf, index));
+
+  /* In a compiled program the constant pool is in native word
+     order.  How weird is that???  */
+  else if (big_endian)
+    index = find_constant2 (cpool, kind,
+			    JPOOL_INT (jcf, index), 
+			    JPOOL_INT (jcf, index+1));
+  else
+    index = find_constant2 (cpool, kind,
+			    JPOOL_INT (jcf, index+1), 
+			    JPOOL_INT (jcf, index));
+  
+  return index;
+}
+
+/* Given a class file and an index into its constant pool, create an
+   entry in the outgoing constant pool for the same item.  */
+
+static uint16
+handle_constant (JCF *jcf, int index, enum cpool_tag purpose)
+{
+  enum cpool_tag kind;
+  CPool *cpool = cpool_for_class (output_class);
+  
+  if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
+    error ("<constant pool index %d not in range>", index);
+  
+  kind = JPOOL_TAG (jcf, index);
+
+  if (kind != purpose)
+    {
+      if (purpose == CONSTANT_Class
+	  && kind == CONSTANT_Utf8)
+	;
+      else
+	error ("<constant pool index %d unexpected type", index);
+    }
+
+  switch (kind)
+    {
+    case CONSTANT_Utf8:
+      {
+	tree utf8 = get_constant (jcf, index);
+
+	if (purpose == CONSTANT_Class)
+	  /* Create a constant pool entry for a type.  This one has
+	     '.' rather than '/' because it isn't going into a class
+	     file, it's going into a compiled object.
+	     
+	     This has to match the logic in
+	     _Jv_ClassReader::prepare_pool_entry().  */
+	  utf8 = identifier_subst (utf8, "", '/', '.', "");
+
+	index = alloc_name_constant (kind, utf8);
+      }
+      break;
+
+    case CONSTANT_Long:
+      index = handle_long_constant (jcf, cpool, kind, index, 
+				    WORDS_BIG_ENDIAN);
+      break;
+      
+    case CONSTANT_Double:
+      index = handle_long_constant (jcf, cpool, kind, index, 
+				    FLOAT_WORDS_BIG_ENDIAN);
+      break;
+
+    case CONSTANT_Float:
+    case CONSTANT_Integer:
+      index = find_constant1 (cpool, kind, JPOOL_INT (jcf, index));
+      break;
+      
+    default:
+      abort ();
+    }
+  
+  return index;
+}
+
+/* Read an element_value structure from an annotation in JCF.  Return
+   the constant pool index for the resulting constant pool entry.  */
+
+static int
+handle_element_value (JCF *jcf, int level)
+{
+  uint8 tag = JCF_readu (jcf);
+  int index = 0;
+
+  annotation_write_byte (tag);
+  switch (tag)
+    {
+    case 'B':
+    case 'C':
+    case 'S':
+    case 'Z':
+    case 'I':
+      {
+	uint16 cindex = JCF_readu2 (jcf);
+	index = handle_constant (jcf, cindex,
+				 CONSTANT_Integer);
+	annotation_write_short (index);
+      }
+      break;
+    case 'D':
+      {
+	uint16 cindex = JCF_readu2 (jcf);
+	index = handle_constant (jcf, cindex,
+				 CONSTANT_Double);
+	annotation_write_short (index);
+      }
+      break;
+    case 'F':
+      {
+	uint16 cindex = JCF_readu2 (jcf);
+	index = handle_constant (jcf, cindex,
+				 CONSTANT_Float);
+	annotation_write_short (index);
+      }
+      break;
+    case 'J':
+      {
+	uint16 cindex = JCF_readu2 (jcf);
+	index = handle_constant (jcf, cindex,
+				 CONSTANT_Long);
+	annotation_write_short (index);
+      }
+      break;
+    case 's':
+      {
+	uint16 cindex = JCF_readu2 (jcf);
+	/* Despite what the JVM spec says, compilers generate a Utf8
+	   constant here, not a String.  */
+	index = handle_constant (jcf, cindex,
+				 CONSTANT_Utf8);
+	annotation_write_short (index);
+      }
+      break;
+
+    case 'e':
+      {
+	uint16 type_name_index = JCF_readu2 (jcf);
+	uint16 const_name_index = JCF_readu2 (jcf);
+	index = handle_constant (jcf, type_name_index,
+				 CONSTANT_Class);
+	annotation_write_short (index);
+	index = handle_constant (jcf, const_name_index,
+				 CONSTANT_Utf8);
+	annotation_write_short (index);
+     }
+      break;
+    case 'c':
+      {
+	uint16 class_info_index = JCF_readu2 (jcf);
+	index = handle_constant (jcf, class_info_index,
+				 CONSTANT_Class);
+	annotation_write_short (index);
+      }
+      break;
+    case '@':
+      {
+	handle_annotation (jcf, level + 1);
+      }
+      break;
+    case '[':
+      {
+	uint16 n_array_elts = JCF_readu2 (jcf);
+	printf ("array[%d]: [\n", (int) n_array_elts);
+	annotation_write_short (n_array_elts);
+	while (n_array_elts--)
+	  handle_element_value (jcf, level + 1);
+	printf ("]");
+      }
+      break;
+    default:
+      abort();
+      break;
+    }
+  return index;
+}
+
+/* Read an annotation structure from JCF.  Write it to the
+   reflection_data field of the outgoing class.  */
+
+static void
+handle_annotation (JCF *jcf, int level)
+{
+  uint16 type_index = JCF_readu2 (jcf);
+  uint16 npairs = JCF_readu2 (jcf);
+  int index = handle_constant (jcf, type_index,
+			       CONSTANT_Class);
+  annotation_write_short (index);
+  annotation_write_short (npairs);
+  while (npairs--)
+    {
+      uint16 name_index = JCF_readu2 (jcf);
+      index = handle_constant (jcf, name_index,
+			       CONSTANT_Utf8);
+      annotation_write_short (index);
+      handle_element_value (jcf, level + 2);
+    }
+}
+
+/* Read an annotation count from JCF, and write the following
+   annotatons to the reflection_data field of the outgoing class.  */
+
+static void
+handle_annotations (JCF *jcf, int level)
+{
+  uint16 num = JCF_readu2 (jcf);
+  annotation_write_short (num);
+  while (num--)
+    handle_annotation (jcf, level);
+}
+
+/* As handle_annotations(), but perform a sanity check that we write
+   the same number of bytes that we were expecting.  */
+
+static void
+handle_annotation_attribute (int ATTRIBUTE_UNUSED index, JCF *jcf, 
+			     long length)
+{
+  long old_datasize = TYPE_REFLECTION_DATASIZE (current_class);
+
+  handle_annotations (jcf, 0);
+
+  gcc_assert (old_datasize + length
+	      == TYPE_REFLECTION_DATASIZE (current_class));
+}
+
+/* gcj permutes its fields array after generating annotation_data, so
+   we have to fixup field indexes for fields that have moved.  Given
+   ARG, a VEC_int, fixup the field indexes in the reflection_data of
+   the outgoing class.  We use field_offsets to tell us where the
+   fixups must go.  */
+
+void
+rewrite_reflection_indexes (void *arg)
+{
+  bitmap_iterator bi;
+  int offset;
+  VEC(int, heap) *map = arg;
+  CPool *cpool = cpool_for_class (output_class);
+  unsigned char *data = TYPE_REFLECTION_DATA (current_class);
+
+  EXECUTE_IF_SET_IN_BITMAP (field_offsets, 0, offset, bi)
+    {
+      uint16 index = annotation_read_short (data + offset);
+      annotation_rewrite_short (VEC_index (int, map, index), data + offset);
+    }
+}
+
+/* Read the RuntimeVisibleAnnotations from JCF and write them to the
+   reflection_data of the outgoing class.  */
+
+static void
+handle_member_annotations (int member_index, JCF *jcf, 
+			   const unsigned char *name ATTRIBUTE_UNUSED, 
+			   long len, jv_attr_type member_type)
+{
+  int new_len = len + 1;
+  annotation_write_byte (member_type);
+  if (member_type != JV_CLASS_ATTR)
+    new_len += 2;
+  annotation_write_int (new_len);
+  annotation_write_byte (JV_ANNOTATIONS_KIND);
+  if (member_type == JV_FIELD_ATTR)
+    bitmap_set_bit (field_offsets, TYPE_REFLECTION_DATASIZE (current_class));
+  if (member_type != JV_CLASS_ATTR)
+    annotation_write_short (member_index);
+  handle_annotation_attribute (member_index, jcf, len);
+}
+
+/* Read the RuntimeVisibleParameterAnnotations from JCF and write them
+   to the reflection_data of the outgoing class.  */
+
+static void
+handle_parameter_annotations (int member_index, JCF *jcf, 
+			      const unsigned char *name ATTRIBUTE_UNUSED, 
+			      long len, jv_attr_type member_type)
+{
+  int new_len = len + 1;
+  uint8 num;
+  annotation_write_byte (member_type);
+  if (member_type != JV_CLASS_ATTR)
+    new_len += 2;
+  annotation_write_int (new_len);
+  annotation_write_byte (JV_PARAMETER_ANNOTATIONS_KIND);
+  if (member_type != JV_CLASS_ATTR)
+    annotation_write_short (member_index);
+  num = JCF_readu (jcf);
+  annotation_write_byte (num);
+  while (num--)
+    handle_annotations (jcf, 0);
+}
+
+
+/* Read the AnnotationDefault data from JCF and write them to the
+   reflection_data of the outgoing class.  */
+
+static void
+handle_default_annotation (int member_index, JCF *jcf, 
+			   const unsigned char *name ATTRIBUTE_UNUSED, 
+			   long len, jv_attr_type member_type)
+{
+  int new_len = len + 1;
+  annotation_write_byte (member_type);
+  if (member_type != JV_CLASS_ATTR)
+    new_len += 2;
+  annotation_write_int (new_len);
+  annotation_write_byte (JV_ANNOTATION_DEFAULT_KIND);
+  if (member_type != JV_CLASS_ATTR)
+    annotation_write_short (member_index);
+  handle_element_value (jcf, 0);
+}
+
+
+
 #define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)
 
 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
@@ -462,6 +903,31 @@
     jcf->right_zip = 1;				\
 }
 
+#define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE()			\
+{									\
+  handle_member_annotations (index, jcf, name_data, attribute_length, attr_type); \
+}
+
+#define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE()	\
+{							\
+  JCF_SKIP(jcf, attribute_length);			\
+}
+
+#define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE()		\
+{									\
+  handle_parameter_annotations (index, jcf, name_data, attribute_length, attr_type); \
+}
+
+#define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE()	\
+{								\
+  JCF_SKIP(jcf, attribute_length);				\
+}
+
+#define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE()				\
+{									\
+  handle_default_annotation (index, jcf, name_data, attribute_length, attr_type); \
+}
+
 #include "jcf-reader.c"
 
 tree
@@ -972,6 +1438,10 @@
   code = jcf_parse_final_attributes (jcf);
   if (code != 0)
     fatal_error ("error while parsing final attributes");
+
+  if (TYPE_REFLECTION_DATA (current_class))
+    annotation_write_byte (JV_DONE_ATTR);
+
 #ifdef USE_MAPPED_LOCATION
   linemap_add (&line_table, LC_LEAVE, false, NULL, 0);
 #endif
@@ -1258,6 +1728,9 @@
   FILE *finput = NULL;
   int in_quotes = 0;
  
+  bitmap_obstack_initialize (&bit_obstack);
+  field_offsets = BITMAP_ALLOC (&bit_obstack);
+
   if (flag_filelist_file)
     {
       int avail = 2000;
@@ -1508,6 +1981,8 @@
     }
   input_location = save_location;
 
+  bitmap_obstack_release (&bit_obstack);
+
   java_expand_classes ();
   if (java_report_errors () || flag_syntax_only)
     return;
Index: java/constants.c
===================================================================
--- java/constants.c	(revision 117853)
+++ java/constants.c	(working copy)
@@ -34,11 +34,9 @@
 
 static void set_constant_entry (CPool *, int, int, jword);
 static int find_tree_constant (CPool *, int, tree);
-static int find_class_or_string_constant (CPool *, int, tree);
 static int find_name_and_type_constant (CPool *, tree, tree);
 static tree get_tag_node (int);
 static tree build_constant_data_ref (void);
-static CPool *cpool_for_class (tree);
 
 /* Set the INDEX'th constant in CPOOL to have the given TAG and VALUE. */
 
@@ -134,7 +132,7 @@
   return find_tree_constant (cpool, CONSTANT_Utf8, name);
 }
 
-static int
+int
 find_class_or_string_constant (CPool *cpool, int tag, tree name)
 {
   jword j = find_utf8_constant (cpool, name);
@@ -329,7 +327,7 @@
 
 /* Given a class, return its constant pool, creating one if necessary.  */
 
-static CPool *
+CPool *
 cpool_for_class (tree class)
 {
   CPool *cpool = TYPE_CPOOL (class);
@@ -495,11 +493,20 @@
   tree tags_list = NULL_TREE;
   tree data_list = NULL_TREE;
   int i;
+
   for (i = outgoing_cpool->count;  --i > 0; )
     switch (outgoing_cpool->tags[i])
       {
+      case CONSTANT_None:  /* The second half of a Double or Long on a
+			      32-bit target.  */
       case CONSTANT_Fieldref:
       case CONSTANT_NameAndType:
+      case CONSTANT_Float:
+      case CONSTANT_Integer:
+      case CONSTANT_Double:
+      case CONSTANT_Long:
+      case CONSTANT_Methodref:
+      case CONSTANT_InterfaceMethodref:
 	{
 	  unsigned HOST_WIDE_INT temp = outgoing_cpool->data[i].w;
 
@@ -522,7 +529,11 @@
 			 data_list);
 	}
 	break;
-      default:
+
+      case CONSTANT_Class:
+      case CONSTANT_String:
+      case CONSTANT_Unicode:
+      case CONSTANT_Utf8:
 	tags_list
 	  = tree_cons (NULL_TREE, get_tag_node (outgoing_cpool->tags[i]),
 		       tags_list);
@@ -530,6 +541,9 @@
 	  = tree_cons (NULL_TREE, build_utf8_ref (outgoing_cpool->data[i].t),
 		       data_list);
 	break;
+
+      default:
+	gcc_assert (false);
       }
   if (outgoing_cpool->count > 0)
     {
Index: java/jcf-reader.c
===================================================================
--- java/jcf-reader.c	(revision 117853)
+++ java/jcf-reader.c	(working copy)
@@ -28,12 +28,12 @@
 #include "jcf.h"
 #include "zipfile.h"
 
-static int get_attribute (JCF *);
+static int get_attribute (JCF *, int, jv_attr_type);
 static int jcf_parse_preamble (JCF *);
 static int jcf_parse_constant_pool (JCF *);
 static void jcf_parse_class (JCF *);
 static int jcf_parse_fields (JCF *);
-static int jcf_parse_one_method (JCF *);
+static int jcf_parse_one_method (JCF *, int);
 static int jcf_parse_methods (JCF *);
 static int jcf_parse_final_attributes (JCF *);
 #ifdef NEED_PEEK_ATTRIBUTE
@@ -103,7 +103,7 @@
 #endif
 
 static int
-get_attribute (JCF *jcf)
+get_attribute (JCF *jcf, int index, jv_attr_type attr_type)
 {
   uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf));
   uint32 attribute_length = JCF_readu4 (jcf);
@@ -168,7 +168,7 @@
       attributes_count = JCF_readu2 (jcf);
       for (j = 0; j < attributes_count; j++)
 	{
-	  int code = get_attribute (jcf);
+	  int code = get_attribute (jcf, index, JV_METHOD_ATTR);
 	  if (code != 0)
 	    return code;
 	}
@@ -441,7 +441,7 @@
 #endif
       for (j = 0; j < attribute_count; j++)
 	{
-	  int code = get_attribute (jcf);
+	  int code = get_attribute (jcf, i, JV_FIELD_ATTR);
 	  if (code != 0)
 	    return code;
 	}
@@ -458,7 +458,7 @@
 /* Read methods. */
 
 static int
-jcf_parse_one_method (JCF* jcf)
+jcf_parse_one_method (JCF* jcf, int index)
 {
   int i;
   uint16 access_flags = (JCF_FILL (jcf, 8), JCF_readu2 (jcf));
@@ -470,7 +470,7 @@
 #endif
   for (i = 0; i < attribute_count; i++)
     {
-      int code = get_attribute (jcf);
+      int code = get_attribute (jcf, index, JV_METHOD_ATTR);
       if (code != 0)
 	return code;
     }
@@ -492,7 +492,7 @@
 #endif
   for (i = 0; i < methods_count; i++)
     {
-      int code = jcf_parse_one_method (jcf);
+      int code = jcf_parse_one_method (jcf, i);
       if (code != 0)
 	return code;
     }
@@ -513,7 +513,7 @@
 #endif
   for (i = 0; i < attributes_count; i++)
     {
-      int code = get_attribute (jcf);
+      int code = get_attribute (jcf, i, JV_CLASS_ATTR);
       if (code != 0)
 	return code;
     }
Index: java/ChangeLog
===================================================================
--- java/ChangeLog	(revision 117853)
+++ java/ChangeLog	(working copy)
@@ -1,3 +1,35 @@
+2006-11-01  Andrew Haley  <aph@redhat.com>
+
+	* jcf-parse.c (field_offsets, bit_obstack): New variables.
+	(jcf_parse): Write end marker to annotation_data.
+	(java_parse_file): Create field_offsets bitmap.
+	Destroy it.
+	(annotation_grow, annotation_rewrite_byte) 
+	(annotation_rewrite_short, annotation_rewrite_int) 
+	(annotation_read_short, annotation_write_byte) 
+	(annotation_write_short, annotation_write_int) 
+	(handle_long_constant, handle_constant, handle_element_value) 
+	(handle_annotation, handle_annotations) 
+	(handle_annotation_attribute, rewrite_reflection_indexes) 
+	(handle_member_annotations, handle_parameter_annotations) 
+	(handle_default_annotation) 
+	(HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE) 
+	(HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE) 
+	(HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE) 
+	(HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE) 
+	(HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE): New functions.
+	* java-tree.h (enum jv_attr_type, enum jv_attr_kind): New. 
+	* jcf.h (enum cpool_tag): Convert a bunch of #define constants to
+	an enum.
+	* jcf-reader.c (get_attribute): Pass field/method index and
+	attribute type to get_attribute().
+	* constants.c (find_class_or_string_constant): Make nonstatic.
+	(cpool_for_class): Likewise.
+	(build_constants_constructor): Separate string and scalar types.
+	* class.c (make_class_data): Generate field_indexes permutation.
+	Pass it to rewrite_reflection_indexes().
+	(make_class_data): Generate constructor for reflection_data field.
+
 2006-10-17  Tom Tromey  <tromey@redhat.com>
 
 	* jcf-dump.c (print_element_value): Expect a utf8 constant in the
Index: java/jcf.h
===================================================================
--- java/jcf.h	(revision 117853)
+++ java/jcf.h	(working copy)
@@ -241,18 +241,22 @@
 
 #define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
 
-#define CONSTANT_Class 7
-#define CONSTANT_Fieldref 9
-#define CONSTANT_Methodref 10
-#define CONSTANT_InterfaceMethodref 11
-#define CONSTANT_String 8
-#define CONSTANT_Integer 3
-#define CONSTANT_Float 4
-#define CONSTANT_Long 5
-#define CONSTANT_Double 6
-#define CONSTANT_NameAndType 12
-#define CONSTANT_Utf8 1
-#define CONSTANT_Unicode 2
+enum cpool_tag
+{
+  CONSTANT_Class = 7,
+  CONSTANT_Fieldref = 9,
+  CONSTANT_Methodref = 10,
+  CONSTANT_InterfaceMethodref = 11,
+  CONSTANT_String = 8,
+  CONSTANT_Integer = 3,
+  CONSTANT_Float = 4,
+  CONSTANT_Long = 5,
+  CONSTANT_Double = 6,
+  CONSTANT_NameAndType = 12,
+  CONSTANT_Utf8 = 1,
+  CONSTANT_Unicode = 2,
+  CONSTANT_None = 0
+};
 
 #define DEFAULT_CLASS_PATH "."
 
Index: java/java-tree.h
===================================================================
--- java/java-tree.h	(revision 117853)
+++ java/java-tree.h	(working copy)
@@ -993,7 +993,7 @@
   tree value;
 };
 
-/* These represent the possible assertion_code's that can be emitted in the
+/* These represent the possible assertion_codes that can be emitted in the
    type assertion table.  */
 enum
 {
@@ -1002,6 +1002,28 @@
   JV_ASSERT_IS_INSTANTIABLE = 2   /* Operand A is an instantiable class.  */
 };
 
+/* Annotation types used in the reflection_data.  See
+   java.lang.Class.getDeclaredAnnotations() in the runtime library for
+   an example of how these are used.  */
+
+typedef enum
+{
+  JV_CLASS_ATTR,
+  JV_METHOD_ATTR,
+  JV_FIELD_ATTR,
+  JV_DONE_ATTR
+} jv_attr_type;
+
+typedef enum
+{
+  JV_INNER_CLASSES_KIND,
+  JV_ENCLOSING_METHOD_KIND,
+  JV_SIGNATURE_KIND,
+  JV_ANNOTATIONS_KIND,
+  JV_PARAMETER_ANNOTATIONS_KIND,
+  JV_ANNOTATION_DEFAULT_KIND
+} jv_attr_kind;
+
 typedef struct type_assertion GTY(())
 {
   int assertion_code; /* 'opcode' for the type of this assertion. */
@@ -1095,6 +1117,10 @@
 #define TYPE_ASSERTIONS(T)   	 (TYPE_LANG_SPECIFIC (T)->type_assertions)
 #define TYPE_PACKAGE(T)     	 (TYPE_LANG_SPECIFIC (T)->package)
 
+#define TYPE_REFLECTION_DATA(T)	 (TYPE_LANG_SPECIFIC (T)->reflection_data)
+#define TYPE_REFLECTION_DATASIZE(T)					\
+				(TYPE_LANG_SPECIFIC (T)->reflection_datasize)
+
 struct lang_type GTY(())
 {
   tree signature;
@@ -1145,11 +1171,17 @@
   tree package;			/* IDENTIFIER_NODE for package this class is
   				   a member of.  */
 
+  unsigned char* GTY((skip)) reflection_data;	/* The raw reflection
+						   data for this
+						   class.  */
+  long reflection_datasize;	/* The size of the raw reflection data
+				   for this class, in bytes.  */
+
   unsigned pic:1;		/* Private Inner Class. */
   unsigned poic:1;		/* Protected Inner Class. */
   unsigned strictfp:1;		/* `strictfp' class.  */
   unsigned assertions:1;	/* Any method uses `assert'.  */
-  unsigned dummy_class:1;		/* Not a real class, just a placeholder.  */
+  unsigned dummy_class:1;	/* Not a real class, just a placeholder.  */
 };
 
 #define JCF_u4 unsigned long
@@ -1295,6 +1327,8 @@
 extern void finish_class (void);
 extern void java_layout_seen_class_methods (void);
 extern void check_for_initialization (tree, tree);
+extern struct CPool *cpool_for_class (tree);
+extern int find_class_or_string_constant (struct CPool *, int, tree);
 
 extern tree pushdecl_top_level (tree);
 extern tree pushdecl_function_level (tree);
@@ -1407,6 +1441,7 @@
 
 extern void java_read_sourcefilenames (const char *fsource_filename);
 
+extern void rewrite_reflection_indexes (void *);
 
 #define DECL_FINAL(DECL) DECL_LANG_FLAG_3 (DECL)
 



More information about the Gcc-patches mailing list