/* src/vm/resolve.c - resolving classes/interfaces/fields/methods
- Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
This file is part of CACAO.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
- Contact: cacao@complang.tuwien.ac.at
+ Contact: cacao@cacaojvm.org
Authors: Edwin Steiner
Changes: Christan Thalinger
- $Id: resolve.c 3381 2005-10-06 14:04:54Z edwin $
+ $Id: resolve.c 4357 2006-01-22 23:33:38Z twisti $
*/
/*#define RESOLVE_VERBOSE*/
-#ifndef NDEBUG
-#define RESOLVE_DEBUG
-#endif
-
-#ifdef RESOLVE_DEBUG
-#define RESOLVE_ASSERT(cond) assert(cond)
-#else
-#define RESOLVE_ASSERT(cond)
-#endif
-
/******************************************************************************/
/* CLASS RESOLUTION */
/******************************************************************************/
-/* resolve symbolic class reference -- see resolve.h */
-bool
-resolve_class_from_name(classinfo *referer,methodinfo *refmethod,
- utf *classname,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result)
+/* resolve_class_from_name *****************************************************
+
+ Resolve a symbolic class reference
+
+ IN:
+ referer..........the class containing the reference
+ refmethod........the method from which resolution was triggered
+ (may be NULL if not applicable)
+ classname........class name to resolve
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ checkaccess......if true, access rights to the class are checked
+ link.............if true, guarantee that the returned class, if any,
+ has been linked
+
+ OUT:
+ *result..........set to result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+ NOTE:
+ The returned class is *not* guaranteed to be linked!
+ (It is guaranteed to be loaded, though.)
+
+*******************************************************************************/
+
+bool resolve_class_from_name(classinfo *referer,
+ methodinfo *refmethod,
+ utf *classname,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result)
{
classinfo *cls = NULL;
char *utf_ptr;
int len;
- RESOLVE_ASSERT(result);
- RESOLVE_ASSERT(referer);
- RESOLVE_ASSERT(classname);
- RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
+ assert(result);
+ assert(referer);
+ assert(classname);
+ assert(mode == resolveLazy || mode == resolveEager);
*result = NULL;
mode,checkaccess,link,&cls))
return false; /* exception */
if (!cls) {
- RESOLVE_ASSERT(mode == resolveLazy);
+ assert(mode == resolveLazy);
return true; /* be lazy */
}
/* create the array class */
}
/* the class is now loaded */
- RESOLVE_ASSERT(cls);
- RESOLVE_ASSERT(cls->loaded);
+ assert(cls);
+ assert(cls->state & CLASS_LOADED);
#ifdef RESOLVE_VERBOSE
fprintf(stderr," checking access rights...\n");
#endif
/* check access rights of referer to refered class */
- if (checkaccess && !is_accessible_class(referer,cls)) {
+ if (checkaccess && !access_is_accessible_class(referer,cls)) {
int msglen;
char *message;
/* link the class if necessary */
if (link) {
- if (!cls->linked)
+ if (!(cls->state & CLASS_LINKED))
if (!link_class(cls))
return false; /* exception */
- RESOLVE_ASSERT(cls->linked);
+
+ assert(cls->state & CLASS_LINKED);
}
/* resolution succeeds */
return true;
}
-bool
-resolve_classref(methodinfo *refmethod,
- constant_classref *ref,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result)
+/* resolve_classref ************************************************************
+
+ Resolve a symbolic class reference
+
+ IN:
+ refmethod........the method from which resolution was triggered
+ (may be NULL if not applicable)
+ ref..............class reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ checkaccess......if true, access rights to the class are checked
+ link.............if true, guarantee that the returned class, if any,
+ has been linked
+
+ OUT:
+ *result..........set to result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool resolve_classref(methodinfo *refmethod,
+ constant_classref *ref,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result)
{
return resolve_classref_or_classinfo(refmethod,CLASSREF_OR_CLASSINFO(ref),mode,checkaccess,link,result);
}
-bool
-resolve_classref_or_classinfo(methodinfo *refmethod,
- classref_or_classinfo cls,
- resolve_mode_t mode,
- bool checkaccess,
- bool link,
- classinfo **result)
+/* resolve_classref_or_classinfo ***********************************************
+
+ Resolve a symbolic class reference if necessary
+
+ IN:
+ refmethod........the method from which resolution was triggered
+ (may be NULL if not applicable)
+ cls..............class reference or classinfo
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ checkaccess......if true, access rights to the class are checked
+ link.............if true, guarantee that the returned class, if any,
+ has been linked
+
+ OUT:
+ *result..........set to result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool resolve_classref_or_classinfo(methodinfo *refmethod,
+ classref_or_classinfo cls,
+ resolve_mode_t mode,
+ bool checkaccess,
+ bool link,
+ classinfo **result)
{
classinfo *c;
- java_objectheader *e;
- java_objectheader *cause;
- RESOLVE_ASSERT(cls.any);
- RESOLVE_ASSERT(mode == resolveEager || mode == resolveLazy);
- RESOLVE_ASSERT(result);
+ assert(cls.any);
+ assert(mode == resolveEager || mode == resolveLazy);
+ assert(result);
#ifdef RESOLVE_VERBOSE
fprintf(stderr,"resolve_classref_or_classinfo(");
} else {
/* cls has already been resolved */
c = cls.cls;
- RESOLVE_ASSERT(c->loaded);
+ assert(c->state & CLASS_LOADED);
}
- RESOLVE_ASSERT(c || (mode == resolveLazy));
+ assert(c || (mode == resolveLazy));
if (!c)
return true; /* be lazy */
- RESOLVE_ASSERT(c);
- RESOLVE_ASSERT(c->loaded);
+ assert(c);
+ assert(c->state & CLASS_LOADED);
if (link) {
- if (!c->linked)
+ if (!(c->state & CLASS_LINKED))
if (!link_class(c))
goto return_exception;
- RESOLVE_ASSERT(c->linked);
+ assert(c->state & CLASS_LINKED);
}
/* succeeded */
return true;
return_exception:
- /* get the cause */
-
- cause = *exceptionptr;
-
- /* convert ClassNotFoundException's to NoClassDefFoundError's */
-
- if (builtin_instanceof(cause, class_java_lang_ClassNotFoundException)) {
- /* clear exception, because we are calling jit code again */
-
- *exceptionptr = NULL;
-
- /* create new error */
-
- e = new_exception_javastring(string_java_lang_NoClassDefFoundError,
- ((java_lang_Throwable *) cause)->detailMessage);
-
- /* we had an exception while creating the error */
-
- if (*exceptionptr)
- return false;
-
- /* set new exception */
-
- *exceptionptr = e;
- }
-
*result = NULL;
return false;
}
-bool
-resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
+/* resolve_class_from_typedesc *************************************************
+
+ Return a classinfo * for the given type descriptor
+
+ IN:
+ d................type descriptor
+ checkaccess......if true, access rights to the class are checked
+ link.............if true, guarantee that the returned class, if any,
+ has been linked
+ OUT:
+ *result..........set to result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+ NOTE:
+ This function always resolved eagerly.
+
+*******************************************************************************/
+
+bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
{
classinfo *cls;
- RESOLVE_ASSERT(d);
- RESOLVE_ASSERT(result);
+ assert(d);
+ assert(result);
*result = NULL;
else {
/* a primitive type */
cls = primitivetype_table[d->decltype].class_primitive;
- RESOLVE_ASSERT(cls->loaded);
- if (!cls->linked)
+ assert(cls->state & CLASS_LOADED);
+ if (!(cls->state & CLASS_LINKED))
if (!link_class(cls))
return false; /* exception */
}
- RESOLVE_ASSERT(cls);
- RESOLVE_ASSERT(cls->loaded);
- RESOLVE_ASSERT(!link || cls->linked);
+ assert(cls);
+ assert(cls->state & CLASS_LOADED);
+ assert(!link || (cls->state & CLASS_LINKED));
#ifdef RESOLVE_VERBOSE
fprintf(stderr," result = ");utf_fprint(stderr,cls->name);fprintf(stderr,"\n");
/* SUBTYPE SET CHECKS */
/******************************************************************************/
-/* for documentation see resolve.h */
-bool
-resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
- unresolved_subtype_set *ref,
- classref_or_classinfo typeref,
- bool reversed,
- resolve_mode_t mode,
- resolve_err_t error,
- bool *checked)
+#ifdef ENABLE_VERIFIER
+
+/* resolve_and_check_subtype_set ***********************************************
+
+ Resolve the references in the given set and test subtype relationships
+
+ IN:
+ referer..........the class containing the references
+ refmethod........the method triggering the resolution
+ ref..............a set of class/interface references
+ (may be empty)
+ type.............the type to test against the set
+ reversed.........if true, test if type is a subtype of
+ the set members, instead of the other
+ way round
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ error............which type of exception to throw if
+ the test fails. May be:
+ resolveLinkageError, or
+ resolveIllegalAccessError
+ IMPORTANT: If error==resolveIllegalAccessError,
+ then array types in the set are skipped.
+
+ OUT:
+ *checked.........set to true if all checks were performed,
+ otherwise set to false
+ (This is guaranteed to be true if mode was
+ resolveEager and no exception occured.)
+ If checked == NULL, this parameter is not used.
+
+ RETURN VALUE:
+ true.............the check succeeded
+ false............the check failed. An exception has been
+ thrown.
+
+ NOTE:
+ The references in the set are resolved first, so any
+ exception which may occurr during resolution may
+ be thrown by this function.
+
+*******************************************************************************/
+
+bool resolve_and_check_subtype_set(classinfo *referer,methodinfo *refmethod,
+ unresolved_subtype_set *ref,
+ classref_or_classinfo typeref,
+ bool reversed,
+ resolve_mode_t mode,
+ resolve_err_t error,
+ bool *checked)
{
classref_or_classinfo *setp;
classinfo *result;
int msglen;
typecheck_result r;
- RESOLVE_ASSERT(referer);
- RESOLVE_ASSERT(ref);
- RESOLVE_ASSERT(typeref.any);
- RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
- RESOLVE_ASSERT(error == resolveLinkageError || error == resolveIllegalAccessError);
+ assert(referer);
+ assert(ref);
+ assert(typeref.any);
+ assert(mode == resolveLazy || mode == resolveEager);
+ assert(error == resolveLinkageError || error == resolveIllegalAccessError);
#ifdef RESOLVE_VERBOSE
fprintf(stderr,"resolve_and_check_subtype_set\n");
if (!type)
return true; /* be lazy */
- RESOLVE_ASSERT(type);
- RESOLVE_ASSERT(type->loaded);
- RESOLVE_ASSERT(type->linked);
- TYPEINFO_INIT_CLASSINFO(typeti,type);
+ assert(type);
+ assert(type->state & CLASS_LOADED);
+ assert(type->state & CLASS_LINKED);
+ typeinfo_init_classinfo(&typeti,type);
for (; setp->any; ++setp) {
/* first resolve the set member if necessary */
if (!result)
return true; /* be lazy */
- RESOLVE_ASSERT(result);
- RESOLVE_ASSERT(result->loaded);
- RESOLVE_ASSERT(result->linked);
+ assert(result);
+ assert(result->state & CLASS_LOADED);
+ assert(result->state & CLASS_LINKED);
/* do not check access to protected members of arrays */
#endif
/* now check the subtype relationship */
- TYPEINFO_INIT_CLASSINFO(resultti,result);
+ typeinfo_init_classinfo(&resultti,result);
if (reversed) {
/* we must test against `true` because `MAYBE` is also != 0 */
r = typeinfo_is_assignable_to_class(&typeti,CLASSREF_OR_CLASSINFO(result));
if (error == resolveIllegalAccessError)
*exceptionptr = new_exception_message(string_java_lang_IllegalAccessException,message);
else
- *exceptionptr = new_exception_message(string_java_lang_LinkageError,message);
+ *exceptionptr = exceptions_new_linkageerror(message,NULL);
MFREE(message,char,msglen);
return false; /* exception */
}
+#endif /* ENABLE_VERIFIER */
+
/******************************************************************************/
/* CLASS RESOLUTION */
/******************************************************************************/
-/* for documentation see resolve.h */
-bool
-resolve_class(unresolved_class *ref,
- resolve_mode_t mode,
- bool checkaccess,
- classinfo **result)
+/* resolve_class ***************************************************************
+
+ Resolve an unresolved class reference. The class is also linked.
+
+ IN:
+ ref..............struct containing the reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+ checkaccess......if true, access rights to the class are checked
+
+ OUT:
+ *result..........set to the result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool resolve_class(unresolved_class *ref,
+ resolve_mode_t mode,
+ bool checkaccess,
+ classinfo **result)
{
classinfo *cls;
bool checked;
- RESOLVE_ASSERT(ref);
- RESOLVE_ASSERT(result);
- RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
+ assert(ref);
+ assert(result);
+ assert(mode == resolveLazy || mode == resolveEager);
*result = NULL;
if (!cls)
return true; /* be lazy */
- RESOLVE_ASSERT(cls);
- RESOLVE_ASSERT(cls->loaded && cls->linked);
+ assert(cls);
+ assert((cls->state & CLASS_LOADED) && (cls->state & CLASS_LINKED));
/* now we check the subtype constraints */
if (!resolve_and_check_subtype_set(ref->classref->referer,ref->referermethod,
*result = cls;
return true;
}
+#endif /* ENABLE_VERIFIER */
+
+/* resolve_classref_eager ******************************************************
+
+ Resolve an unresolved class reference eagerly. The class is also linked and
+ access rights to the class are checked.
+
+ IN:
+ ref..............constant_classref to the class
+
+ RETURN VALUE:
+ classinfo * to the class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo * resolve_classref_eager(constant_classref *ref)
+{
+ classinfo *c;
+
+ if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
+ return NULL;
+
+ return c;
+}
+
+/* resolve_classref_eager_nonabstract ******************************************
+
+ Resolve an unresolved class reference eagerly. The class is also linked and
+ access rights to the class are checked. A check is performed that the class
+ is not abstract.
+
+ IN:
+ ref..............constant_classref to the class
+
+ RETURN VALUE:
+ classinfo * to the class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo * resolve_classref_eager_nonabstract(constant_classref *ref)
+{
+ classinfo *c;
+
+ if (!resolve_classref(NULL,ref,resolveEager,true,true,&c))
+ return NULL;
+
+ /* ensure that the class is not abstract */
+
+ if (c->flags & ACC_ABSTRACT) {
+ *exceptionptr = new_verifyerror(NULL,"creating instance of abstract class");
+ return NULL;
+ }
+
+ return c;
+}
+
+/* resolve_class_eager *********************************************************
+
+ Resolve an unresolved class reference eagerly. The class is also linked and
+ access rights to the class are checked.
+
+ IN:
+ ref..............struct containing the reference
+
+ RETURN VALUE:
+ classinfo * to the class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+classinfo * resolve_class_eager(unresolved_class *ref)
+{
+ classinfo *c;
+
+ if (!resolve_class(ref,resolveEager,true,&c))
+ return NULL;
+
+ return c;
+}
+#endif /* ENABLE_VERIFIER */
/******************************************************************************/
/* FIELD RESOLUTION */
/******************************************************************************/
-/* for documentation see resolve.h */
-bool
-resolve_field(unresolved_field *ref,
- resolve_mode_t mode,
- fieldinfo **result)
+/* resolve_field ***************************************************************
+
+ Resolve an unresolved field reference
+
+ IN:
+ ref..............struct containing the reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+
+ OUT:
+ *result..........set to the result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool resolve_field(unresolved_field *ref,
+ resolve_mode_t mode,
+ fieldinfo **result)
{
classinfo *referer;
classinfo *container;
fieldinfo *fi;
bool checked;
- RESOLVE_ASSERT(ref);
- RESOLVE_ASSERT(result);
- RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
+ assert(ref);
+ assert(result);
+ assert(mode == resolveLazy || mode == resolveEager);
*result = NULL;
/* the class containing the reference */
referer = ref->fieldref->classref->referer;
- RESOLVE_ASSERT(referer);
+ assert(referer);
/* first we must resolve the class containg the field */
if (!resolve_class_from_name(referer,ref->referermethod,
if (!container)
return true; /* be lazy */
- RESOLVE_ASSERT(container);
- RESOLVE_ASSERT(container->loaded && container->linked);
+ assert(container);
+ assert(container->state & CLASS_LOADED);
+ assert(container->state & CLASS_LINKED);
/* now we must find the declaration of the field in `container`
* or one of its superclasses */
fi = class_resolvefield(container,
ref->fieldref->name,ref->fieldref->descriptor,
referer,true);
- if (!fi)
+ if (!fi) {
+ if (mode == resolveLazy) {
+ /* The field does not exist. But since we were called lazily, */
+ /* this error must not be reported now. (It will be reported */
+ /* if eager resolving of this field is ever tried.) */
+
+ *exceptionptr = NULL;
+ return true; /* be lazy */
+ }
+
return false; /* exception */
+ }
+
+#ifdef ENABLE_VERIFIER
/* { the field reference has been resolved } */
declarer = fi->class;
- RESOLVE_ASSERT(declarer);
- RESOLVE_ASSERT(declarer->loaded && declarer->linked);
+ assert(declarer);
+ assert(declarer->state & CLASS_LOADED);
+ assert(declarer->state & CLASS_LINKED);
#ifdef RESOLVE_VERBOSE
fprintf(stderr," checking static...\n");
#ifdef RESOLVE_VERBOSE
fprintf(stderr," checking value constraints...\n");
#endif
- RESOLVE_ASSERT(fieldtyperef);
+ assert(fieldtyperef);
if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
/* check subtype constraints */
if (!resolve_and_check_subtype_set(referer, ref->referermethod,
#ifdef RESOLVE_VERBOSE
fprintf(stderr," checking access rights...\n");
#endif
- if (!is_accessible_member(referer,declarer,fi->flags)) {
+ if (!access_is_accessible_member(referer,declarer,fi->flags)) {
int msglen;
char *message;
/* check protected access */
if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
#ifdef RESOLVE_VERBOSE
- fprintf(stderr," checking protectec access...\n");
+ fprintf(stderr," checking protected access...\n");
#endif
if (!resolve_and_check_subtype_set(referer,ref->referermethod,
&(ref->instancetypes),
#ifdef RESOLVE_VERBOSE
fprintf(stderr," adding constraint...\n");
#endif
- RESOLVE_ASSERT(fieldtyperef);
+ assert(fieldtyperef);
if (!classcache_add_constraint(declarer->classloader,
referer->classloader,
fieldtyperef->name))
return false;
}
+#endif /* ENABLE_VERIFIER */
/* succeed */
#ifdef RESOLVE_VERBOSE
return true;
}
+/* resolve_field_eager *********************************************************
+
+ Resolve an unresolved field reference eagerly.
+
+ IN:
+ ref..............struct containing the reference
+
+ RETURN VALUE:
+ fieldinfo * to the field, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+fieldinfo * resolve_field_eager(unresolved_field *ref)
+{
+ fieldinfo *fi;
+
+ if (!resolve_field(ref,resolveEager,&fi))
+ return NULL;
+
+ return fi;
+}
+
/******************************************************************************/
/* METHOD RESOLUTION */
/******************************************************************************/
-/* for documentation see resolve.h */
-bool
-resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
+/* resolve_method **************************************************************
+
+ Resolve an unresolved method reference
+
+ IN:
+ ref..............struct containing the reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+
+ OUT:
+ *result..........set to the result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool resolve_method(unresolved_method *ref, resolve_mode_t mode, methodinfo **result)
{
classinfo *referer;
classinfo *container;
int i;
bool checked;
- RESOLVE_ASSERT(ref);
- RESOLVE_ASSERT(result);
- RESOLVE_ASSERT(mode == resolveLazy || mode == resolveEager);
+ assert(ref);
+ assert(result);
+ assert(mode == resolveLazy || mode == resolveEager);
#ifdef RESOLVE_VERBOSE
unresolved_method_debug_dump(ref,stderr);
/* the class containing the reference */
referer = ref->methodref->classref->referer;
- RESOLVE_ASSERT(referer);
+ assert(referer);
/* first we must resolve the class containg the method */
if (!resolve_class_from_name(referer,ref->referermethod,
if (!container)
return true; /* be lazy */
- RESOLVE_ASSERT(container);
- RESOLVE_ASSERT(container->linked);
+ assert(container);
+ assert(container->state & CLASS_LINKED);
/* now we must find the declaration of the method in `container`
* or one of its superclasses */
referer, true);
}
- if (!mi)
+ if (!mi) {
+ if (mode == resolveLazy) {
+ /* The method does not exist. But since we were called lazily, */
+ /* this error must not be reported now. (It will be reported */
+ /* if eager resolving of this method is ever tried.) */
+
+ *exceptionptr = NULL;
+ return true; /* be lazy */
+ }
+
return false; /* exception */ /* XXX set exceptionptr? */
+ }
+
+#ifdef ENABLE_VERIFIER
#ifdef RESOLVE_VERBOSE
fprintf(stderr," flags: %02x\n",mi->flags);
/* { the method reference has been resolved } */
declarer = mi->class;
- RESOLVE_ASSERT(declarer);
- RESOLVE_ASSERT(referer->linked);
+ assert(declarer);
+ assert(referer->state & CLASS_LINKED);
/* checks for INVOKESPECIAL: */
/* for <init> and methods of the current class we don't need any */
/* check subtype constraints for TYPE_ADR parameters */
- RESOLVE_ASSERT(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
+ assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
paramtypes = mi->parseddesc->paramtypes;
for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
/* check access rights */
- if (!is_accessible_member(referer,declarer,mi->flags)) {
+ if (!access_is_accessible_member(referer,declarer,mi->flags)) {
int msglen;
char *message;
if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
utf *name;
- if (i < instancecount)
- name = container->name; /* XXX should this be declarer->name? */
- else
+ if (i < instancecount) {
+ /* The type of the 'this' pointer is the class containing */
+ /* the method definition. Since container is the same as, */
+ /* or a subclass of declarer, we also constrain declarer */
+ /* by transitivity of loading constraints. */
+ name = container->name;
+ }
+ else {
name = paramtypes[i].classref->name;
+ }
+ /* The caller (referer) and the callee (container) must agree */
+ /* on the types of the parameters. */
if (!classcache_add_constraint(referer->classloader,
- declarer->classloader, name))
+ container->classloader, name))
return false; /* exception */
}
}
- /* impose loading constraing onto return type */
+ /* impose loading constraint onto return type */
if (ref->methodref->parseddesc.md->returntype.type == TYPE_ADR) {
- if (!classcache_add_constraint(referer->classloader,declarer->classloader,
+ /* The caller (referer) and the callee (container) must agree */
+ /* on the return type. */
+ if (!classcache_add_constraint(referer->classloader,container->classloader,
ref->methodref->parseddesc.md->returntype.classref->name))
return false; /* exception */
}
+#endif /* ENABLE_VERIFIER */
+
/* succeed */
*result = mi;
return true;
}
+/* resolve_method_eager ********************************************************
+
+ Resolve an unresolved method reference eagerly.
+
+ IN:
+ ref..............struct containing the reference
+
+ RETURN VALUE:
+ methodinfo * to the method, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+methodinfo * resolve_method_eager(unresolved_method *ref)
+{
+ methodinfo *mi;
+
+ if (!resolve_method(ref,resolveEager,&mi))
+ return NULL;
+
+ return mi;
+}
+
/******************************************************************************/
/* CREATING THE DATA STRUCTURES */
/******************************************************************************/
-static bool
-unresolved_subtype_set_from_typeinfo(classinfo *referer,methodinfo *refmethod,
- unresolved_subtype_set *stset,typeinfo *tinfo,
- constant_classref *declaredtype)
+#ifdef ENABLE_VERIFIER
+static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
+ methodinfo *refmethod,
+ unresolved_subtype_set *stset,
+ typeinfo *tinfo,
+ constant_classref *declaredtype)
{
int count;
int i;
- RESOLVE_ASSERT(stset);
- RESOLVE_ASSERT(tinfo);
+ assert(stset);
+ assert(tinfo);
#ifdef RESOLVE_VERBOSE
fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
UNRESOLVED_SUBTYPE_SET_EMTPY(*stset);
return true;
}
+#endif /* ENABLE_VERIFIER */
/* create_unresolved_class *****************************************************
*******************************************************************************/
-unresolved_class *
-create_unresolved_class(methodinfo *refmethod,
- constant_classref *classref,
- typeinfo *valuetype)
+#ifdef ENABLE_VERIFIER
+unresolved_class * create_unresolved_class(methodinfo *refmethod,
+ constant_classref *classref,
+ typeinfo *valuetype)
{
unresolved_class *ref;
return ref;
}
+#endif /* ENABLE_VERIFIER */
/* create_unresolved_field *****************************************************
*******************************************************************************/
-unresolved_field *
-create_unresolved_field(classinfo *referer, methodinfo *refmethod,
- instruction *iptr)
+unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refmethod,
+ instruction *iptr)
{
unresolved_field *ref;
constant_FMIref *fieldref = NULL;
break;
}
- RESOLVE_ASSERT(fieldref);
+ assert(fieldref);
#ifdef RESOLVE_VERBOSE
fprintf(stderr," class : ");utf_fprint(stderr,fieldref->classref->name);fputc('\n',stderr);
*******************************************************************************/
-bool
-constrain_unresolved_field(unresolved_field *ref,
- classinfo *referer, methodinfo *refmethod,
- instruction *iptr,
- stackelement *stack)
+#ifdef ENABLE_VERIFIER
+bool constrain_unresolved_field(unresolved_field *ref,
+ classinfo *referer, methodinfo *refmethod,
+ instruction *iptr,
+ stackelement *stack)
{
constant_FMIref *fieldref;
stackelement *instanceslot = NULL;
typeinfo *tip = NULL;
typedesc *fd;
- RESOLVE_ASSERT(ref);
+ assert(ref);
fieldref = ref->fieldref;
- RESOLVE_ASSERT(fieldref);
+ assert(fieldref);
#ifdef RESOLVE_VERBOSE
fprintf(stderr,"constrain_unresolved_field\n");
break;
}
- RESOLVE_ASSERT(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
+ assert(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
fd = fieldref->parseddesc.fd;
- RESOLVE_ASSERT(fd);
+ assert(fd);
/* record subtype constraints for the instance type, if any */
if (instanceslot) {
}
/* XXX check that class of field == refmethod->class */
initclass = refmethod->class; /* XXX classrefs */
- RESOLVE_ASSERT(initclass->loaded && initclass->linked);
- TYPEINFO_INIT_CLASSINFO(tinfo,initclass);
+ assert(initclass->state & CLASS_LOADED);
+ assert(initclass->state & CLASS_LINKED);
+
+ typeinfo_init_classinfo(&tinfo,initclass);
insttip = &tinfo;
}
else {
/* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
tip = &tinfo;
if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
- RESOLVE_ASSERT(class_java_lang_String);
- RESOLVE_ASSERT(class_java_lang_String->loaded);
- RESOLVE_ASSERT(class_java_lang_String->linked);
- TYPEINFO_INIT_CLASSINFO(tinfo,class_java_lang_String);
+ assert(class_java_lang_String);
+ assert(class_java_lang_String->state & CLASS_LOADED);
+ assert(class_java_lang_String->state & CLASS_LINKED);
+ typeinfo_init_classinfo(&tinfo,class_java_lang_String);
}
else
TYPEINFO_INIT_NULLTYPE(tinfo);
return true;
}
+#endif /* ENABLE_VERIFIER */
/* create_unresolved_method ****************************************************
*******************************************************************************/
-unresolved_method *
-create_unresolved_method(classinfo *referer, methodinfo *refmethod,
- instruction *iptr)
+unresolved_method * create_unresolved_method(classinfo *referer, methodinfo *refmethod,
+ instruction *iptr)
{
unresolved_method *ref;
constant_FMIref *methodref;
bool staticmethod;
methodref = (constant_FMIref *) iptr[0].val.a;
- RESOLVE_ASSERT(methodref);
+ assert(methodref);
staticmethod = (iptr[0].opc == ICMD_INVOKESTATIC);
#ifdef RESOLVE_VERBOSE
*******************************************************************************/
-bool
-constrain_unresolved_method(unresolved_method *ref,
- classinfo *referer, methodinfo *refmethod,
- instruction *iptr,
- stackelement *stack)
+#ifdef ENABLE_VERIFIER
+bool constrain_unresolved_method(unresolved_method *ref,
+ classinfo *referer, methodinfo *refmethod,
+ instruction *iptr,
+ stackelement *stack)
{
constant_FMIref *methodref;
stackelement *instanceslot = NULL;
int type;
int instancecount;
- RESOLVE_ASSERT(ref);
+ assert(ref);
methodref = ref->methodref;
- RESOLVE_ASSERT(methodref);
+ assert(methodref);
md = methodref->parseddesc.md;
- RESOLVE_ASSERT(md);
- RESOLVE_ASSERT(md->params != NULL);
+ assert(md);
+ assert(md->params != NULL);
#ifdef RESOLVE_VERBOSE
fprintf(stderr,"constrain_unresolved_method\n");
instancecount = 0;
}
- RESOLVE_ASSERT((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
+ assert((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
/* record subtype constraints for the instance type, if any */
if (instanceslot) {
typeinfo *tip;
- RESOLVE_ASSERT(instanceslot->type == TYPE_ADR);
+ assert(instanceslot->type == TYPE_ADR);
if (iptr[0].opc == ICMD_INVOKESPECIAL &&
TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
{ /* XXX clean up */
instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
- classref_or_classinfo initclass = (ins) ? CLASSREF_OR_CLASSINFO(ins[-1].val.a)
+ classref_or_classinfo initclass = (ins) ? CLASSREF_OR_CLASSINFO(ins[-1].target)
: CLASSREF_OR_CLASSINFO(refmethod->class);
tip = &tinfo;
if (!typeinfo_init_class(tip,initclass))
for (i=md->paramcount-1-instancecount; i>=0; --i, param=param->prev) {
type = md->paramtypes[i+instancecount].type;
- RESOLVE_ASSERT(param);
- RESOLVE_ASSERT(type == param->type);
+ assert(param);
+ assert(type == param->type);
if (type == TYPE_ADR) {
if (!ref->paramconstraints) {
for (j=md->paramcount-1-instancecount; j>i; --j)
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
}
- RESOLVE_ASSERT(ref->paramconstraints);
+ assert(ref->paramconstraints);
if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
ref->paramconstraints + i,&(param->typeinfo),
md->paramtypes[i+instancecount].classref))
return true;
}
+#endif /* ENABLE_VERIFIER */
/******************************************************************************/
/* FREEING MEMORY */
/******************************************************************************/
-inline static void
-unresolved_subtype_set_free_list(classref_or_classinfo *list)
+#ifdef ENABLE_VERIFIER
+inline static void unresolved_subtype_set_free_list(classref_or_classinfo *list)
{
if (list) {
classref_or_classinfo *p = list;
MFREE(list,classref_or_classinfo,(p - list));
}
}
+#endif /* ENABLE_VERIFIER */
/* unresolved_class_free *******************************************************
*******************************************************************************/
-void
-unresolved_class_free(unresolved_class *ref)
+void unresolved_class_free(unresolved_class *ref)
{
- RESOLVE_ASSERT(ref);
+ assert(ref);
+#ifdef ENABLE_VERIFIER
unresolved_subtype_set_free_list(ref->subtypeconstraints.subtyperefs);
+#endif
FREE(ref,unresolved_class);
}
*******************************************************************************/
-void
-unresolved_field_free(unresolved_field *ref)
+void unresolved_field_free(unresolved_field *ref)
{
- RESOLVE_ASSERT(ref);
+ assert(ref);
+#ifdef ENABLE_VERIFIER
unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
unresolved_subtype_set_free_list(ref->valueconstraints.subtyperefs);
+#endif
FREE(ref,unresolved_field);
}
*******************************************************************************/
-void
-unresolved_method_free(unresolved_method *ref)
+void unresolved_method_free(unresolved_method *ref)
{
- RESOLVE_ASSERT(ref);
+ assert(ref);
+#ifdef ENABLE_VERIFIER
unresolved_subtype_set_free_list(ref->instancetypes.subtyperefs);
if (ref->paramconstraints) {
int i;
unresolved_subtype_set_free_list(ref->paramconstraints[i].subtyperefs);
MFREE(ref->paramconstraints,unresolved_subtype_set,count);
}
+#endif
FREE(ref,unresolved_method);
}
+#ifndef NDEBUG
/******************************************************************************/
/* DEBUG DUMPS */
/******************************************************************************/
*******************************************************************************/
-void
-unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
+void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file)
{
classref_or_classinfo *p;
*******************************************************************************/
-void
-unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
+void unresolved_class_debug_dump(unresolved_class *ref,FILE *file)
{
fprintf(file,"unresolved_class(%p):\n",(void *)ref);
if (ref) {
*******************************************************************************/
-void
-unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
+void unresolved_field_debug_dump(unresolved_field *ref,FILE *file)
{
fprintf(file,"unresolved_field(%p):\n",(void *)ref);
if (ref) {
*******************************************************************************/
-void
-unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
+void unresolved_method_debug_dump(unresolved_method *ref,FILE *file)
{
int i;
}
}
}
+#endif
/*
* These are local overrides for various environment variables in Emacs.