[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