/* src/vm/resolve.c - resolving classes/interfaces/fields/methods
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Edwin Steiner
-
- Changes: Christan Thalinger
-
- $Id: resolve.c 5737 2006-10-11 19:40:22Z edwin $
-
*/
#include <assert.h>
+#include "vm/types.h"
+
#include "mm/memory.h"
-#include "vm/resolve.h"
+
#include "vm/access.h"
-#include "vm/classcache.h"
-#include "vm/descriptor.h"
#include "vm/exceptions.h"
#include "vm/global.h"
-#include "vm/linker.h"
-#include "vm/loader.h"
-#include "vm/options.h"
-#include "vm/stringlocal.h"
+#include "vm/primitive.h"
+#include "vm/resolve.h"
+
#include "vm/jit/jit.h"
#include "vm/jit/verify/typeinfo.h"
+#include "vmcore/classcache.h"
+#include "vmcore/descriptor.h"
+#include "vmcore/linker.h"
+#include "vmcore/loader.h"
+#include "vmcore/options.h"
+
/******************************************************************************/
/* DEBUG HELPERS */
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) {
+ /* If the exception is a ClassNotFoundException,
+ convert it to a NoClassDefFoundError. */
+
+ exceptions_classnotfoundexception_to_noclassdeffounderror();
+
+ 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;
- 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, ")");
- *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
- MFREE(message,char,msglen);
+ msglen =
+ utf_bytes(cls->name) +
+ utf_bytes(referer->name) +
+ 100;
+
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, "class is not accessible (");
+ utf_cat_classname(msg, cls->name);
+ strcat(msg, " from ");
+ utf_cat_classname(msg, referer->name);
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_illegalaccessexception(u);
+
return false; /* exception */
}
/* resolve_classref_or_classinfo ***********************************************
Resolve a symbolic class reference if necessary
-
+
+ NOTE: If given, refmethod->class is used as the referring class.
+ Otherwise, cls.ref->referer is used.
+
IN:
refmethod........the method from which resolution was triggered
(may be NULL if not applicable)
classinfo **result)
{
classinfo *c;
+ classinfo *referer;
assert(cls.any);
assert(mode == resolveEager || mode == resolveLazy);
if (IS_CLASSREF(cls)) {
/* we must resolve this reference */
- if (!resolve_class_from_name(cls.ref->referer, refmethod, cls.ref->name,
+ /* determine which class to use as the referer */
+
+ /* Common cases are refmethod == NULL or both referring classes */
+ /* 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 */
+ /* the type of the formal argument. */
+
+ referer = (refmethod) ? refmethod->class : cls.ref->referer;
+
+ if (!resolve_class_from_name(referer, refmethod, cls.ref->name,
mode, checkaccess, link, &c))
goto return_exception;
}
+/* resolve_classref_or_classinfo_eager *****************************************
+
+ Resolve a symbolic class reference eagerly if necessary.
+ No attempt is made to link the class.
+
+ IN:
+ cls..............class reference or classinfo
+ checkaccess......if true, access rights to the class are checked
+
+ RETURN VALUE:
+ classinfo *......the resolved class
+ NULL.............an exception has been thrown
+
+*******************************************************************************/
+
+classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls,
+ bool checkaccess)
+{
+ classinfo *c;
+
+ if (!resolve_classref_or_classinfo(NULL, cls, resolveEager, checkaccess, false, &c))
+ return NULL;
+
+ return c;
+}
+
+
/* resolve_class_from_typedesc *************************************************
Return a classinfo * for the given type descriptor
}
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 subti;
+ typecheck_result r;
+ char *msg;
+ s4 msglen;
+ utf *u;
assert(refmethod);
assert(subtype.any);
/* the subclass could not be resolved. therefore we are sure that */
/* no instances of this subclass will ever exist -> skip this test */
/* XXX this assumes that class loading has invariant results (as in JVM spec) */
- *exceptionptr = NULL;
+ exceptions_clear_exception();
return resolveSucceeded;
}
if (!subclass)
if (!r) {
/* sub class relationship is false */
- char *message;
- int msglen;
-
#if defined(RESOLVE_VERBOSE)
printf("SUBTYPE CHECK FAILED!\n");
#endif
- msglen = utf_bytes(subclass->name) + utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype)) + 200;
- message = MNEW(char, msglen);
- strcpy(message, (error == resolveIllegalAccessError) ?
- "illegal access to protected member ("
- : "subtype constraint violated (");
- utf_cat_classname(message, subclass->name);
- strcat(message, " is not a subclass of ");
- utf_cat_classname(message, CLASSREF_OR_CLASSINFO_NAME(supertype));
- strcat(message, ")");
+ msglen =
+ utf_bytes(subclass->name) +
+ utf_bytes(CLASSREF_OR_CLASSINFO_NAME(supertype))
+ + 200;
+
+ msg = MNEW(char, msglen);
+
+ strcpy(msg, (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, ")");
+
+ u = utf_new_char(msg);
+
if (error == resolveIllegalAccessError)
- *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
+ exceptions_throw_illegalaccessexception(u);
else
- *exceptionptr = exceptions_new_linkageerror(message, NULL);
- MFREE(message, char, msglen);
+ exceptions_throw_linkageerror(msg, NULL);
+
+ /* ATTENTION: We probably need msg for
+ exceptions_throw_linkageerror. */
+
+ MFREE(msg, char, msglen);
+
return resolveFailed; /* exception */
}
}
#endif /* ENABLE_VERIFIER */
+/* resolve_class_eager_no_access_check *****************************************
+
+ Resolve an unresolved class reference eagerly. The class is also linked.
+ Access rights are _not_ 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_no_access_check(unresolved_class *ref)
+{
+ classinfo *c;
+
+ if (!resolve_class(ref, resolveEager, false, &c))
+ return NULL;
+
+ return c;
+}
+#endif /* ENABLE_VERIFIER */
+
/******************************************************************************/
/* FIELD RESOLUTION */
/******************************************************************************/
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);
if (((fi->flags & ACC_STATIC) != 0) != isstatic) {
/* a static field is accessed via an instance, or vice versa */
- *exceptionptr =
- new_exception_message(string_java_lang_IncompatibleClassChangeError,
- (fi->flags & ACC_STATIC) ? "static field accessed via instance"
- : "instance field accessed without instance");
+ exceptions_throw_incompatibleclasschangeerror(declarer,
+ (fi->flags & ACC_STATIC)
+ ? "static field accessed via instance"
+ : "instance field accessed without instance");
+
return resolveFailed;
}
/* 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);
- 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, ")");
- *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
- MFREE(message,char,msglen);
+ msglen =
+ utf_bytes(declarer->name) +
+ utf_bytes(fi->name) +
+ utf_bytes(referer->name) +
+ 100;
+
+ 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, ")");
+
+ u = utf_new_char(msg);
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_illegalaccessexception(u);
+
return resolveFailed; /* exception */
}
/* this error must not be reported now. (It will be reported */
/* if eager resolving of this field is ever tried.) */
- *exceptionptr = NULL;
+ exceptions_clear_exception();
return resolveDeferred; /* be lazy */
}
/* this error must not be reported now. (It will be reported */
/* if eager resolving of this field is ever tried.) */
- *exceptionptr = NULL;
+ exceptions_clear_exception();
return true; /* be lazy */
}
if (mi == NULL) {
/* the spec calls for an AbstractMethodError in this case */
+
exceptions_throw_abstractmethoderror();
+
return NULL;
}
}
{
classinfo *declarer;
classinfo *referer;
+ char *msg;
+ s4 msglen;
+ utf *u;
assert(refmethod);
assert(methodref);
if (((mi->flags & ACC_STATIC) != 0) != (invokestatic != false)) {
/* a static method is accessed via an instance, or vice versa */
- *exceptionptr =
- new_exception_message(string_java_lang_IncompatibleClassChangeError,
- (mi->flags & ACC_STATIC) ? "static method called via instance"
- : "instance method called without instance");
+ exceptions_throw_incompatibleclasschangeerror(declarer,
+ (mi->flags & ACC_STATIC)
+ ? "static method called via instance"
+ : "instance method called without instance");
+
return resolveFailed;
}
/* 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(mi->descriptor) + utf_bytes(referer->name) + 100;
- message = MNEW(char, msglen);
- 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,")");
- *exceptionptr = new_exception_message(string_java_lang_IllegalAccessException, message);
- MFREE(message, char, msglen);
+
+ msglen =
+ utf_bytes(declarer->name) +
+ utf_bytes(mi->name) +
+ utf_bytes(mi->descriptor) +
+ utf_bytes(referer->name) +
+ 100;
+
+ 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, ")");
+
+ u = utf_new_char(msg);
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_illegalaccessexception(u);
+
return resolveFailed; /* exception */
}
/* this error must not be reported now. (It will be reported */
/* if eager resolving of this method is ever tried.) */
- *exceptionptr = NULL;
+ exceptions_clear_exception();
return resolveDeferred; /* be lazy */
}
/* this error must not be reported now. (It will be reported */
/* if eager resolving of this method is ever tried.) */
- *exceptionptr = NULL;
+ exceptions_clear_exception();
return true; /* be lazy */
}
printf(" desc : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
printf(" type : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
fputc('\n',stdout);
- /*printf(" opcode : %d %s\n",iptr->opc,icmd_names[iptr->opc]);*/
#endif
ref->fieldref = fieldref;
printf(" desc : ");utf_fprint_printable_ascii(stdout,fieldref->descriptor);fputc('\n',stdout);
printf(" type : ");descriptor_debug_print_typedesc(stdout,fieldref->parseddesc.fd);
fputc('\n',stdout);
- /*printf(" opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
#endif
assert(instanceti || ((ref->flags & RESOLVE_STATIC) != 0));
printf("resolve_constrain_unresolved_method_params\n");
printf(" rmethod: "); method_println(refmethod);
printf(" mref : "); method_methodref_println(methodref);
- /*printf(" opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
#endif
instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
}
#endif /* !defined(NDEBUG) */
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
* End:
* vim:noexpandtab:sw=4:ts=4:
*/
-