aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libjava/ChangeLog12
-rw-r--r--libjava/include/jvm.h4
-rw-r--r--libjava/java/lang/Object.h3
-rw-r--r--libjava/java/lang/Object.java8
-rw-r--r--libjava/link.cc76
5 files changed, 85 insertions, 18 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index c920ffe..57f1d4d 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,15 @@
+2005-12-08 Andrew Haley <aph@redhat.com>
+
+ * java/lang/Object.h (throwNoSuchMethodError): New method.
+ * java/lang/Object.java (throwNoSuchMethodError): New method.
+ * include/jvm.h (_Jv_ThrowNoSuchFieldError): Declare.
+ * link.cc (_Jv_ThrowNoSuchFieldError): New.
+ (link_symbol_table): Don't throw a NoSuchFieldError if a field is
+ missing. Instead, set the otable entry to zero.
+ (link_symbol_table): If we don't find a nonstatic method, insert
+ the vtable offset of Object.throwNoSuchMethodError() into the
+ otable.
+
2005-12-05 Tom Tromey <tromey@redhat.com>
* testsuite/libjava.compile/rh174912.java: New file.
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 8d34059..85caa40 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -442,6 +442,10 @@ extern "C" void _Jv_ThrowBadArrayIndex (jint bad_index)
__attribute__((noreturn));
extern "C" void _Jv_ThrowNullPointerException (void)
__attribute__((noreturn));
+extern "C" void _Jv_ThrowNoSuchMethodError (void)
+ __attribute__((noreturn));
+extern "C" void _Jv_ThrowNoSuchFieldError (int)
+ __attribute__((noreturn));
extern "C" jobject _Jv_NewArray (jint type, jint size)
__attribute__((__malloc__));
extern "C" jobject _Jv_NewMultiArray (jclass klass, jint dims, ...)
diff --git a/libjava/java/lang/Object.h b/libjava/java/lang/Object.h
index bf68a72..54fd447 100644
--- a/libjava/java/lang/Object.h
+++ b/libjava/java/lang/Object.h
@@ -83,6 +83,9 @@ private:
// Initialize the sync_info field. Not called with JV_HASH_SYNCHRONIZATION.
void sync_init (void);
+
+public:
+ virtual void throwNoSuchMethodError (void);
};
#endif /* __JAVA_LANG_OBJECT_H__ */
diff --git a/libjava/java/lang/Object.java b/libjava/java/lang/Object.java
index dbe3411..e81a48a 100644
--- a/libjava/java/lang/Object.java
+++ b/libjava/java/lang/Object.java
@@ -506,6 +506,14 @@ public class Object
// completeness (some day we'll be able to auto-generate Object.h).
private final native void sync_init();
+ // If we fail to find a method at class loading time we put the
+ // vtable index of this method in its place: any attempt to call
+ // that method will result in an error.
+ void throwNoSuchMethodError()
+ {
+ throw new NoSuchMethodError("in " + getClass());
+ }
+
// Note that we don't mention the sync_info field here. If we do,
// jc1 will not work correctly.
}
diff --git a/libjava/link.cc b/libjava/link.cc
index 2d6b199..7070d72 100644
--- a/libjava/link.cc
+++ b/libjava/link.cc
@@ -713,6 +713,17 @@ _Jv_ThrowNoSuchMethodError ()
throw new java::lang::NoSuchMethodError;
}
+// Throw a NoSuchFieldError. Called by compiler-generated code when
+// an otable entry is zero. OTABLE_INDEX is the index in the caller's
+// otable that refers to the missing field. This index may be used to
+// print diagnostic information about the field.
+void
+_Jv_ThrowNoSuchFieldError (int /* otable_index */)
+{
+ throw new java::lang::NoSuchFieldError;
+}
+
+
// This is put in empty vtable slots.
void
_Jv_ThrowAbstractMethodError ()
@@ -915,12 +926,6 @@ _Jv_Linker::link_symbol_table (jclass klass)
_Jv_Utf8Const *signature = sym.signature;
- {
- static char *bounce = (char *)_Jv_ThrowNoSuchMethodError;
- ptrdiff_t offset = (char *)(klass->vtable) - bounce;
- klass->otable->offsets[index] = offset;
- }
-
if (target_class == NULL)
throw new java::lang::NoClassDefFoundError
(_Jv_NewStringUTF (sym.class_name->chars()));
@@ -948,14 +953,41 @@ _Jv_Linker::link_symbol_table (jclass klass)
meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
sym.signature);
- if (meth != NULL)
+ // Every class has a throwNoSuchMethodErrorIndex method that
+ // it inherits from java.lang.Object. Find its vtable
+ // offset.
+ static int throwNoSuchMethodErrorIndex;
+ if (throwNoSuchMethodErrorIndex == 0)
{
- int offset = _Jv_VTable::idx_to_offset (meth->index);
- if (offset == -1)
- JvFail ("Bad method index");
- JvAssert (meth->index < target_class->vtable_method_count);
- klass->otable->offsets[index] = offset;
+ Utf8Const* name
+ = _Jv_makeUtf8Const ("throwNoSuchMethodError",
+ strlen ("throwNoSuchMethodError"));
+ _Jv_Method* meth
+ = _Jv_LookupDeclaredMethod (&java::lang::Object::class$,
+ name, gcj::void_signature);
+ throwNoSuchMethodErrorIndex
+ = _Jv_VTable::idx_to_offset (meth->index);
}
+
+ // If we don't find a nonstatic method, insert the
+ // vtable index of Object.throwNoSuchMethodError().
+ // This defers the missing method error until an attempt
+ // is made to execute it.
+ {
+ int offset;
+
+ if (meth != NULL)
+ offset = _Jv_VTable::idx_to_offset (meth->index);
+ else
+ offset = throwNoSuchMethodErrorIndex;
+
+ if (offset == -1)
+ JvFail ("Bad method index");
+ JvAssert (meth->index < target_class->vtable_method_count);
+
+ klass->otable->offsets[index] = offset;
+ }
+
if (debug_link)
fprintf (stderr, " offsets[%d] = %d (class %s@%p : %s(%s))\n",
(int)index,
@@ -971,12 +1003,20 @@ _Jv_Linker::link_symbol_table (jclass klass)
{
wait_for_state(target_class, JV_STATE_PREPARED);
jclass found_class;
- _Jv_Field *the_field = find_field (klass, target_class, &found_class,
- sym.name, sym.signature);
- if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
- throw new java::lang::IncompatibleClassChangeError;
- else
- klass->otable->offsets[index] = the_field->u.boffset;
+ _Jv_Field *the_field = NULL;
+ try
+ {
+ the_field = find_field (klass, target_class, &found_class,
+ sym.name, sym.signature);
+ if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
+ throw new java::lang::IncompatibleClassChangeError;
+ else
+ klass->otable->offsets[index] = the_field->u.boffset;
+ }
+ catch (java::lang::NoSuchFieldError *err)
+ {
+ klass->otable->offsets[index] = 0;
+ }
}
}