diff options
author | bryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-03-07 09:52:56 +0000 |
---|---|---|
committer | bryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-03-07 09:52:56 +0000 |
commit | 2e580b09072b4256e1ef4b43e58d2e9845566e72 (patch) | |
tree | 3d1200ab45d37376fcbddeff18a6199837857dca /libjava/resolve.cc | |
parent | 4095293c7d50d2367f6f60a3d9f8feaa1a932d6d (diff) | |
download | gcc-2e580b09072b4256e1ef4b43e58d2e9845566e72.tar.gz |
2000-03-07 Bryce McKinlay <bryce@albatross.co.nz>
* resolve.cc (_Jv_SearchMethodInClass): New function.
(_Jv_ResolvePoolEntry): Search superinterfaces for interface
methods.
* java/lang/Class.h (_Jv_SearchMethodInClass): New prototype.
2000-03-07 Bryce McKinlay <bryce@albatross.co.nz>
* java/lang/Class.h (union _Jv_IDispatchTable): New declaration.
(struct _Jv_ifaces): New declaration.
JV_CLASS: New macro definition.
(getComponentType): Relocate below isArray() for inlining.
(getModifiers): Declare `inline'.
(getSuperclass): Ditto.
(isArray): Ditto.
(isPrimitive): Ditto.
(_Jv_IsAssignableFrom): New prototype.
(_Jv_LookupInterfaceMethodIdx): New prototype. Predeclare with "C"
linkage.
(_Jv_InitClass): Move from natClass.cc. Declare `inline'.
Check for JV_STATE_DONE before invoking initializeClass().
(_Jv_PrepareConstantTimeTables): New prototype.
(_Jv_GetInterfaces): Ditto.
(_Jv_GenerateITable): Ditto.
(_Jv_GetMethodString): Ditto.
(_Jv_AppendPartialITable): Ditto.
(_Jv_FindIIndex): Ditto.
depth, ancestors, idt: New class fields.
* java/lang/natClass.cc (isAssignableFrom): Move functionality to
inline function `_Jv_IsAssignableFrom'. Use that function.
(isInstance): Declare `inline'.
(initializeClass): Get lock on class before checking `state'. Unlock
before calling resolveClass0. Call _Jv_PrepareConstantTimeTables
with the lock held.
(_Jv_LookupInterfaceMethod): Use _Jv_GetMessageString.
(_Jv_IsAssignableFrom): New inline function. Test assignability
using class->depth and ancestor table.
(_Jv_IsInstanceOf): Use _Jv_IsAssignableFrom.
(_Jv_CheckCast): Move from prims.cc. Use JV_CLASS and
_Jv_IsAssignableFrom.
(_Jv_CheckArrayStore): Ditto.
(_Jv_LookupInterfaceMethodIdx): New function.
INITIAL_IOFFSETS_LEN, INITIAL_IFACES_LEN: New #defines.
(_Jv_PrepareConstantTimeTables): New function.
(_Jv_IndexOf): Ditto.
(_Jv_GetInterfaces): Ditto.
(_Jv_GenerateITable): Ditto.
(_Jv_GetMethodString): Ditto.
(_Jv_AppendPartialITable): Ditto.
iindex_mutex, iindex_mutex_initialized: New static fields.
(_Jv_FindIIndex): New function.
* java/lang/natClassLoader.cc (_Jv_NewClass): Set new jclass fields.
* prims.cc (_Jv_CheckCast): Moved to natClass.cc.
(_Jv_CheckArrayStore): Ditto.
(JvNewCharArray, JvNewBooleanArray, JvNewByteArray, JvNewShortArray,
JvNewIntArray, JvNewLongArray, JvNewFloatArray, JvNewDoubleArray):
Moved to gcj/array.h.
(_Jv_Realloc): New function.
* gcj/cni.h: Move _Jv_PrimClass definitions to gcj/array.h.
* gcj/array.h: _Jv_PrimClass definitions moved from gcj/cni.h.
(JvNewCharArray, JvNewBooleanArray, JvNewByteArray,
JvNewShortArray, JvNewIntArray, JvNewLongArray, JvNewFloatArray,
JvNewDoubleArray): Implementations moved from prims.cc and
declared `inline'.
* gcj/javaprims.h (_Jv_Realloc): Prototype.
* include/jvm.h (_Jv_LookupInterfaceMethodIdx): Prototype.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@32382 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/resolve.cc')
-rw-r--r-- | libjava/resolve.cc | 147 |
1 files changed, 101 insertions, 46 deletions
diff --git a/libjava/resolve.cc b/libjava/resolve.cc index 634c08fa11e..b4713615304 100644 --- a/libjava/resolve.cc +++ b/libjava/resolve.cc @@ -24,6 +24,7 @@ details. */ #include <java/lang/InternalError.h> #include <java/lang/VirtualMachineError.h> #include <java/lang/NoSuchFieldError.h> +#include <java/lang/NoSuchMethodError.h> #include <java/lang/ClassFormatError.h> #include <java/lang/IllegalAccessError.h> #include <java/lang/AbstractMethodError.h> @@ -230,59 +231,78 @@ _Jv_ResolvePoolEntry (jclass klass, int index) _Jv_Method *the_method = 0; jclass found_class = 0; - // we make a loop here, because methods are allowed to be moved to - // a super class, and still be visible.. (binary compatibility). + // First search the class itself. + the_method = _Jv_SearchMethodInClass (owner, klass, + method_name, method_signature); - for (jclass cls = owner; cls != 0; cls = cls->getSuperclass ()) - { - for (int i = 0; i < cls->method_count; i++) - { - _Jv_Method *method = &cls->methods[i]; - if ( (!_Jv_equalUtf8Consts (method->name, - method_name)) - || (!_Jv_equalUtf8Consts (method->signature, - method_signature))) - continue; + if (the_method != 0) + { + found_class = owner; + goto end_of_method_search; + } - if (cls == klass - || ((method->accflags & Modifier::PUBLIC) != 0) - || (((method->accflags & Modifier::PROTECTED) != 0) - && cls->isAssignableFrom (klass)) - || (((method->accflags & Modifier::PRIVATE) == 0) - && _Jv_ClassNameSamePackage (cls->name, - klass->name))) - { - // FIXME: if (cls->loader != klass->loader), then we - // must actually check that the types of arguments - // correspond. That is, for each argument type, and - // the return type, doing _Jv_FindClassFromSignature - // with either loader should produce the same result, - // i.e., exactly the same jclass object. JVMS 5.4.3.3 - - the_method = method; + // If we are resolving an interface method, search the interface's + // superinterfaces (A superinterface is not an interface's superclass - + // a superinterface is implemented by the interface). + if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref) + { + _Jv_ifaces ifaces; + ifaces.count = 0; + ifaces.len = 4; + ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *)); + + _Jv_GetInterfaces (owner, &ifaces); + + for (int i=0; i < ifaces.count; i++) + { + jclass cls = ifaces.list[i]; + the_method = _Jv_SearchMethodInClass (cls, klass, method_name, + method_signature); + if (the_method != 0) + { found_class = cls; - - - if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref) - vtable_index = -1; - else - vtable_index = _Jv_DetermineVTableIndex - (cls, method_name, method_signature); - - if (vtable_index == 0) - throw_incompatible_class_change_error - (JvNewStringLatin1 ("method not found")); - - goto end_of_method_search; - } - else - { - JvThrow (new java::lang::IllegalAccessError); + break; } } + + _Jv_Free (ifaces.list); + + if (the_method != 0) + goto end_of_method_search; + } + + // Finally, search superclasses. + for (jclass cls = owner->getSuperclass (); cls != 0; + cls = cls->getSuperclass ()) + { + the_method = _Jv_SearchMethodInClass (cls, klass, + method_name, method_signature); + if (the_method != 0) + { + found_class = cls; + break; + } } end_of_method_search: + + // FIXME: if (cls->loader != klass->loader), then we + // must actually check that the types of arguments + // correspond. That is, for each argument type, and + // the return type, doing _Jv_FindClassFromSignature + // with either loader should produce the same result, + // i.e., exactly the same jclass object. JVMS 5.4.3.3 + + if (pool->tags[index] == JV_CONSTANT_InterfaceMethodref) + vtable_index = -1; + else + vtable_index = _Jv_DetermineVTableIndex + (found_class, method_name, method_signature); + + if (vtable_index == 0) + throw_incompatible_class_change_error + (JvNewStringLatin1 ("method not found")); + if (the_method == 0) { jstring msg = JvNewStringLatin1 ("method "); @@ -290,7 +310,7 @@ _Jv_ResolvePoolEntry (jclass klass, int index) msg = msg->concat (JvNewStringLatin1(".")); msg = msg->concat (_Jv_NewStringUTF (method_name->data)); msg = msg->concat (JvNewStringLatin1(" was not found.")); - JvThrow(new java::lang::NoSuchFieldError (msg)); + JvThrow(new java::lang::NoSuchMethodError (msg)); } pool->data[index].rmethod = @@ -307,6 +327,41 @@ _Jv_ResolvePoolEntry (jclass klass, int index) return pool->data[index]; } +// Find a method declared in the cls that is referenced from klass and +// perform access checks. +_Jv_Method * +_Jv_SearchMethodInClass (jclass cls, jclass klass, + _Jv_Utf8Const *method_name, + _Jv_Utf8Const *method_signature) +{ + using namespace java::lang::reflect; + + for (int i = 0; i < cls->method_count; i++) + { + _Jv_Method *method = &cls->methods[i]; + if ( (!_Jv_equalUtf8Consts (method->name, + method_name)) + || (!_Jv_equalUtf8Consts (method->signature, + method_signature))) + continue; + + if (cls == klass + || ((method->accflags & Modifier::PUBLIC) != 0) + || (((method->accflags & Modifier::PROTECTED) != 0) + && cls->isAssignableFrom (klass)) + || (((method->accflags & Modifier::PRIVATE) == 0) + && _Jv_ClassNameSamePackage (cls->name, + klass->name))) + { + return method; + } + else + { + JvThrow (new java::lang::IllegalAccessError); + } + } + return 0; +} void _Jv_ResolveField (_Jv_Field *field, java::lang::ClassLoader *loader) |