diff options
-rw-r--r-- | libjava/ChangeLog | 12 | ||||
-rw-r--r-- | libjava/include/jvm.h | 4 | ||||
-rw-r--r-- | libjava/java/lang/Object.h | 3 | ||||
-rw-r--r-- | libjava/java/lang/Object.java | 8 | ||||
-rw-r--r-- | libjava/link.cc | 76 |
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; + } } } |