From 297750da0393e5542752140f9ad5abb924f6305e Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Thu, 8 Jun 2006 14:00:43 +0000 Subject: jvm.h (_Jv_Linker::maybe_adjust_signature): New. 2006-06-07 Andrew Haley * 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 --- libjava/ChangeLog | 15 +++++++++ libjava/include/jvm.h | 27 +++++++++++++++- libjava/link.cc | 89 ++++++++++++++++++++++++++++++++++++--------------- 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 + + * 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 * 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 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) { -- cgit v1.1