aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libjava/ChangeLog15
-rw-r--r--libjava/include/jvm.h27
-rw-r--r--libjava/link.cc89
3 files changed, 104 insertions, 27 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index f2eef03..781d0ae 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -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>
* scripts/makemake.tcl (emit_bc_rule): Do not skip
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index 542056a..d99443c 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -239,6 +239,8 @@ namespace gcj
class _Jv_Linker
{
private:
+ typedef unsigned int uaddr __attribute__ ((mode (pointer)));
+
static _Jv_Field *find_field_helper(jclass, _Jv_Utf8Const *, _Jv_Utf8Const *,
jclass, jclass *);
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 _Jv_Method *search_method_in_class (jclass, jclass,
_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 *);
+ /* 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:
static bool has_field_p (jclass, _Jv_Utf8Const *);
diff --git a/libjava/link.cc b/libjava/link.cc
index f95b128..5fc82e5 100644
--- a/libjava/link.cc
+++ b/libjava/link.cc
@@ -55,8 +55,6 @@ details. */
using namespace gcj;
-typedef unsigned int uaddr __attribute__ ((mode (pointer)));
-
template<typename T>
struct aligner
{
@@ -461,19 +459,11 @@ _Jv_Linker::resolve_pool_entry (jclass klass, int index, bool lazy)
goto end_of_method_search;
}
- // Finally, search superclasses.
- for (jclass cls = owner->getSuperclass (); cls != 0;
- cls = cls->getSuperclass ())
- {
- the_method = search_method_in_class (cls, klass, method_name,
- method_signature);
- if (the_method != 0)
- {
- found_class = cls;
- break;
- }
- }
-
+ // Finally, search superclasses.
+ the_method = (search_method_in_superclasses
+ (owner->getSuperclass (), klass, method_name,
+ method_signature, &found_class));
+
end_of_method_search:
// 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
-// perform access checks.
+// perform access checks if CHECK_PERMS is true.
_Jv_Method *
_Jv_Linker::search_method_in_class (jclass cls, jclass klass,
_Jv_Utf8Const *method_name,
- _Jv_Utf8Const *method_signature)
+ _Jv_Utf8Const *method_signature,
+ bool check_perms)
{
using namespace java::lang::reflect;
@@ -551,7 +542,7 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass,
method_signature)))
continue;
- if (_Jv_CheckAccess (klass, cls, method->accflags))
+ if (!check_perms || _Jv_CheckAccess (klass, cls, method->accflags))
return method;
else
{
@@ -568,6 +559,30 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass,
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_IFACES_LEN 4
@@ -1076,6 +1091,8 @@ _Jv_Linker::link_symbol_table (jclass klass)
_Jv_Method *meth = NULL;
_Jv_Utf8Const *signature = sym.signature;
+ uaddr special;
+ maybe_adjust_signature (signature, special);
if (target_class == NULL)
throw new java::lang::NoClassDefFoundError
@@ -1101,8 +1118,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
// it out now.
wait_for_state(target_class, JV_STATE_PREPARED);
- meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
- sym.signature);
+ try
+ {
+ 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
// it inherits from java.lang.Object. Find its vtable
@@ -1158,7 +1182,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
try
{
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))
throw new java::lang::IncompatibleClassChangeError;
else
@@ -1185,7 +1209,10 @@ _Jv_Linker::link_symbol_table (jclass klass)
_Jv_FindClassNoException (sym.class_name, klass->loader);
_Jv_Method *meth = NULL;
+
_Jv_Utf8Const *signature = sym.signature;
+ uaddr special;
+ maybe_adjust_signature (signature, special);
// ??? Setting this pointer to null will at least get us a
// NullPointerException
@@ -1193,7 +1220,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
// If the target class is missing we prepare a function call
// 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
// execution environment as long as it is never referenced.
if (target_class == NULL)
@@ -1219,8 +1246,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
throw new VerifyError(sb->toString());
}
- meth = _Jv_LookupDeclaredMethod(target_class, sym.name,
- sym.signature);
+ try
+ {
+ meth = (search_method_in_superclasses
+ (target_class, klass, sym.name, signature,
+ NULL, special == 0));
+ }
+ catch (::java::lang::IllegalAccessError *e)
+ {
+ }
if (meth != NULL)
{
@@ -1250,7 +1284,7 @@ _Jv_Linker::link_symbol_table (jclass klass)
wait_for_state(target_class, JV_STATE_PREPARED);
jclass 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))
klass->atable->addresses[index] = the_field->u.addr;
else
@@ -1270,14 +1304,17 @@ _Jv_Linker::link_symbol_table (jclass klass)
++index)
{
jclass target_class = _Jv_FindClass (sym.class_name, klass->loader);
+
_Jv_Utf8Const *signature = sym.signature;
+ uaddr special;
+ maybe_adjust_signature (signature, special);
jclass cls;
int i;
wait_for_state(target_class, JV_STATE_LOADED);
bool found = _Jv_getInterfaceMethod (target_class, cls, i,
- sym.name, sym.signature);
+ sym.name, signature);
if (found)
{