summaryrefslogtreecommitdiff
path: root/libjava/resolve.cc
diff options
context:
space:
mode:
authorbryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4>2000-03-07 09:52:56 +0000
committerbryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4>2000-03-07 09:52:56 +0000
commit2e580b09072b4256e1ef4b43e58d2e9845566e72 (patch)
tree3d1200ab45d37376fcbddeff18a6199837857dca /libjava/resolve.cc
parent4095293c7d50d2367f6f60a3d9f8feaa1a932d6d (diff)
downloadgcc-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.cc147
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)