/* src/vm/resolve.c - resolving classes/interfaces/fields/methods
- Copyright (C) 1996-2005, 2006, 2007 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, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- $Id: resolve.c 7464 2007-03-06 00:26:31Z edwin $
-
*/
#include "vm/access.h"
#include "vm/exceptions.h"
#include "vm/global.h"
+#include "vm/primitive.h"
+#include "vm/resolve.h"
#include "vm/jit/jit.h"
#include "vm/jit/verify/typeinfo.h"
#include "vmcore/linker.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
-#include "vm/resolve.h"
/******************************************************************************/
/*#define RESOLVE_VERBOSE*/
+/* resolve_handle_pending_exception ********************************************
+
+ Convert a pending ClassNotFoundException into a
+ NoClassDefFoundError if requested.
+
+ See: hotspot/src/share/vm/classfile/systemDictionary.cpp
+ (handle_resolution_exception)
+
+ ARGUMENTS:
+ classname .... name of the class currently resolved
+ throwError ... if true throw a NoClassDefFoundError instead of
+ a ClassNotFoundException
+
+*******************************************************************************/
+
+void resolve_handle_pending_exception(bool throwError)
+{
+ java_handle_t *e;
+
+ /* Get the current exception. */
+
+ e = exceptions_get_exception();
+
+ if (e != NULL) {
+ if (throwError == true) {
+ /* Convert ClassNotFoundException to
+ NoClassDefFoundError. */
+
+ if (builtin_instanceof(e, class_java_lang_ClassNotFoundException)) {
+ /* Clear exception, because we are calling Java code
+ again. */
+
+ exceptions_clear_exception();
+
+ /* create new error */
+
+ exceptions_throw_noclassdeffounderror_cause(e);
+ }
+ else {
+ return;
+ }
+ }
+ else {
+ /* An exception conversion was not requested. Simply
+ return. */
+
+ return;
+ }
+ }
+}
+
+
/******************************************************************************/
/* CLASS RESOLUTION */
/******************************************************************************/
bool link,
classinfo **result)
{
- classinfo *cls = NULL;
- char *utf_ptr;
- int len;
-
+ classinfo *cls;
+ char *utf_ptr;
+ int len;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
assert(result);
assert(referer);
assert(classname);
#endif
/* load the class */
- if (!cls) {
- if (!(cls = load_class_from_classloader(classname,
- referer->classloader)))
- return false; /* exception */
+
+ if (cls == NULL) {
+ cls = load_class_from_classloader(classname, referer->classloader);
+
+ if (cls == NULL)
+ return false;
}
}
#endif
/* check access rights of referer to refered class */
+
if (checkaccess && !access_is_accessible_class(referer,cls)) {
- int msglen;
- char *message;
+ msglen =
+ utf_bytes(cls->name) +
+ utf_bytes(referer->name) +
+ 100;
+
+ msg = MNEW(char, msglen);
- msglen = utf_bytes(cls->name) + utf_bytes(referer->name) + 100;
- message = MNEW(char, msglen);
- strcpy(message, "class is not accessible (");
- utf_cat_classname(message, cls->name);
- strcat(message, " from ");
- utf_cat_classname(message, referer->name);
- strcat(message, ")");
+ strcpy(msg, "class is not accessible (");
+ utf_cat_classname(msg, cls->name);
+ strcat(msg, " from ");
+ utf_cat_classname(msg, referer->name);
+ strcat(msg, ")");
- exceptions_throw_illegalaccessexception(message);
+ u = utf_new_char(msg);
- MFREE(message, char, msglen);
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_illegalaccessexception(u);
return false; /* exception */
}
Resolve a symbolic class reference if necessary
- NOTE: If given, refmethod->class is used as the referring class.
+ NOTE: If given, refmethod->clazz is used as the referring class.
Otherwise, cls.ref->referer is used.
IN:
/* being the same, so the referer usually is cls.ref->referer. */
/* There is one important case where it is not: When we do a */
/* deferred assignability check to a formal argument of a method, */
- /* we must use refmethod->class (the caller's class) to resolve */
+ /* we must use refmethod->clazz (the caller's class) to resolve */
/* the type of the formal argument. */
- referer = (refmethod) ? refmethod->class : cls.ref->referer;
+ referer = (refmethod) ? refmethod->clazz : cls.ref->referer;
if (!resolve_class_from_name(referer, refmethod, cls.ref->name,
mode, checkaccess, link, &c))
}
else {
/* a primitive type */
- cls = primitivetype_table[d->decltype].class_primitive;
+
+ cls = primitive_class_get_by_type(d->decltype);
+
assert(cls->state & CLASS_LOADED);
+
if (!(cls->state & CLASS_LINKED))
if (!link_class(cls))
return false; /* exception */
}
+
assert(cls);
assert(cls->state & CLASS_LOADED);
assert(!link || (cls->state & CLASS_LINKED));
resolve_mode_t mode,
resolve_err_t error)
{
- classinfo *subclass;
- typeinfo subti;
- typecheck_result r;
+ classinfo *subclass;
+ typeinfo_t subti;
+ typecheck_result r;
+ char *msg;
+ s4 msglen;
+ utf *u;
assert(refmethod);
assert(subtype.any);
if (!r) {
/* sub class relationship is false */
- char *message;
- int msglen;
-
#if defined(RESOLVE_VERBOSE)
printf("SUBTYPE CHECK FAILED!\n");
#endif
utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype))
+ 200;
- message = MNEW(char, msglen);
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, (error == resolveIllegalAccessError) ?
+ "illegal access to protected member (" :
+ "subtype constraint violated (");
- strcpy(message, (error == resolveIllegalAccessError) ?
- "illegal access to protected member ("
- : "subtype constraint violated (");
+ utf_cat_classname(msg, subclass->name);
+ strcat(msg, " is not a subclass of ");
+ utf_cat_classname(msg, CLASSREF_OR_CLASSINFO_NAME(supertype));
+ strcat(msg, ")");
- utf_cat_classname(message, subclass->name);
- strcat(message, " is not a subclass of ");
- utf_cat_classname(message, CLASSREF_OR_CLASSINFO_NAME(supertype));
- strcat(message, ")");
+ u = utf_new_char(msg);
if (error == resolveIllegalAccessError)
- exceptions_throw_illegalaccessexception(message);
+ exceptions_throw_illegalaccessexception(u);
else
- exceptions_throw_linkageerror(message, NULL);
+ exceptions_throw_linkageerror(msg, NULL);
- MFREE(message, char, msglen);
+ /* ATTENTION: We probably need msg for
+ exceptions_throw_linkageerror. */
+
+ MFREE(msg, char, msglen);
return resolveFailed; /* exception */
}
#if defined(ENABLE_VERIFIER)
static resolve_result_t resolve_lazy_subtype_checks(methodinfo *refmethod,
- typeinfo *subtinfo,
+ typeinfo_t *subtinfo,
classref_or_classinfo supertype,
resolve_err_t error)
{
if (supertype.cls == class_java_lang_Object
|| (CLASSREF_OR_CLASSINFO_NAME(supertype) == utf_java_lang_Object
- && refmethod->class->classloader == NULL))
+ && refmethod->clazz->classloader == NULL))
{
return resolveSucceeded;
}
constant_FMIref *fieldref,
classinfo *container,
fieldinfo *fi,
- typeinfo *instanceti,
- typeinfo *valueti,
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti,
bool isstatic,
bool isput)
{
- classinfo *declarer;
- classinfo *referer;
- resolve_result_t result;
+ classinfo *declarer;
+ classinfo *referer;
+ resolve_result_t result;
constant_classref *fieldtyperef;
+ char *msg;
+ s4 msglen;
+ utf *u;
assert(refmethod);
assert(fieldref);
/* get the classinfos and the field type */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- declarer = fi->class;
+ declarer = fi->clazz;
assert(declarer);
assert(referer->state & CLASS_LINKED);
/* check access rights */
if (!access_is_accessible_member(referer,declarer,fi->flags)) {
- int msglen;
- char *message;
-
msglen =
utf_bytes(declarer->name) +
utf_bytes(fi->name) +
utf_bytes(referer->name) +
100;
- message = MNEW(char, msglen);
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, "field is not accessible (");
+ utf_cat_classname(msg, declarer->name);
+ strcat(msg, ".");
+ utf_cat(msg, fi->name);
+ strcat(msg, " from ");
+ utf_cat_classname(msg, referer->name);
+ strcat(msg, ")");
- strcpy(message, "field is not accessible (");
- utf_cat_classname(message, declarer->name);
- strcat(message, ".");
- utf_cat(message, fi->name);
- strcat(message, " from ");
- utf_cat_classname(message, referer->name);
- strcat(message, ")");
+ u = utf_new_char(msg);
- exceptions_throw_illegalaccessexception(message);
+ MFREE(msg, char, msglen);
- MFREE(message, char, msglen);
+ exceptions_throw_illegalaccessexception(u);
return resolveFailed; /* exception */
}
/* instance type */
if (instanceti) {
- typeinfo *insttip;
- typeinfo tinfo;
+ typeinfo_t *insttip;
+ typeinfo_t tinfo;
/* The instanceslot must contain a reference to a non-array type */
return resolveFailed;
}
- /* XXX check that class of field == refmethod->class */
+ /* XXX check that class of field == refmethod->clazz */
initclass = referer; /* XXX classrefs */
assert(initclass->state & CLASS_LINKED);
/* the class containing the reference */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
/* check if the field itself is already resolved */
/* the class containing the reference */
- referer = ref->referermethod->class;
+ referer = ref->referermethod->clazz;
assert(referer);
/* check if the field itself is already resolved */
if (IS_FMIREF_RESOLVED(ref->fieldref)) {
fi = ref->fieldref->p.field;
- container = fi->class;
+ container = fi->clazz;
goto resolved_the_field;
}
if (checkresult != resolveSucceeded)
return (bool) checkresult;
- declarer = fi->class;
+ declarer = fi->clazz;
assert(declarer);
assert(declarer->state & CLASS_LOADED);
assert(declarer->state & CLASS_LINKED);
/* get referer and declarer classes */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- declarer = mi->class;
+ declarer = mi->clazz;
assert(declarer);
assert(referer->state & CLASS_LINKED);
/* lookup starting with the direct super class of referer */
if ((referer->flags & ACC_SUPER) != 0) {
- mi = class_resolvemethod(referer->super.cls,
+ mi = class_resolvemethod(referer->super,
mi->name,
mi->descriptor);
{
classinfo *declarer;
classinfo *referer;
+ char *msg;
+ s4 msglen;
+ utf *u;
assert(refmethod);
assert(methodref);
/* get the classinfos and the method descriptor */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- declarer = mi->class;
+ declarer = mi->clazz;
assert(declarer);
/* check static */
/* check access rights */
if (!access_is_accessible_member(referer,declarer,mi->flags)) {
- int msglen;
- char *message;
-
/* XXX clean this up. this should be in exceptions.c */
+
msglen =
utf_bytes(declarer->name) +
utf_bytes(mi->name) +
utf_bytes(referer->name) +
100;
- message = MNEW(char, msglen);
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, "method is not accessible (");
+ utf_cat_classname(msg, declarer->name);
+ strcat(msg, ".");
+ utf_cat(msg, mi->name);
+ utf_cat(msg, mi->descriptor);
+ strcat(msg, " from ");
+ utf_cat_classname(msg, referer->name);
+ strcat(msg, ")");
- strcpy(message, "method is not accessible (");
- utf_cat_classname(message, declarer->name);
- strcat(message, ".");
- utf_cat(message, mi->name);
- utf_cat(message, mi->descriptor);
- strcat(message, " from ");
- utf_cat_classname(message, referer->name);
- strcat(message, ")");
+ u = utf_new_char(msg);
- exceptions_throw_illegalaccessexception(message);
+ MFREE(msg, char, msglen);
- MFREE(message, char, msglen);
+ exceptions_throw_illegalaccessexception(u);
return resolveFailed; /* exception */
}
#if defined(ENABLE_VERIFIER)
resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
methodinfo *mi,
- typeinfo *instanceti,
+ typeinfo_t *instanceti,
bool invokespecial)
{
- typeinfo tinfo;
- typeinfo *tip;
+ typeinfo_t tinfo;
+ typeinfo_t *tip;
resolve_result_t result;
if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
{ /* XXX clean up */
instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
- : CLASSREF_OR_CLASSINFO(refmethod->class);
+ : CLASSREF_OR_CLASSINFO(refmethod->clazz);
tip = &tinfo;
if (!typeinfo_init_class(tip, initclass))
return false;
result = resolve_lazy_subtype_checks(refmethod,
tip,
- CLASSREF_OR_CLASSINFO(mi->class),
+ CLASSREF_OR_CLASSINFO(mi->clazz),
resolveLinkageError);
if (result != resolveSucceeded)
return result;
/* check protected access */
- /* XXX use other `declarer` than mi->class? */
+ /* XXX use other `declarer` than mi->clazz? */
if (((mi->flags & ACC_PROTECTED) != 0)
- && !SAME_PACKAGE(mi->class, refmethod->class))
+ && !SAME_PACKAGE(mi->clazz, refmethod->clazz))
{
result = resolve_lazy_subtype_checks(refmethod,
tip,
- CLASSREF_OR_CLASSINFO(refmethod->class),
+ CLASSREF_OR_CLASSINFO(refmethod->clazz),
resolveIllegalAccessError);
if (result != resolveSucceeded)
return result;
methodinfo *refmethod,
methodinfo *mi,
bool invokestatic,
- typedescriptor *stack)
+ typedescriptor_t *stack)
{
- typedescriptor *param;
+ typedescriptor_t *param;
resolve_result_t result;
methoddesc *md;
typedesc *paramtypes;
/* the method definition. Since container is the same as, */
/* or a subclass of declarer, we also constrain declarer */
/* by transitivity of loading constraints. */
- name = mi->class->name;
+ name = mi->clazz->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,
- mi->class->classloader, name))
+ mi->clazz->classloader, name))
return false; /* exception */
}
}
/* The caller (referer) and the callee (container) must agree */
/* on the return type. */
if (!classcache_add_constraint(referer->classloader,
- mi->class->classloader,
+ mi->clazz->classloader,
md->returntype.classref->name))
return false; /* exception */
}
/* the class containing the reference */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
/* check if the method itself is already resolved */
/* the class containing the reference */
- referer = ref->referermethod->class;
+ referer = ref->referermethod->clazz;
assert(referer);
/* check if the method itself is already resolved */
if (IS_FMIREF_RESOLVED(ref->methodref)) {
mi = ref->methodref->p.method;
- container = mi->class;
+ container = mi->clazz;
goto resolved_the_method;
}
if (!resolve_method_loading_constraints(referer, mi))
return false;
- declarer = mi->class;
+ declarer = mi->clazz;
assert(declarer);
assert(referer->state & CLASS_LINKED);
/* check subtype constraints for TYPE_ADR parameters */
- assert(mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
+ assert(mi == ref->methodref->p.method || mi->parseddesc->paramcount == ref->methodref->parseddesc.md->paramcount);
paramtypes = mi->parseddesc->paramtypes;
for (i = 0; i < mi->parseddesc->paramcount-instancecount; i++) {
static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
methodinfo *refmethod,
unresolved_subtype_set *stset,
- typeinfo *tinfo,
+ typeinfo_t *tinfo,
utf *declaredclassname)
{
int count;
#ifdef ENABLE_VERIFIER
unresolved_class * create_unresolved_class(methodinfo *refmethod,
constant_classref *classref,
- typeinfo *valuetype)
+ typeinfo_t *valuetype)
{
unresolved_class *ref;
bool resolve_constrain_unresolved_field(unresolved_field *ref,
classinfo *referer,
methodinfo *refmethod,
- typeinfo *instanceti,
- typeinfo *valueti)
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti)
{
constant_FMIref *fieldref;
int type;
- typeinfo tinfo;
+ typeinfo_t tinfo;
typedesc *fd;
assert(ref);
/* record subtype constraints for the instance type, if any */
if (instanceti) {
- typeinfo *insttip;
+ typeinfo_t *insttip;
/* The instanceslot must contain a reference to a non-array type */
if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
"accessing field of uninitialized object");
return false;
}
- /* XXX check that class of field == refmethod->class */
- initclass = refmethod->class; /* XXX classrefs */
+ /* XXX check that class of field == refmethod->clazz */
+ initclass = refmethod->clazz; /* XXX classrefs */
assert(initclass->state & CLASS_LOADED);
assert(initclass->state & CLASS_LINKED);
#if defined(ENABLE_VERIFIER)
bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
methodinfo *refmethod,
- typeinfo *instanceti,
+ typeinfo_t *instanceti,
bool invokespecial)
{
constant_FMIref *methodref;
constant_classref *instanceref;
- typeinfo tinfo;
- typeinfo *tip;
+ typeinfo_t tinfo;
+ typeinfo_t *tip;
assert(ref);
methodref = ref->methodref;
/* XXX clean this up */
instanceref = IS_FMIREF_RESOLVED(methodref)
- ? class_get_self_classref(methodref->p.method->class)
+ ? class_get_self_classref(methodref->p.method->clazz)
: methodref->p.classref;
#ifdef RESOLVE_VERBOSE
{ /* XXX clean up */
instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
- : CLASSREF_OR_CLASSINFO(refmethod->class);
+ : CLASSREF_OR_CLASSINFO(refmethod->clazz);
tip = &tinfo;
if (!typeinfo_init_class(tip, initclass))
return false;
tip = instanceti;
}
- if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
&(ref->instancetypes),tip,instanceref->name))
return false;
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
}
assert(ref->paramconstraints);
- if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
ref->paramconstraints + i,&(param->typeinfo),
md->paramtypes[i+instancecount].classref->name))
return false;
bool resolve_constrain_unresolved_method_params_stackbased(
unresolved_method *ref,
methodinfo *refmethod,
- typedescriptor *stack)
+ typedescriptor_t *stack)
{
constant_FMIref *methodref;
- typedescriptor *param;
+ typedescriptor_t *param;
methoddesc *md;
int i,j;
int type;
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
}
assert(ref->paramconstraints);
- if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
ref->paramconstraints + i - instancecount,&(param->typeinfo),
md->paramtypes[i].classref->name))
return false;
fprintf(file,"unresolved_field(%p):\n",(void *)ref);
if (ref) {
fprintf(file," referer : ");
- utf_fprint_printable_ascii(file,ref->referermethod->class->name); fputc('\n',file);
+ utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
fprintf(file," refmethod : ");
utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
fprintf(file," refmethodd: ");
fprintf(file,"unresolved_method(%p):\n",(void *)ref);
if (ref) {
fprintf(file," referer : ");
- utf_fprint_printable_ascii(file,ref->referermethod->class->name); fputc('\n',file);
+ utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
fprintf(file," refmethod : ");
utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
fprintf(file," refmethodd: ");