resolve.cc (_Jv_SearchMethodInClass): New function.

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.

From-SVN: r32382
This commit is contained in:
Bryce McKinlay 2000-03-07 09:52:56 +00:00 committed by Bryce McKinlay
parent 173f556ccc
commit ddf0fc6c9f
10 changed files with 776 additions and 228 deletions

View file

@ -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++)
if (the_method != 0)
{
found_class = owner;
goto end_of_method_search;
}
// 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++)
{
_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)))
{
// 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;
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)