mirror of git://gcc.gnu.org/git/gcc.git
jvm.h (_Jv_Linker::maybe_adjust_signature): New.
2006-06-07 Andrew Haley <aph@redhat.com> * include/jvm.h (_Jv_Linker::maybe_adjust_signature): New. (_Jv_Linker::uaddr): New. * link.cc (resolve_pool_entry): Call search_method_in_superclasses instead of an open-coded loop around search_method_in_class. (search_method_in_class): Add a new arg, check_perms. (search_method_in_superclasses): New. (link_symbol_table): Call maybe_adjust_signature() to extract the least significnt bit of the signature pointer. Do this three times, for instace method calls, static methods, and interfaces. Call search_method_in_superclasses() instead of _Jv_LookupDeclaredMethod. (typedef uaddr): Delete. From-SVN: r114486
This commit is contained in:
parent
f70b22c942
commit
297750da03
|
@ -1,3 +1,18 @@
|
||||||
|
2006-06-07 Andrew Haley <aph@redhat.com>
|
||||||
|
|
||||||
|
* include/jvm.h (_Jv_Linker::maybe_adjust_signature): New.
|
||||||
|
(_Jv_Linker::uaddr): New.
|
||||||
|
* link.cc (resolve_pool_entry): Call search_method_in_superclasses
|
||||||
|
instead of an open-coded loop around search_method_in_class.
|
||||||
|
(search_method_in_class): Add a new arg, check_perms.
|
||||||
|
(search_method_in_superclasses): New.
|
||||||
|
(link_symbol_table): Call maybe_adjust_signature() to extract the
|
||||||
|
least significnt bit of the signature pointer. Do this three
|
||||||
|
times, for instace method calls, static methods, and interfaces.
|
||||||
|
Call search_method_in_superclasses() instead of
|
||||||
|
_Jv_LookupDeclaredMethod.
|
||||||
|
(typedef uaddr): Delete.
|
||||||
|
|
||||||
2006-06-07 Thomas Fitzsimmons <fitzsim@redhat.com>
|
2006-06-07 Thomas Fitzsimmons <fitzsim@redhat.com>
|
||||||
|
|
||||||
* scripts/makemake.tcl (emit_bc_rule): Do not skip
|
* scripts/makemake.tcl (emit_bc_rule): Do not skip
|
||||||
|
|
|
@ -239,6 +239,8 @@ namespace gcj
|
||||||
class _Jv_Linker
|
class _Jv_Linker
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
|
||||||
|
|
||||||
static _Jv_Field *find_field_helper(jclass, _Jv_Utf8Const *, _Jv_Utf8Const *,
|
static _Jv_Field *find_field_helper(jclass, _Jv_Utf8Const *, _Jv_Utf8Const *,
|
||||||
jclass, jclass *);
|
jclass, jclass *);
|
||||||
static _Jv_Field *find_field(jclass, jclass, jclass *, _Jv_Utf8Const *,
|
static _Jv_Field *find_field(jclass, jclass, jclass *, _Jv_Utf8Const *,
|
||||||
|
@ -264,9 +266,32 @@ private:
|
||||||
static jshort append_partial_itable(jclass, jclass, void **, jshort);
|
static jshort append_partial_itable(jclass, jclass, void **, jshort);
|
||||||
static _Jv_Method *search_method_in_class (jclass, jclass,
|
static _Jv_Method *search_method_in_class (jclass, jclass,
|
||||||
_Jv_Utf8Const *,
|
_Jv_Utf8Const *,
|
||||||
_Jv_Utf8Const *);
|
_Jv_Utf8Const *,
|
||||||
|
bool check_perms = true);
|
||||||
|
static _Jv_Method *search_method_in_superclasses (jclass cls, jclass klass,
|
||||||
|
_Jv_Utf8Const *method_name,
|
||||||
|
_Jv_Utf8Const *method_signature,
|
||||||
|
jclass *found_class,
|
||||||
|
bool check_perms = true);
|
||||||
static void *create_error_method(_Jv_Utf8Const *);
|
static void *create_error_method(_Jv_Utf8Const *);
|
||||||
|
|
||||||
|
/* The least significant bit of the signature pointer in a symbol
|
||||||
|
table is set to 1 by the compiler if the reference is "special",
|
||||||
|
i.e. if it is an access to a private field or method. Extract
|
||||||
|
that bit, clearing it in the address and setting the LSB of
|
||||||
|
SPECIAL accordingly. */
|
||||||
|
static void maybe_adjust_signature (_Jv_Utf8Const *&s, uaddr &special)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
_Jv_Utf8Const *signature;
|
||||||
|
uaddr signature_bits;
|
||||||
|
};
|
||||||
|
signature = s;
|
||||||
|
special = signature_bits & 1;
|
||||||
|
signature_bits -= special;
|
||||||
|
s = signature;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static bool has_field_p (jclass, _Jv_Utf8Const *);
|
static bool has_field_p (jclass, _Jv_Utf8Const *);
|
||||||
|
|
|
@ -55,8 +55,6 @@ details. */
|
||||||
|
|
||||||
using namespace gcj;
|
using namespace gcj;
|
||||||
|
|
||||||
typedef unsigned int uaddr __attribute__ ((mode (pointer)));
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct aligner
|
struct aligner
|
||||||
{
|
{
|
||||||
|
@ -461,19 +459,11 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index, bool lazy)
|
||||||
goto end_of_method_search;
|
goto end_of_method_search;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, search superclasses.
|
// Finally, search superclasses.
|
||||||
for (jclass cls = owner->getSuperclass (); cls != 0;
|
the_method = (search_method_in_superclasses
|
||||||
cls = cls->getSuperclass ())
|
(owner->getSuperclass (), klass, method_name,
|
||||||
{
|
method_signature, &found_class));
|
||||||
the_method = search_method_in_class (cls, klass, method_name,
|
|
||||||
method_signature);
|
|
||||||
if (the_method != 0)
|
|
||||||
{
|
|
||||||
found_class = cls;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
end_of_method_search:
|
end_of_method_search:
|
||||||
|
|
||||||
// FIXME: if (cls->loader != klass->loader), then we
|
// FIXME: if (cls->loader != klass->loader), then we
|
||||||
|
@ -534,11 +524,12 @@ _Jv_Linker::resolve_class_ref (jclass klass, jclass *classref)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a method declared in the cls that is referenced from klass and
|
// Find a method declared in the cls that is referenced from klass and
|
||||||
// perform access checks.
|
// perform access checks if CHECK_PERMS is true.
|
||||||
_Jv_Method *
|
_Jv_Method *
|
||||||
_Jv_Linker::search_method_in_class (jclass cls, jclass klass,
|
_Jv_Linker::search_method_in_class (jclass cls, jclass klass,
|
||||||
_Jv_Utf8Const *method_name,
|
_Jv_Utf8Const *method_name,
|
||||||
_Jv_Utf8Const *method_signature)
|
_Jv_Utf8Const *method_signature,
|
||||||
|
bool check_perms)
|
||||||
{
|
{
|
||||||
using namespace java::lang::reflect;
|
using namespace java::lang::reflect;
|
||||||
|
|
||||||
|
@ -551,7 +542,7 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass,
|
||||||
method_signature)))
|
method_signature)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (_Jv_CheckAccess (klass, cls, method->accflags))
|
if (!check_perms || _Jv_CheckAccess (klass, cls, method->accflags))
|
||||||
return method;
|
return method;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -568,6 +559,30 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Like search_method_in_class, but work our way up the superclass
|
||||||
|
// chain.
|
||||||
|
_Jv_Method *
|
||||||
|
_Jv_Linker::search_method_in_superclasses (jclass cls, jclass klass,
|
||||||
|
_Jv_Utf8Const *method_name,
|
||||||
|
_Jv_Utf8Const *method_signature,
|
||||||
|
jclass *found_class, bool check_perms)
|
||||||
|
{
|
||||||
|
_Jv_Method *the_method = NULL;
|
||||||
|
|
||||||
|
for ( ; cls != 0; cls = cls->getSuperclass ())
|
||||||
|
{
|
||||||
|
the_method = search_method_in_class (cls, klass, method_name,
|
||||||
|
method_signature, check_perms);
|
||||||
|
if (the_method != 0)
|
||||||
|
{
|
||||||
|
if (found_class)
|
||||||
|
*found_class = cls;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return the_method;
|
||||||
|
}
|
||||||
|
|
||||||
#define INITIAL_IOFFSETS_LEN 4
|
#define INITIAL_IOFFSETS_LEN 4
|
||||||
#define INITIAL_IFACES_LEN 4
|
#define INITIAL_IFACES_LEN 4
|
||||||
|
@ -1076,6 +1091,8 @@ _Jv_Linker::link_symbol_table (jclass klass)
|
||||||
_Jv_Method *meth = NULL;
|
_Jv_Method *meth = NULL;
|
||||||
|
|
||||||
_Jv_Utf8Const *signature = sym.signature;
|
_Jv_Utf8Const *signature = sym.signature;
|
||||||
|
uaddr special;
|
||||||
|
maybe_adjust_signature (signature, special);
|
||||||
|
|
||||||
if (target_class == NULL)
|
if (target_class == NULL)
|
||||||
throw new java::lang::NoClassDefFoundError
|
throw new java::lang::NoClassDefFoundError
|
||||||
|
@ -1101,8 +1118,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
|
||||||
// it out now.
|
// it out now.
|
||||||
wait_for_state(target_class, JV_STATE_PREPARED);
|
wait_for_state(target_class, JV_STATE_PREPARED);
|
||||||
|
|
||||||
meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
|
try
|
||||||
sym.signature);
|
{
|
||||||
|
meth = (search_method_in_superclasses
|
||||||
|
(target_class, klass, sym.name, signature,
|
||||||
|
NULL, special == 0));
|
||||||
|
}
|
||||||
|
catch (::java::lang::IllegalAccessError *e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Every class has a throwNoSuchMethodErrorIndex method that
|
// Every class has a throwNoSuchMethodErrorIndex method that
|
||||||
// it inherits from java.lang.Object. Find its vtable
|
// it inherits from java.lang.Object. Find its vtable
|
||||||
|
@ -1158,7 +1182,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
the_field = find_field (klass, target_class, &found_class,
|
the_field = find_field (klass, target_class, &found_class,
|
||||||
sym.name, sym.signature);
|
sym.name, signature);
|
||||||
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
|
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
|
||||||
throw new java::lang::IncompatibleClassChangeError;
|
throw new java::lang::IncompatibleClassChangeError;
|
||||||
else
|
else
|
||||||
|
@ -1185,7 +1209,10 @@ _Jv_Linker::link_symbol_table (jclass klass)
|
||||||
_Jv_FindClassNoException (sym.class_name, klass->loader);
|
_Jv_FindClassNoException (sym.class_name, klass->loader);
|
||||||
|
|
||||||
_Jv_Method *meth = NULL;
|
_Jv_Method *meth = NULL;
|
||||||
|
|
||||||
_Jv_Utf8Const *signature = sym.signature;
|
_Jv_Utf8Const *signature = sym.signature;
|
||||||
|
uaddr special;
|
||||||
|
maybe_adjust_signature (signature, special);
|
||||||
|
|
||||||
// ??? Setting this pointer to null will at least get us a
|
// ??? Setting this pointer to null will at least get us a
|
||||||
// NullPointerException
|
// NullPointerException
|
||||||
|
@ -1193,7 +1220,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
|
||||||
|
|
||||||
// If the target class is missing we prepare a function call
|
// If the target class is missing we prepare a function call
|
||||||
// that throws a NoClassDefFoundError and store the address of
|
// that throws a NoClassDefFoundError and store the address of
|
||||||
// that newly prepare method in the atable. The user can run
|
// that newly prepared method in the atable. The user can run
|
||||||
// code in classes where the missing class is part of the
|
// code in classes where the missing class is part of the
|
||||||
// execution environment as long as it is never referenced.
|
// execution environment as long as it is never referenced.
|
||||||
if (target_class == NULL)
|
if (target_class == NULL)
|
||||||
|
@ -1219,8 +1246,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
|
||||||
throw new VerifyError(sb->toString());
|
throw new VerifyError(sb->toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
|
try
|
||||||
sym.signature);
|
{
|
||||||
|
meth = (search_method_in_superclasses
|
||||||
|
(target_class, klass, sym.name, signature,
|
||||||
|
NULL, special == 0));
|
||||||
|
}
|
||||||
|
catch (::java::lang::IllegalAccessError *e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
if (meth != NULL)
|
if (meth != NULL)
|
||||||
{
|
{
|
||||||
|
@ -1250,7 +1284,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
|
||||||
wait_for_state(target_class, JV_STATE_PREPARED);
|
wait_for_state(target_class, JV_STATE_PREPARED);
|
||||||
jclass found_class;
|
jclass found_class;
|
||||||
_Jv_Field *the_field = find_field (klass, target_class, &found_class,
|
_Jv_Field *the_field = find_field (klass, target_class, &found_class,
|
||||||
sym.name, sym.signature);
|
sym.name, signature);
|
||||||
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
|
if ((the_field->flags & java::lang::reflect::Modifier::STATIC))
|
||||||
klass->atable->addresses[index] = the_field->u.addr;
|
klass->atable->addresses[index] = the_field->u.addr;
|
||||||
else
|
else
|
||||||
|
@ -1270,14 +1304,17 @@ _Jv_Linker::link_symbol_table (jclass klass)
|
||||||
++index)
|
++index)
|
||||||
{
|
{
|
||||||
jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
|
jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
|
||||||
|
|
||||||
_Jv_Utf8Const *signature = sym.signature;
|
_Jv_Utf8Const *signature = sym.signature;
|
||||||
|
uaddr special;
|
||||||
|
maybe_adjust_signature (signature, special);
|
||||||
|
|
||||||
jclass cls;
|
jclass cls;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
wait_for_state(target_class, JV_STATE_LOADED);
|
wait_for_state(target_class, JV_STATE_LOADED);
|
||||||
bool found = _Jv_getInterfaceMethod (target_class, cls, i,
|
bool found = _Jv_getInterfaceMethod (target_class, cls, i,
|
||||||
sym.name, sym.signature);
|
sym.name, signature);
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue