This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Patch: FYI: gcjh and PR 1200
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Cc: Gcc Patch List <gcc-patches at gcc dot gnu dot org>
- Date: 07 May 2002 19:47:37 -0600
- Subject: Patch: FYI: gcjh and PR 1200
- Reply-to: tromey at redhat dot com
I'm checking this in on the trunk.
Today while digging for some other information I ran across an old
patch to fix this PR. The patch was never cleaned up as I had asked,
so it was never checked in. I rewrote the patch based on the same
idea, but with a completely new implementation.
This also fixes a lurking bug -- a `jweak' is not the same thing as a
`java.lang.ref.WeakReference'. JNI weak references are their own
thing.
Tested on x86 against the jni.exp part of the test suite.
(This code only matters for `gcjh -jni'.)
Tom
Index: ChangeLog
from Tom Tromey <tromey@redhat.com>
Fix for PR java/1200:
* gjavah.c (throwable_p): New function.
(decode_signature_piece): Use it. A `WeakReference' isn't the
same as a `jweak'.
Include hashtab.h.
(gcjh_streq): New function.
Index: gjavah.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/gjavah.c,v
retrieving revision 1.86
diff -u -r1.86 gjavah.c
--- gjavah.c 12 Apr 2002 14:28:49 -0000 1.86
+++ gjavah.c 8 May 2002 01:35:42 -0000
@@ -33,6 +33,7 @@
#include "javaop.h"
#include "java-tree.h"
#include "java-opcodes.h"
+#include "hashtab.h"
#include <getopt.h>
@@ -142,6 +143,8 @@
static void print_field_name PARAMS ((FILE *, JCF *, int, JCF_u2));
static const unsigned char *super_class_name PARAMS ((JCF *, int *));
static void print_include PARAMS ((FILE *, const unsigned char *, int));
+static int gcjh_streq PARAMS ((const void *p1, const void *p2));
+static int throwable_p PARAMS ((const unsigned char *signature));
static const unsigned char *decode_signature_piece
PARAMS ((FILE *, const unsigned char *, const unsigned char *, int *));
static void print_class_decls PARAMS ((FILE *, JCF *, int));
@@ -1091,6 +1094,111 @@
}
}
+/* Like strcmp, but invert the return result for the hash table. This
+ should probably be in hashtab.c to complement the existing string
+ hash function. */
+static int
+gcjh_streq (p1, p2)
+ const void *p1, *p2;
+{
+ return ! strcmp ((char *) p1, (char *) p2);
+}
+
+/* Return 1 if the initial (L<classname>;) part of SIGNATURE names a
+ subclass of throwable, or 0 if not. */
+static int
+throwable_p (signature)
+ const unsigned char *signature;
+{
+ int length;
+ unsigned char *current;
+ int i;
+ int result = 0;
+
+ /* We keep two hash tables of class names. In one we list all the
+ classes which are subclasses of Throwable. In the other we will
+ all other classes. We keep two tables to make the code a bit
+ simpler; we don't have to have a structure mapping class name to
+ a `throwable?' bit. */
+ static htab_t throw_hash;
+ static htab_t non_throw_hash;
+ static int init_done = 0;
+
+ if (! init_done)
+ {
+ PTR *slot;
+ const unsigned char *str;
+
+ /* Self-initializing. The cost of this really doesn't matter.
+ We also don't care about freeing these, either. */
+ throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
+ (htab_del) free);
+ non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
+ (htab_del) free);
+
+ /* Make sure the root classes show up in the tables. */
+ str = strdup ("java.lang.Throwable");
+ slot = htab_find_slot (throw_hash, str, INSERT);
+ *slot = (PTR) str;
+
+ str = strdup ("java.lang.Object");
+ slot = htab_find_slot (non_throw_hash, str, INSERT);
+ *slot = (PTR) str;
+
+ init_done = 1;
+ }
+
+ for (length = 0; signature[length] != ';'; ++length)
+ ;
+ current = (unsigned char *) ALLOC (length);
+ for (i = 1; signature[i] != ';'; ++i)
+ current[i - 1] = signature[i] == '/' ? '.' : signature[i];
+ current[i - 1] = '\0';
+
+ /* We don't compute the hash slot here because the table might be
+ modified by the recursion. In that case the slot could be
+ invalidated. */
+ if (htab_find (throw_hash, current))
+ result = 1;
+ else if (htab_find (non_throw_hash, current))
+ result = 0;
+ else
+ {
+ JCF jcf;
+ PTR *slot;
+ const char *classfile_name = find_class (current, strlen (current),
+ &jcf, 0);
+
+ if (! classfile_name)
+ {
+ fprintf (stderr, "couldn't find class %s\n", current);
+ found_error = 1;
+ return 0;
+ }
+ if (jcf_parse_preamble (&jcf) != 0
+ || jcf_parse_constant_pool (&jcf) != 0
+ || verify_constant_pool (&jcf) > 0)
+ {
+ fprintf (stderr, "parse error while reading %s\n", classfile_name);
+ found_error = 1;
+ return 0;
+ }
+ jcf_parse_class (&jcf);
+
+ result = throwable_p (super_class_name (&jcf, NULL));
+ slot = htab_find_slot (result ? throw_hash : non_throw_hash,
+ current, INSERT);
+ *slot = current;
+ current = NULL;
+
+ JCF_FINISH (&jcf);
+ }
+
+ if (current)
+ free (current);
+ return result;
+}
+
/* Print one piece of a signature. Returns pointer to next parseable
character on success, NULL on error. */
static const unsigned char *
@@ -1204,24 +1312,15 @@
case 'L':
if (flag_jni)
{
- /* We know about certain types and special-case their
- names.
- FIXME: something like java.lang.Exception should be
- printed as `jthrowable', because it is a subclass. This
- means that gcjh must read the entire hierarchy and
- comprehend it. */
+ /* We know about certain types and special-case their names. */
if (! strncmp (signature, "Ljava/lang/String;",
sizeof ("Ljava/lang/String;") -1))
ctype = "jstring";
else if (! strncmp (signature, "Ljava/lang/Class;",
sizeof ("Ljava/lang/Class;") - 1))
ctype = "jclass";
- else if (! strncmp (signature, "Ljava/lang/Throwable;",
- sizeof ("Ljava/lang/Throwable;") - 1))
+ else if (throwable_p (signature))
ctype = "jthrowable";
- else if (! strncmp (signature, "Ljava/lang/ref/WeakReference;",
- sizeof ("Ljava/lang/ref/WeakReference;") - 1))
- ctype = "jweak";
else
ctype = "jobject";