diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 8dfbcf42016..4f4a7e14aa3 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,17 @@ +2002-12-05 Tom Tromey + + * java/lang/Class.h (_Jv_SetVTableEntries): Updated declaration. + * resolve.cc: Don't include AbstractMethodError.h. + (_Jv_abstractMethodError): Removed. + * defineclass.cc (handleMethodsBegin): Initialize method index to + -1. + * java/lang/natClass.cc (_Jv_LayoutVTableMethods): Don't set + method index for "new" final method. + (_Jv_SetVTableEntries): Compare index against -1 instead of using + isVirtualMethod. Added `flags' argument. + (_Jv_MakeVTable): Throw exception for abstract method in concrete + class. + 2002-12-04 Tom Tromey * java/net/SocketPermission.java (hashCode): Rewrote. diff --git a/libjava/defineclass.cc b/libjava/defineclass.cc index 6a250dadda6..dc350028cdd 100644 --- a/libjava/defineclass.cc +++ b/libjava/defineclass.cc @@ -1184,15 +1184,17 @@ void _Jv_ClassReader::handleFieldsEnd () void _Jv_ClassReader::handleMethodsBegin (int count) { - def->methods = (_Jv_Method*) - _Jv_AllocBytes (sizeof (_Jv_Method)*count); + def->methods = (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method) * count); def->interpreted_methods = (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *) * count); for (int i = 0; i < count; i++) - def->interpreted_methods[i] = 0; + { + def->interpreted_methods[i] = 0; + def->methods[i].index = (_Jv_ushort) -1; + } def->method_count = count; } @@ -1376,12 +1378,14 @@ throw_internal_error (char *msg) throw new java::lang::InternalError (JvNewStringLatin1 (msg)); } -static void throw_incompatible_class_change_error (jstring msg) +static void +throw_incompatible_class_change_error (jstring msg) { throw new java::lang::IncompatibleClassChangeError (msg); } -static void throw_class_circularity_error (jstring msg) +static void +throw_class_circularity_error (jstring msg) { throw new java::lang::ClassCircularityError (msg); } diff --git a/libjava/java/lang/Class.h b/libjava/java/lang/Class.h index 6fb918a90dc..4ccf3886431 100644 --- a/libjava/java/lang/Class.h +++ b/libjava/java/lang/Class.h @@ -325,7 +325,7 @@ private: friend jshort _Jv_FindIIndex (jclass *, jshort *, jshort); friend void _Jv_LinkOffsetTable (jclass); friend void _Jv_LayoutVTableMethods (jclass klass); - friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *); + friend void _Jv_SetVTableEntries (jclass, _Jv_VTable *, jboolean *); friend void _Jv_MakeVTable (jclass); // Return array class corresponding to element type KLASS, creating it if diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index 68fbd54d754..bafac789b0d 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -97,7 +97,7 @@ java::lang::Class::forName (jstring className) java::lang::Class *klass = NULL; try { - for (int i=1; !klass; i++) + for (int i = 1; !klass; i++) { klass = t->classAt (i); } @@ -1556,7 +1556,7 @@ _Jv_LinkOffsetTable(jclass klass) } // Returns true if METH should get an entry in a VTable. -static bool +static jboolean isVirtualMethod (_Jv_Method *meth) { using namespace java::lang::reflect; @@ -1574,7 +1574,7 @@ _Jv_LayoutVTableMethods (jclass klass) if (klass->vtable != NULL || klass->isInterface() || klass->vtable_method_count != -1) return; - + jclass superclass = klass->superclass; if (superclass != NULL && superclass->vtable_method_count == -1) @@ -1582,48 +1582,59 @@ _Jv_LayoutVTableMethods (jclass klass) JvSynchronize sync (superclass); _Jv_LayoutVTableMethods (superclass); } - + int index = (superclass == NULL ? 0 : superclass->vtable_method_count); for (int i = 0; i < klass->method_count; ++i) { _Jv_Method *meth = &klass->methods[i]; _Jv_Method *super_meth = NULL; - - if (!isVirtualMethod(meth)) - continue; - + + if (! isVirtualMethod (meth)) + continue; + if (superclass != NULL) super_meth = _Jv_LookupDeclaredMethod (superclass, meth->name, meth->signature); - + if (super_meth) meth->index = super_meth->index; - else + else if (! (meth->accflags & java::lang::reflect::Modifier::FINAL)) meth->index = index++; } - + klass->vtable_method_count = index; } -// Set entries in VTABLE for virtual methods declared in KLASS. If KLASS has -// an immediate abstract parent, recursivly do its methods first. +// Set entries in VTABLE for virtual methods declared in KLASS. If +// KLASS has an immediate abstract parent, recursively do its methods +// first. FLAGS is used to determine which slots we've actually set. void -_Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable) +_Jv_SetVTableEntries (jclass klass, _Jv_VTable *vtable, jboolean *flags) { using namespace java::lang::reflect; jclass superclass = klass->getSuperclass(); if (superclass != NULL && (superclass->getModifiers() & Modifier::ABSTRACT)) - _Jv_SetVTableEntries (superclass, vtable); - + _Jv_SetVTableEntries (superclass, vtable, flags); + for (int i = klass->method_count - 1; i >= 0; i--) { _Jv_Method *meth = &klass->methods[i]; - if (!isVirtualMethod(meth)) + if (meth->index == (_Jv_ushort) -1) continue; - vtable->set_method(meth->index, meth->ncode); + if ((meth->accflags & Modifier::ABSTRACT)) + { + // FIXME: we should set abstract slots to a function that + // throws AbstractMethodError. How can we do that on IA-64? + flags[meth->index] = false; + } + else + { + vtable->set_method(meth->index, meth->ncode); + flags[meth->index] = true; + } } } @@ -1639,7 +1650,7 @@ _Jv_MakeVTable (jclass klass) if (klass->vtable != NULL || klass->isInterface() || (klass->accflags & Modifier::ABSTRACT)) return; - + // out before we can create a vtable. if (klass->vtable_method_count == -1) _Jv_LayoutVTableMethods (klass); @@ -1647,7 +1658,11 @@ _Jv_MakeVTable (jclass klass) // Allocate the new vtable. _Jv_VTable *vtable = _Jv_VTable::new_vtable (klass->vtable_method_count); klass->vtable = vtable; - + + jboolean flags[klass->vtable_method_count]; + for (int i = 0; i < klass->vtable_method_count; ++i) + flags[i] = false; + // Copy the vtable of the closest non-abstract superclass. jclass superclass = klass->superclass; if (superclass != NULL) @@ -1662,7 +1677,10 @@ _Jv_MakeVTable (jclass klass) } for (int i = 0; i < superclass->vtable_method_count; ++i) - vtable->set_method (i, superclass->vtable->get_method (i)); + { + vtable->set_method (i, superclass->vtable->get_method (i)); + flags[i] = true; + } } // Set the class pointer and GC descriptor. @@ -1671,5 +1689,14 @@ _Jv_MakeVTable (jclass klass) // For each virtual declared in klass and any immediate abstract // superclasses, set new vtable entry or override an old one. - _Jv_SetVTableEntries (klass, vtable); + _Jv_SetVTableEntries (klass, vtable, flags); + + // It is an error to have an abstract method in a concrete class. + if (! (klass->accflags & Modifier::ABSTRACT)) + { + for (int i = 0; i < klass->vtable_method_count; ++i) + if (! flags[i]) + // FIXME: messsage. + throw new java::lang::AbstractMethodError (); + } } diff --git a/libjava/resolve.cc b/libjava/resolve.cc index e9fe4ad5af2..e195c333cc8 100644 --- a/libjava/resolve.cc +++ b/libjava/resolve.cc @@ -363,13 +363,6 @@ _Jv_SearchMethodInClass (jclass cls, jclass klass, return 0; } -/* this is installed in place of abstract methods */ -static void -_Jv_abstractMethodError () -{ - throw new java::lang::AbstractMethodError; -} - void _Jv_PrepareClass(jclass klass) {