This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
better error on VerifyError
- From: Per Bothner <per at bothner dot com>
- To: tromey at redhat dot com, java at gcc dot gnu dot org
- Date: Tue, 15 Jan 2002 13:19:18 -0800
- Subject: better error on VerifyError
Compiling Kawa gave me a VerifyError, but it was very uninformative,
without specifying the class of the method.
I made a partial patch to improve the situation, for the particular
error I experience, and I now get:
Exception in thread "main" java.lang.VerifyError: verification failed at
PC 3 in gnu.xquery.lang.XQuery:getFormat: incompatible return type
at 0x40248970: java.lang.Throwable.Throwable(java.lang.String)
(/home/bothner/GNU/install-gcc/lib/libgcj.so.2)
Before checking it in, I'd like to get some feedback (especially from
Tom, of course) on how we want to do this more generally.
The basic problem is that we need to pass the verifier state, or at
least the current method, to the verify_fail routine. However,
most calls to verify_fail are in either static methods, or in methods
of the inner classes type or state. One solution is to make all
the methods non-static, and to add a field to type that points back
to the _Jv_ByteCodeVerifier object. The alternative is to explicitly
pass _Jv_ByteCodeVerifier in method calls. The tradoff is an extra
for each each type and state object vs an extra parameter in each
method call. I lean towards the latter. The former probably
requires fewer changes; however, however, it is easier to make the
fixes on an incremental bases with the latter. For example,
type::set_uninitalized becomes:
void set_uninitialized (int npc,
_Jv_ByteCodeVerifier* verifier=NULL)
{
... verify_fail("...", verifier);
}
Then we can incrementally fix the callers of set_uninitialized to
pass the verifier reference, and so on.
--
--Per Bothner
per@bothner.com http://www.bothner.com/per/
Index: verify.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/verify.cc,v
retrieving revision 1.25
diff -u -p -r1.25 verify.cc
--- verify.cc 2001/12/10 01:18:30 1.25
+++ verify.cc 2002/01/15 21:00:43
@@ -44,6 +44,9 @@ details. */
static void verify_fail (char *msg, jint pc = -1)
__attribute__ ((__noreturn__));
+static void verify_fail (char *msg, _Jv_BytecodeVerifier *verifier, jint pc = -1)
+ __attribute__ ((__noreturn__));
+
static void debug_print (const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
@@ -107,10 +110,12 @@ private:
// The exceptions.
_Jv_InterpException *exception;
+public:
// Defining class.
jclass current_class;
// This method.
_Jv_InterpMethod *current_method;
+private:
// A linked list of utf8 objects we allocate. This is really ugly,
// but without this our utf8 objects would be collected.
@@ -1898,7 +1903,7 @@ private:
{
type rt = compute_return_type (current_method->self->signature);
if (! rt.compatible (onstack))
- verify_fail ("incompatible return type", start_PC);
+ verify_fail ("incompatible return type", this, start_PC);
}
// Initialize the stack for the new method. Returns true if this
@@ -2892,6 +2897,12 @@ _Jv_VerifyMethod (_Jv_InterpMethod *meth
static void
verify_fail (char *s, jint pc)
{
+ verify_fail(s, NULL, pc);
+}
+
+static void
+verify_fail (char *s, _Jv_BytecodeVerifier *verifier, jint pc)
+{
using namespace java::lang;
StringBuffer *buf = new StringBuffer ();
@@ -2900,6 +2911,14 @@ verify_fail (char *s, jint pc)
{
buf->append (JvNewStringLatin1 (" at PC "));
buf->append (pc);
+ }
+ if (verifier != NULL)
+ {
+ _Jv_InterpMethod *method = verifier->current_method;
+ buf->append (JvNewStringLatin1 (" in "));
+ buf->append (verifier->defining_class->getName());
+ buf->append ((jchar) ':');
+ buf->append (JvNewStringUTF (method->get_method()->name->data));
}
buf->append (JvNewStringLatin1 (": "));
buf->append (JvNewStringLatin1 (s));