[ecj] Implement signatures for Class.getEnclosingMethod() et al
Andrew Haley
aph@redhat.com
Mon Nov 6 15:32:00 GMT 2006
Internal handling for a bunch of reflection methods.
Class.getEnclosingMethod(), Class.getGenericXX, and so on.
Andrew.
2006-11-06 Andrew Haley <aph@redhat.com>
* java-tree.h (CONSTANT_LazyFlag): New.
* constants.c (build_constants_constructor): Mask CONSTANT_LazyFlag.
* jcf-parse.c (handle_innerclass_attribute): Write attribute to
reflection_data.
(handle_constant): Return 0 for dummy cpool entries.
Handle constants of kind Class.
Handle constants of kind NameAndType.
(handle_enclosingmethod_attribute): New.
(handle_signature_attribute): New.
(HANDLE_ENCLOSINGMETHOD_ATTRIBUTE): New.
(HANDLE_SIGNATURE_ATTRIBUTE): New.
(handle_constant): Use unmangle_classname()rather than calling
identifier_subst() directly.
Index: java/jcf-parse.c
===================================================================
--- java/jcf-parse.c (revision 118395)
+++ java/jcf-parse.c (working copy)
@@ -104,7 +104,7 @@
bitmap_obstack bit_obstack;
/* Declarations of some functions used here. */
-static void handle_innerclass_attribute (int count, JCF *);
+static void handle_innerclass_attribute (int count, JCF *, int len);
static tree give_name_to_class (JCF *jcf, int index);
static char *compute_class_name (struct ZipDirectory *zdir);
static int classify_zip_file (struct ZipDirectory *zdir);
@@ -517,12 +517,15 @@
enum cpool_tag kind;
CPool *cpool = cpool_for_class (output_class);
+ if (index == 0)
+ return 0;
+
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 ((kind & ~CONSTANT_ResolvedFlag) != purpose)
{
if (purpose == CONSTANT_Class
&& kind == CONSTANT_Utf8)
@@ -533,19 +536,36 @@
switch (kind)
{
+ case CONSTANT_Class:
+ case CONSTANT_ResolvedClass:
+ {
+ /* For some reason I know not the what of, class names in
+ annotations are UTF-8 strings in the constant pool but
+ class names in EnclosingMethod attributes are real class
+ references. Set CONSTANT_LazyFlag here so that the VM
+ doesn't attempt to resolve them at class initialization
+ time. */
+ tree resolved_class, class_name;
+ resolved_class = get_class_constant (jcf, index);
+ class_name = build_internal_class_name (resolved_class);
+ index = alloc_name_constant (CONSTANT_Class | CONSTANT_LazyFlag,
+ (unmangle_classname
+ (IDENTIFIER_POINTER(class_name),
+ IDENTIFIER_LENGTH(class_name))));
+ break;
+ }
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.
+ /* Create a constant pool entry for a type signature. 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, "", '/', '.', "");
-
+ utf8 = unmangle_classname (IDENTIFIER_POINTER(utf8),
+ IDENTIFIER_LENGTH(utf8));
index = alloc_name_constant (kind, utf8);
}
break;
@@ -565,6 +585,17 @@
index = find_constant1 (cpool, kind, JPOOL_INT (jcf, index));
break;
+ case CONSTANT_NameAndType:
+ {
+ uint16 name = JPOOL_USHORT1 (jcf, index);
+ uint16 sig = JPOOL_USHORT2 (jcf, index);
+ uint32 name_index = handle_constant (jcf, name, CONSTANT_Utf8);
+ uint32 sig_index = handle_constant (jcf, sig, CONSTANT_Class);
+ jword new_index = (name_index << 16) | sig_index;
+ index = find_constant1 (cpool, kind, new_index);
+ }
+ break;
+
default:
abort ();
}
@@ -805,6 +836,54 @@
handle_element_value (jcf, 0);
}
+/* As above, for the EnclosingMethod attribute. */
+
+static void
+handle_enclosingmethod_attribute (int member_index, JCF *jcf,
+ const unsigned char *name ATTRIBUTE_UNUSED,
+ long len, jv_attr_type member_type)
+{
+ int new_len = len + 1;
+ uint16 index;
+ annotation_write_byte (member_type);
+ if (member_type != JV_CLASS_ATTR)
+ new_len += 2;
+ annotation_write_int (new_len);
+ annotation_write_byte (JV_ENCLOSING_METHOD_KIND);
+ if (member_type != JV_CLASS_ATTR)
+ annotation_write_short (member_index);
+
+ index = JCF_readu2 (jcf);
+ index = handle_constant (jcf, index, CONSTANT_Class);
+ annotation_write_short (index);
+
+ index = JCF_readu2 (jcf);
+ index = handle_constant (jcf, index, CONSTANT_NameAndType);
+ annotation_write_short (index);
+}
+
+/* As above, for the Signature attribute. */
+
+static void
+handle_signature_attribute (int member_index, JCF *jcf,
+ const unsigned char *name ATTRIBUTE_UNUSED,
+ long len, jv_attr_type member_type)
+{
+ int new_len = len + 1;
+ uint16 index;
+ annotation_write_byte (member_type);
+ if (member_type != JV_CLASS_ATTR)
+ new_len += 2;
+ annotation_write_int (new_len);
+ annotation_write_byte (JV_SIGNATURE_KIND);
+ if (member_type != JV_CLASS_ATTR)
+ annotation_write_short (member_index);
+
+ index = JCF_readu2 (jcf);
+ index = handle_constant (jcf, index, CONSTANT_Utf8);
+ annotation_write_short (index);
+}
+
#define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)
@@ -882,7 +961,7 @@
/* Link seen inner classes to their outer context and register the
inner class to its outer context. They will be later loaded. */
#define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
- handle_innerclass_attribute (COUNT, jcf)
+ handle_innerclass_attribute (COUNT, jcf, attribute_length)
#define HANDLE_SYNTHETIC_ATTRIBUTE() \
{ \
@@ -925,6 +1004,18 @@
handle_default_annotation (index, jcf, name_data, attribute_length, attr_type); \
}
+#define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE() \
+{ \
+ handle_enclosingmethod_attribute (index, jcf, name_data, \
+ attribute_length, attr_type); \
+}
+
+#define HANDLE_SIGNATURE_ATTRIBUTE() \
+{ \
+ handle_signature_attribute (index, jcf, name_data, \
+ attribute_length, attr_type); \
+}
+
#include "jcf-reader.c"
tree
@@ -1049,9 +1140,15 @@
the outer context with the newly resolved innerclass. */
static void
-handle_innerclass_attribute (int count, JCF *jcf)
+handle_innerclass_attribute (int count, JCF *jcf, int attribute_length)
{
- int c = (count);
+ int c = count;
+
+ annotation_write_byte (JV_CLASS_ATTR);
+ annotation_write_int (attribute_length+1);
+ annotation_write_byte (JV_INNER_CLASSES_KIND);
+ annotation_write_short (count);
+
while (c--)
{
/* Read inner_class_info_index. This may be 0 */
@@ -1064,6 +1161,12 @@
int ini = JCF_readu2 (jcf);
/* Read the access flag. */
int acc = JCF_readu2 (jcf);
+
+ annotation_write_short (handle_constant (jcf, icii, CONSTANT_Class));
+ annotation_write_short (handle_constant (jcf, ocii, CONSTANT_Class));
+ annotation_write_short (handle_constant (jcf, ini, CONSTANT_Utf8));
+ annotation_write_short (acc);
+
/* If icii is 0, don't try to read the class. */
if (icii >= 0)
{
Index: java/constants.c
===================================================================
--- java/constants.c (revision 118395)
+++ java/constants.c (working copy)
@@ -495,7 +495,7 @@
int i;
for (i = outgoing_cpool->count; --i > 0; )
- switch (outgoing_cpool->tags[i])
+ switch (outgoing_cpool->tags[i] & ~CONSTANT_LazyFlag)
{
case CONSTANT_None: /* The second half of a Double or Long on a
32-bit target. */
* java-tree.h (FIELD_ENUM): New.
Index: java/java-tree.h
===================================================================
--- java/java-tree.h (revision 118418)
+++ java/java-tree.h (working copy)
@@ -243,6 +243,11 @@
#define CONSTANT_ResolvedFlag 16
+/* Don't eagerly resolve this entry. When this flag is set, constant
+ pool entries are resolved only at runtime when the entry is first
+ referred to. */
+#define CONSTANT_LazyFlag 32
+
/* The cpool->data[i] for a ResolvedString points to a STRING_CST. */
#define CONSTANT_ResolvedString (CONSTANT_String+CONSTANT_ResolvedFlag)
2006-11-06 Andrew Haley <aph@redhat.com>
* defineclass.cc (prepare_pool_entry): Be careful about which
constant pool entries have their '/' characters stripped.
(handleGenericSignature): Likewise.
(handleAnnotationElement): Likewise.
(handleAnnotation): Likewise.
(read_one_class_attribute): Likewise.
(handleMethod): Likewise.
* include/java-cpool.h (JV_CONSTANT_LazyFlag): New.
* java/lang/natClass.cc (check_constant): Likewise.
* link.cc (resolve_pool_entry): Mask JV_CONSTANT_LazyFlag.
Index: libjava/link.cc
===================================================================
--- libjava/link.cc (revision 118387)
+++ libjava/link.cc (working copy)
@@ -390,7 +390,7 @@
if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
return pool->data[index];
- switch (pool->tags[index])
+ switch (pool->tags[index] & ~JV_CONSTANT_LazyFlag)
{
case JV_CONSTANT_Class:
{
Index: libjava/gnu/java/nio/channels/natFileChannelPosix.cc
===================================================================
--- libjava/gnu/java/nio/channels/natFileChannelPosix.cc (revision 118387)
+++ libjava/gnu/java/nio/channels/natFileChannelPosix.cc (working copy)
@@ -513,6 +513,17 @@
throw new IOException (JvNewStringLatin1 (strerror (errno)));
buf->implPtr = reinterpret_cast<RawData*> (ptr);
buf->implLen = size+align;
+
+ struct stat st;
+
+ if (fstat (fd, &st))
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+
+ if (size+position > st.st_size)
+ throw new IOException (JvNewStringLatin1
+ ("mmap: requested region not completely "
+ "contained within file\n"));
+
return buf;
#else
throw new IOException (JvNewStringUTF ("mmap not implemented"));
Index: libjava/java/lang/natClass.cc
===================================================================
--- libjava/java/lang/natClass.cc (revision 118388)
+++ libjava/java/lang/natClass.cc (working copy)
@@ -1058,7 +1058,8 @@
{
if (cpool_index <= 0 || cpool_index >= pool->size)
throw new InternalError(JvNewStringLatin1("invalid constant pool index"));
- if ((pool->tags[cpool_index] & ~JV_CONSTANT_ResolvedFlag) != type)
+ if ((pool->tags[cpool_index] &
+ ~(JV_CONSTANT_ResolvedFlag|JV_CONSTANT_LazyFlag)) != type)
{
::java::lang::StringBuffer *sb = new ::java::lang::StringBuffer();
sb->append(JvNewStringLatin1("expected pool constant "));
Index: libjava/java/lang/VMCompiler.java
===================================================================
--- libjava/java/lang/VMCompiler.java (revision 118387)
+++ libjava/java/lang/VMCompiler.java (working copy)
@@ -187,7 +187,8 @@
ProtectionDomain domain)
{
if (precompiledMapFiles == null
- && (! useCompiler || ! canUseCompiler))
+ && (! useCompiler || ! canUseCompiler)
+ || name.startsWith("$Proxy"))
return null;
byte digest[];
Index: libjava/include/java-cpool.h
===================================================================
--- libjava/include/java-cpool.h (revision 118387)
+++ libjava/include/java-cpool.h (working copy)
@@ -28,6 +28,7 @@
#define JV_CONSTANT_InterfaceMethodref (11L)
#define JV_CONSTANT_NameAndType (12L)
#define JV_CONSTANT_ResolvedFlag (16L)
+#define JV_CONSTANT_LazyFlag (32L)
#define JV_CONSTANT_ResolvedString (16L | 8L)
#define JV_CONSTANT_ResolvedClass (16L | 7L)
Index: libjava/defineclass.cc
===================================================================
--- libjava/defineclass.cc (revision 118387)
+++ libjava/defineclass.cc (working copy)
@@ -277,7 +277,8 @@
/** and here goes the parser members defined out-of-line */
void parse ();
void read_constpool ();
- void prepare_pool_entry (int index, unsigned char tag);
+ void prepare_pool_entry (int index, unsigned char tag,
+ bool rewrite = true);
void read_fields ();
void read_methods ();
void read_one_class_attribute ();
@@ -473,7 +474,7 @@
int cpool_idx = read2u();
check_tag (cpool_idx, JV_CONSTANT_Utf8);
- prepare_pool_entry (cpool_idx, JV_CONSTANT_Utf8);
+ prepare_pool_entry (cpool_idx, JV_CONSTANT_Utf8, false);
::java::io::DataOutputStream *stream = get_reflection_stream ();
stream->writeByte(type);
@@ -531,7 +532,7 @@
// Despite what the JVM spec says, compilers generate a Utf8
// constant here, not a String.
check_tag (index, JV_CONSTANT_Utf8);
- prepare_pool_entry (index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (index, JV_CONSTANT_Utf8, false);
}
break;
@@ -542,7 +543,7 @@
check_tag (type_name_index, JV_CONSTANT_Utf8);
prepare_pool_entry (type_name_index, JV_CONSTANT_Utf8);
check_tag (const_name_index, JV_CONSTANT_Utf8);
- prepare_pool_entry (const_name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (const_name_index, JV_CONSTANT_Utf8, false);
}
break;
case 'c':
@@ -579,7 +580,7 @@
{
int name_index = read2u();
check_tag (name_index, JV_CONSTANT_Utf8);
- prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (name_index, JV_CONSTANT_Utf8, false);
handleAnnotationElement();
}
}
@@ -955,7 +956,7 @@
{
int source_index = read2u ();
check_tag (source_index, JV_CONSTANT_Utf8);
- prepare_pool_entry (source_index, JV_CONSTANT_Utf8);
+ prepare_pool_entry (source_index, JV_CONSTANT_Utf8, false);
def_interp->source_file_name = _Jv_NewStringUtf8Const
(def->constants.data[source_index].utf8);
}
@@ -1041,9 +1042,15 @@
}
/* this is a recursive procedure, which will prepare pool entries as needed.
- Which is how we avoid initializing those entries which go unused. */
+ Which is how we avoid initializing those entries which go unused.
+
+ REWRITE is true iff this pool entry is the Utf8 representation of a
+ class name or a signature.
+*/
+
void
-_Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
+_Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag,
+ bool rewrite)
{
/* these two, pool_data and pool_tags, point into the class
structure we are currently defining */
@@ -1064,27 +1071,29 @@
{
case JV_CONSTANT_Utf8:
{
- // FIXME: this is very wrong.
-
- // If we came here, it is because some other tag needs this
- // utf8-entry for type information! Thus, we translate /'s to .'s in
- // order to accomondate gcj's internal representation.
-
int len = get2u (this_data);
- char *buffer = (char*) __builtin_alloca (len);
char *s = ((char*) this_data)+2;
+ pool_tags[index] = JV_CONSTANT_Utf8;
- /* FIXME: avoid using a buffer here */
+ if (! rewrite)
+ {
+ pool_data[index].utf8 = _Jv_makeUtf8Const (s, len);
+ break;
+ }
+
+ // If REWRITE is set, it is because some other tag needs this
+ // utf8-entry for type information: it is a class or a
+ // signature. Thus, we translate /'s to .'s in order to
+ // accomondate gcj's internal representation.
+ char *buffer = (char*) __builtin_alloca (len);
for (int i = 0; i < len; i++)
{
if (s[i] == '/')
buffer[i] = '.';
else
- buffer[i] = (char) s[i];
+ buffer[i] = s[i];
}
-
pool_data[index].utf8 = _Jv_makeUtf8Const (buffer, len);
- pool_tags[index] = JV_CONSTANT_Utf8;
}
break;
@@ -1152,8 +1161,7 @@
_Jv_ushort type_index = get2u (this_data+2);
check_tag (name_index, JV_CONSTANT_Utf8);
- prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
-
+ prepare_pool_entry (name_index, JV_CONSTANT_Utf8, false);
check_tag (type_index, JV_CONSTANT_Utf8);
prepare_pool_entry (type_index, JV_CONSTANT_Utf8);
@@ -1572,7 +1580,7 @@
_Jv_Method *method = &def->methods[mth_index];
check_tag (name, JV_CONSTANT_Utf8);
- prepare_pool_entry (name, JV_CONSTANT_Utf8);
+ prepare_pool_entry (name, JV_CONSTANT_Utf8, false);
method->name = pool_data[name].utf8;
check_tag (desc, JV_CONSTANT_Utf8);
More information about the Gcc-patches
mailing list