/* src/vm/resolve.c - resolving classes/interfaces/fields/methods
- 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
+ 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.
- Contact: cacao@cacaojvm.org
-
- Authors: Edwin Steiner
-
- Changes: Christan Thalinger
-
- $Id: resolve.c 5008 2006-06-01 16:00:18Z 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 */
/*#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);
*result = NULL;
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"resolve_class_from_name(");
- utf_fprint_printable_ascii(stderr,referer->name);
- fprintf(stderr,",%p,",referer->classloader);
- utf_fprint_printable_ascii(stderr,classname);
- fprintf(stderr,",%d,%d)\n",(int)checkaccess,(int)link);
+ printf("resolve_class_from_name(");
+ utf_fprint_printable_ascii(stdout,referer->name);
+ printf(",%p,",(void*)referer->classloader);
+ utf_fprint_printable_ascii(stdout,classname);
+ printf(",%d,%d)\n",(int)checkaccess,(int)link);
#endif
/* lookup if this class has already been loaded */
cls = classcache_lookup(referer->classloader, classname);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr," lookup result: %p\n",(void*)cls);
+ printf(" lookup result: %p\n",(void*)cls);
#endif
if (!cls) {
}
#ifdef RESOLVE_VERBOSE
- fprintf(stderr," loading...\n");
+ printf(" loading...\n");
#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;
}
}
assert(cls->state & CLASS_LOADED);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr," checking access rights...\n");
+ printf(" checking access rights...\n");
#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 */
}
/* resolution succeeds */
#ifdef RESOLVE_VERBOSE
- fprintf(stderr," success.\n");
+ printf(" success.\n");
#endif
*result = cls;
return true;
/* resolve_classref_or_classinfo ***********************************************
Resolve a symbolic class reference if necessary
-
+
+ NOTE: If given, refmethod->clazz 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);
assert(result);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"resolve_classref_or_classinfo(");
- utf_fprint_printable_ascii(stderr,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
- fprintf(stderr,",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
+ printf("resolve_classref_or_classinfo(");
+ utf_fprint_printable_ascii(stdout,(IS_CLASSREF(cls)) ? cls.ref->name : cls.cls->name);
+ printf(",%i,%i,%i)\n",mode,(int)checkaccess,(int)link);
#endif
*result = NULL;
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->clazz (the caller's class) to resolve */
+ /* the type of the formal argument. */
+
+ referer = (refmethod) ? refmethod->clazz : 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
*result = NULL;
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"resolve_class_from_typedesc(");
- descriptor_debug_print_typedesc(stderr,d);
- fprintf(stderr,",%i,%i)\n",(int)checkaccess,(int)link);
+ printf("resolve_class_from_typedesc(");
+ descriptor_debug_print_typedesc(stdout,d);
+ printf(",%i,%i)\n",(int)checkaccess,(int)link);
#endif
if (d->type == TYPE_ADR) {
}
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));
#ifdef RESOLVE_VERBOSE
- fprintf(stderr," result = ");utf_fprint_printable_ascii(stderr,cls->name);fprintf(stderr,"\n");
+ printf(" result = ");utf_fprint_printable_ascii(stdout,cls->name);printf("\n");
#endif
*result = cls;
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);
/* 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;
-
- 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, ")");
+#if defined(RESOLVE_VERBOSE)
+ printf("SUBTYPE CHECK FAILED!\n");
+#endif
+
+ 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 */
}
#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)
{
/* returnAddresses are illegal here */
if (TYPEINFO_IS_PRIMITIVE(*subtinfo)) {
- *exceptionptr = new_verifyerror(refmethod,
+ exceptions_throw_verifyerror(refmethod,
"Invalid use of returnAddress");
return resolveFailed;
}
/* uninitialized objects are illegal here */
if (TYPEINFO_IS_NEWOBJECT(*subtinfo)) {
- *exceptionptr = new_verifyerror(refmethod,
+ exceptions_throw_verifyerror(refmethod,
"Invalid use of uninitialized object");
return resolveFailed;
}
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;
}
assert(mode == resolveLazy || mode == resolveEager);
assert(error == resolveLinkageError || error == resolveIllegalAccessError);
+#if defined(RESOLVE_VERBOSE)
+ printf("resolve_and_check_subtype_set:\n");
+ unresolved_subtype_set_debug_dump(ref, stdout);
+ if (IS_CLASSREF(typeref))
+ class_classref_println(typeref.ref);
+ else
+ class_println(typeref.cls);
+#endif
+
setp = ref->subtyperefs;
/* an empty set of tests always succeeds */
for (; setp->any; ++setp) {
checkresult = resolve_subtype_check(refmethod,*setp,typeref,mode,error);
+#if defined(RESOLVE_VERBOSE)
+ if (checkresult != resolveSucceeded)
+ printf("SUBTYPE CHECK FAILED!\n");
+#endif
if (checkresult != resolveSucceeded)
return checkresult;
}
*result = NULL;
#ifdef RESOLVE_VERBOSE
- unresolved_class_debug_dump(ref,stderr);
+ unresolved_class_debug_dump(ref,stdout);
#endif
/* first we must resolve the class */
/* ensure that the class is not abstract */
if (c->flags & ACC_ABSTRACT) {
- *exceptionptr = new_verifyerror(NULL,"creating instance of abstract class");
+ exceptions_throw_verifyerror(NULL,"creating instance of abstract class");
return NULL;
}
}
#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 */
/******************************************************************************/
-/* resolve_field_verifier_checks ***********************************************
+/* resolve_field_verifier_checks *******************************************
Do the verifier checks necessary after field has been resolved.
fieldref.........the field reference
container........the class where the field was found
fi...............the fieldinfo of the resolved field
- opc..............opcode of the {GET,PUT}{STATIC,FIELD} instruction
+ instanceti.......instance typeinfo, if available
+ valueti..........value typeinfo, if available
+ isstatic.........true if this is a *STATIC* instruction
+ isput............true if this is a PUT* instruction
RETURN VALUE:
resolveSucceeded....everything ok
constant_FMIref *fieldref,
classinfo *container,
fieldinfo *fi,
- s4 opc,
- stackptr curstack)
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti,
+ bool isstatic,
+ bool isput)
{
- classinfo *declarer;
- classinfo *referer;
- resolve_result_t result;
- bool isstatic = false;
- bool isput = false;
- stackelement *instanceslot = NULL;
- stackelement *valueslot = NULL;
+ 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);
fieldtyperef = fieldref->parseddesc.fd->classref;
- /* get opcode dependent values */
-
- switch (opc) {
- case ICMD_PUTFIELD:
- isput = true;
- if (curstack) {
- valueslot = curstack;
- instanceslot = curstack->prev;
- }
- break;
-
- case ICMD_PUTFIELDCONST:
- isput = true;
- instanceslot = curstack;
- break;
-
- case ICMD_PUTSTATIC:
- isput = true;
- isstatic = true;
- valueslot = curstack;
- break;
-
- case ICMD_PUTSTATICCONST:
- isput = true;
- isstatic = true;
- break;
-
- case ICMD_GETFIELD:
- instanceslot = curstack;
- break;
-
- case ICMD_GETSTATIC:
- isstatic = true;
- break;
- }
-
/* check static */
#if true != 1
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 */
}
/* for non-static methods we have to check the constraints on the */
/* instance type */
- if (instanceslot) {
- typeinfo *insttip;
- typeinfo tinfo;
+ if (instanceti) {
+ typeinfo_t *insttip;
+ typeinfo_t tinfo;
/* The instanceslot must contain a reference to a non-array type */
- assert(instanceslot->type == TYPE_ADR); /* checked earlier */
-
- if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
- *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on non-reference");
+ if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
+ exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
return resolveFailed;
}
- if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
- *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on array");
+ if (TYPEINFO_IS_ARRAY(*instanceti)) {
+ exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on array");
return resolveFailed;
}
- if (isput && TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
+ if (isput && TYPEINFO_IS_NEWOBJECT(*instanceti))
{
/* The instruction writes a field in an uninitialized object. */
/* This is only allowed when a field of an uninitialized 'this' object is */
/* written inside an initialization method */
classinfo *initclass;
- instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
+ instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
if (ins != NULL) {
- *exceptionptr = new_verifyerror(refmethod,"accessing field of uninitialized object");
+ exceptions_throw_verifyerror(refmethod, "accessing field of uninitialized object");
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);
- typeinfo_init_classinfo(&tinfo,initclass);
+ typeinfo_init_classinfo(&tinfo, initclass);
insttip = &tinfo;
}
else {
- insttip = &(instanceslot->typeinfo);
+ insttip = instanceti;
}
result = resolve_lazy_subtype_checks(refmethod,
if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
{
result = resolve_lazy_subtype_checks(refmethod,
- &(instanceslot->typeinfo),
+ instanceti,
CLASSREF_OR_CLASSINFO(referer),
resolveIllegalAccessError);
if (result != resolveSucceeded)
/* for PUT* instructions we have to check the constraints on the value type */
- if (valueslot && valueslot->type == TYPE_ADR) {
+ if (valueti) {
assert(fieldtyperef);
/* check subtype constraints */
result = resolve_lazy_subtype_checks(refmethod,
- &(valueslot->typeinfo),
+ valueti,
CLASSREF_OR_CLASSINFO(fieldtyperef),
resolveLinkageError);
return resolveFailed;
}
- /* XXX impose loading constraing on instance? */
+ /* XXX impose loading constraint on instance? */
/* everything ok */
return resolveSucceeded;
/* resolve_field_lazy **********************************************************
Resolve an unresolved field reference lazily
+
+ NOTE: This function does NOT do any verification checks. In case of a
+ successful resolution, you must call resolve_field_verifier_checks
+ in order to perform the necessary checks!
IN:
- iptr.............instruction containing the field reference
- curstack.........instack of the instruction
refmethod........the referer method
+ fieldref.........the field reference
RETURN VALUE:
resolveSucceeded.....the reference has been resolved
*******************************************************************************/
-resolve_result_t new_resolve_field_lazy(new_instruction *iptr,
- stackptr curstack,
- methodinfo *refmethod)
+resolve_result_t resolve_field_lazy(methodinfo *refmethod,
+ constant_FMIref *fieldref)
{
classinfo *referer;
classinfo *container;
fieldinfo *fi;
- constant_FMIref *fieldref;
- resolve_result_t result;
- assert(iptr);
assert(refmethod);
/* the class containing the reference */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- /* get the field reference */
-
- NEW_INSTRUCTION_GET_FIELDREF(iptr, fieldref);
-
/* check if the field itself is already resolved */
- if (IS_FMIREF_RESOLVED(fieldref)) {
- fi = fieldref->p.field;
- container = fi->class;
- goto resolved_the_field;
- }
+ if (IS_FMIREF_RESOLVED(fieldref))
+ return resolveSucceeded;
/* first we must resolve the class containg the field */
/* this error must not be reported now. (It will be reported */
/* if eager resolving of this field is ever tried.) */
- *exceptionptr = NULL;
- return resolveDeferred; /* be lazy */
- }
-
- /* cache the result of the resolution */
-
- fieldref->p.field = fi;
-
-resolved_the_field:
-
-#if defined(ENABLE_VERIFIER)
- if (opt_verify) {
- result = resolve_field_verifier_checks(refmethod, fieldref, container,
- fi,
- iptr->opc,
- curstack);
-
- if (result != resolveSucceeded)
- return result;
- }
-#endif /* defined(ENABLE_VERIFIER) */
-
- /* everything ok */
- return resolveSucceeded;
-}
-
-resolve_result_t resolve_field_lazy(instruction *iptr,stackptr curstack,
- methodinfo *refmethod)
-{
- classinfo *referer;
- classinfo *container;
- fieldinfo *fi;
- constant_FMIref *fieldref;
- resolve_result_t result;
-
- assert(iptr);
- assert(refmethod);
-
- /* the class containing the reference */
-
- referer = refmethod->class;
- assert(referer);
-
- /* get the field reference */
-
- if (iptr->opc == ICMD_PUTFIELDCONST || iptr->opc == ICMD_PUTSTATICCONST)
- INSTRUCTION_GET_FIELDREF(iptr + 1,fieldref);
- else
- INSTRUCTION_GET_FIELDREF(iptr,fieldref);
-
- /* check if the field itself is already resolved */
-
- if (IS_FMIREF_RESOLVED(fieldref)) {
- fi = fieldref->p.field;
- container = fi->class;
- goto resolved_the_field;
- }
-
- /* first we must resolve the class containg the field */
-
- /* XXX can/may lazyResolving trigger linking? */
-
- if (!resolve_class_from_name(referer,refmethod,
- fieldref->p.classref->name,resolveLazy,true,true,&container))
- {
- /* the class reference could not be resolved */
- return resolveFailed; /* exception */
- }
- if (!container)
- return resolveDeferred; /* be lazy */
-
- 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,
- fieldref->name,fieldref->descriptor,
- referer,true);
- if (!fi) {
- /* 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;
+ exceptions_clear_exception();
return resolveDeferred; /* be lazy */
}
fieldref->p.field = fi;
-resolved_the_field:
-
-#if defined(ENABLE_VERIFIER)
- if (opt_verify) {
- result = resolve_field_verifier_checks(refmethod,fieldref,container,
- fi,
- iptr->opc,
- curstack);
-
- if (result != resolveSucceeded)
- return result;
- }
-#endif /* defined(ENABLE_VERIFIER) */
-
/* everything ok */
return resolveSucceeded;
}
*result = NULL;
#ifdef RESOLVE_VERBOSE
- unresolved_field_debug_dump(ref,stderr);
+ unresolved_field_debug_dump(ref,stdout);
#endif
/* 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;
}
* or one of its superclasses */
#ifdef RESOLVE_VERBOSE
- fprintf(stderr," resolving field in class...\n");
+ printf(" resolving field in class...\n");
#endif
fi = class_resolvefield(container,
/* 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 */
}
resolved_the_field:
#ifdef ENABLE_VERIFIER
+ /* Checking opt_verify is ok here, because the NULL iptr guarantees */
+ /* that no missing parts of an instruction will be accessed. */
if (opt_verify) {
- checkresult = resolve_field_verifier_checks(ref->referermethod,
+ checkresult = resolve_field_verifier_checks(
+ ref->referermethod,
ref->fieldref,
container,
fi,
- /* XXX pass NULL instruction * */
- (ref->flags & RESOLVE_STATIC) ? ICMD_GETSTATIC : ICMD_GETFIELD,
- NULL);
+ NULL, /* instanceti, handled by constraints below */
+ NULL, /* valueti, handled by constraints below */
+ (ref->flags & RESOLVE_STATIC) != 0, /* isstatic */
+ (ref->flags & RESOLVE_PUTFIELD) != 0 /* isput */);
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);
/* check that declarer is a super class of the current class */
if (!class_issubclass(referer,declarer)) {
- *exceptionptr = new_verifyerror(refmethod,
+ exceptions_throw_verifyerror(refmethod,
"INVOKESPECIAL calling non-super class method");
return NULL;
}
/* 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);
- if (!mi) {
+
+ if (mi == NULL) {
/* the spec calls for an AbstractMethodError in this case */
- *exceptionptr = new_exception(string_java_lang_AbstractMethodError);
+
+ exceptions_throw_abstractmethoderror();
+
return NULL;
}
}
return mi;
}
-/* resolve_method_verifier_checks **********************************************
+/* resolve_method_verifier_checks ******************************************
Do the verifier checks necessary after a method has been resolved.
IN:
refmethod........the method containing the reference
methodref........the method reference
- container........the class where the method was found
mi...............the methodinfo of the resolved method
invokestatic.....true if the method is invoked by INVOKESTATIC
#if defined(ENABLE_VERIFIER)
resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
constant_FMIref *methodref,
- classinfo *container,
methodinfo *mi,
- bool invokestatic,
- bool invokespecial,
- stackptr curstack)
+ bool invokestatic)
{
classinfo *declarer;
classinfo *referer;
- resolve_result_t result;
- int instancecount;
- typedesc *paramtypes;
- int i;
- stackelement *instanceslot = NULL;
- stackelement *param;
- methoddesc *md;
- typeinfo tinfo;
- int type;
+ char *msg;
+ s4 msglen;
+ utf *u;
assert(refmethod);
assert(methodref);
- assert(container);
assert(mi);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"resolve_method_verifier_checks\n");
- fprintf(stderr," flags: %02x\n",mi->flags);
+ printf("resolve_method_verifier_checks\n");
+ printf(" flags: %02x\n",mi->flags);
#endif
/* get the classinfos and the method descriptor */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- declarer = mi->class;
+ declarer = mi->clazz;
assert(declarer);
- assert(referer->state & CLASS_LINKED);
-
- md = methodref->parseddesc.md;
- assert(md);
- assert(md->params);
-
- instancecount = (invokestatic) ? 0 : 1;
/* check static */
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);
- return resolveFailed; /* exception */
- }
- if (curstack) {
- /* for non-static methods we have to check the constraints on the */
- /* instance type */
+ msglen =
+ utf_bytes(declarer->name) +
+ utf_bytes(mi->name) +
+ utf_bytes(mi->descriptor) +
+ utf_bytes(referer->name) +
+ 100;
- if (!invokestatic) {
- /* find the instance slot under all the parameter slots on the stack */
- instanceslot = curstack;
- for (i=1; i<md->paramcount; ++i)
- instanceslot = instanceslot->prev;
- }
+ msg = MNEW(char, msglen);
- assert((instanceslot && instancecount == 1) || invokestatic);
+ 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, ")");
- /* record subtype constraints for the instance type, if any */
- if (instanceslot) {
- typeinfo *tip;
+ u = utf_new_char(msg);
- assert(instanceslot->type == TYPE_ADR);
+ MFREE(msg, char, msglen);
- if (invokespecial &&
- TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
- { /* XXX clean up */
- instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
- classref_or_classinfo initclass = (ins) ? ICMD_ACONST_CLASSREF_OR_CLASSINFO(ins-1)
- : CLASSREF_OR_CLASSINFO(refmethod->class);
- tip = &tinfo;
- if (!typeinfo_init_class(tip,initclass))
- return false;
- }
- else {
- tip = &(instanceslot->typeinfo);
- }
+ exceptions_throw_illegalaccessexception(u);
- result = resolve_lazy_subtype_checks(refmethod,
- tip,
- CLASSREF_OR_CLASSINFO(container),
- resolveLinkageError);
+ return resolveFailed; /* exception */
+ }
+
+ /* everything ok */
+
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_instance_type_checks *****************************************
+
+ Check the instance type of a method invocation.
+
+ IN:
+ refmethod........the method containing the reference
+ mi...............the methodinfo of the resolved method
+ instanceti.......typeinfo of the instance slot
+ invokespecial....true if the method is invoked by INVOKESPECIAL
+
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
+ methodinfo *mi,
+ typeinfo_t *instanceti,
+ bool invokespecial)
+{
+ 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->clazz);
+ tip = &tinfo;
+ if (!typeinfo_init_class(tip, initclass))
+ return false;
+ }
+ else {
+ tip = instanceti;
+ }
+
+ result = resolve_lazy_subtype_checks(refmethod,
+ tip,
+ CLASSREF_OR_CLASSINFO(mi->clazz),
+ resolveLinkageError);
+ if (result != resolveSucceeded)
+ return result;
+
+ /* check protected access */
+
+ /* XXX use other `declarer` than mi->clazz? */
+ if (((mi->flags & ACC_PROTECTED) != 0)
+ && !SAME_PACKAGE(mi->clazz, refmethod->clazz))
+ {
+ result = resolve_lazy_subtype_checks(refmethod,
+ tip,
+ CLASSREF_OR_CLASSINFO(refmethod->clazz),
+ resolveIllegalAccessError);
+ if (result != resolveSucceeded)
+ return result;
+ }
+
+ /* everything ok */
+
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_param_type_checks ********************************************
+
+ Check non-instance parameter types of a method invocation.
+
+ IN:
+ jd...............jitdata of the method doing the call
+ refmethod........the method containing the reference
+ iptr.............the invoke instruction
+ mi...............the methodinfo of the resolved method
+ invokestatic.....true if the method is invoked by INVOKESTATIC
+
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_param_type_checks(jitdata *jd,
+ methodinfo *refmethod,
+ instruction *iptr,
+ methodinfo *mi,
+ bool invokestatic)
+{
+ varinfo *param;
+ resolve_result_t result;
+ methoddesc *md;
+ typedesc *paramtypes;
+ s4 type;
+ s4 instancecount;
+ s4 i;
+
+ assert(jd);
+
+ instancecount = (invokestatic) ? 0 : 1;
+
+ /* check subtype constraints for TYPE_ADR parameters */
+
+ md = mi->parseddesc;
+ paramtypes = md->paramtypes;
+
+ for (i = md->paramcount-1-instancecount; i>=0; --i) {
+ param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
+ type = md->paramtypes[i+instancecount].type;
+
+ assert(param);
+ assert(type == param->type);
+
+ if (type == TYPE_ADR) {
+ result = resolve_lazy_subtype_checks(refmethod,
+ &(param->typeinfo),
+ CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
+ resolveLinkageError);
if (result != resolveSucceeded)
return result;
+ }
+ }
- /* check protected access */
+ /* everything ok */
- if (((mi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
- {
- result = resolve_lazy_subtype_checks(refmethod,
- tip,
- CLASSREF_OR_CLASSINFO(referer),
- resolveIllegalAccessError);
- if (result != resolveSucceeded)
- return result;
- }
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
- }
- /* check subtype constraints for TYPE_ADR parameters */
+/* resolve_method_param_type_checks_stackbased *********************************
- assert(md->paramcount == methodref->parseddesc.md->paramcount);
- paramtypes = md->paramtypes;
- param = curstack;
+ Check non-instance parameter types of a method invocation.
- for (i = md->paramcount-1-instancecount; i>=0; --i, param = param->prev) {
- type = md->paramtypes[i+instancecount].type;
+ IN:
+ refmethod........the method containing the reference
+ mi...............the methodinfo of the resolved method
+ invokestatic.....true if the method is invoked by INVOKESTATIC
+ stack............TOS before the INVOKE instruction
- assert(param);
- assert(type == param->type);
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
- if (type == TYPE_ADR) {
- result = resolve_lazy_subtype_checks(refmethod,
- &(param->typeinfo),
- CLASSREF_OR_CLASSINFO(paramtypes[i+instancecount].classref),
- resolveLinkageError);
- if (result != resolveSucceeded)
- return result;
- }
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_param_type_checks_stackbased(
+ methodinfo *refmethod,
+ methodinfo *mi,
+ bool invokestatic,
+ typedescriptor_t *stack)
+{
+ typedescriptor_t *param;
+ resolve_result_t result;
+ methoddesc *md;
+ typedesc *paramtypes;
+ s4 type;
+ s4 instancecount;
+ s4 i;
+
+ instancecount = (invokestatic) ? 0 : 1;
+
+ /* check subtype constraints for TYPE_ADR parameters */
+
+ md = mi->parseddesc;
+ paramtypes = md->paramtypes;
+
+ param = stack - (md->paramslots - 1 - instancecount);
+
+ for (i = instancecount; i < md->paramcount; ++i) {
+ type = md->paramtypes[i].type;
+
+ assert(type == param->type);
+
+ if (type == TYPE_ADR) {
+ result = resolve_lazy_subtype_checks(refmethod,
+ &(param->typeinfo),
+ CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
+ resolveLinkageError);
+ if (result != resolveSucceeded)
+ return result;
}
- } /* if (curstack) */
+ param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
+ }
+
+ /* everything ok */
+
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* resolve_method_loading_constraints ******************************************
+
+ Impose loading constraints on the parameters and return type of the
+ given method.
+
+ IN:
+ referer..........the class refering to the method
+ mi...............the method
+
+ RETURN VALUE:
+ true................everything ok
+ false...............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_method_loading_constraints(classinfo *referer,
+ methodinfo *mi)
+{
+ methoddesc *md;
+ typedesc *paramtypes;
+ utf *name;
+ s4 i;
+ s4 instancecount;
/* impose loading constraints on parameters (including instance) */
+ md = mi->parseddesc;
paramtypes = md->paramtypes;
+ instancecount = (mi->flags & ACC_STATIC) / ACC_STATIC;
for (i = 0; i < md->paramcount; i++) {
if (i < instancecount || paramtypes[i].type == TYPE_ADR) {
- utf *name;
-
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;
+ 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,
- container->classloader, name))
- return resolveFailed; /* exception */
+ mi->clazz->classloader, name))
+ return false; /* exception */
}
}
if (md->returntype.type == TYPE_ADR) {
/* The caller (referer) and the callee (container) must agree */
/* on the return type. */
- if (!classcache_add_constraint(referer->classloader,container->classloader,
- md->returntype.classref->name))
- return resolveFailed; /* exception */
+ if (!classcache_add_constraint(referer->classloader,
+ mi->clazz->classloader,
+ md->returntype.classref->name))
+ return false; /* exception */
}
/* everything ok */
- return resolveSucceeded;
+
+ return true;
}
#endif /* defined(ENABLE_VERIFIER) */
+
/* resolve_method_lazy *********************************************************
Resolve an unresolved method reference lazily
+ NOTE: This function does NOT do any verification checks. In case of a
+ successful resolution, you must call resolve_method_verifier_checks
+ in order to perform the necessary checks!
+
IN:
- iptr.............instruction containing the method reference
- curstack.........instack of the instruction
refmethod........the referer method
+ methodref........the method reference
+ invokespecial....true if this is an INVOKESPECIAL instruction
RETURN VALUE:
resolveSucceeded.....the reference has been resolved
*******************************************************************************/
-resolve_result_t new_resolve_method_lazy(new_instruction *iptr,
- stackptr curstack,
- methodinfo *refmethod)
+resolve_result_t resolve_method_lazy(methodinfo *refmethod,
+ constant_FMIref *methodref,
+ bool invokespecial)
{
classinfo *referer;
classinfo *container;
methodinfo *mi;
- constant_FMIref *methodref;
- resolve_result_t result;
- assert(iptr);
assert(refmethod);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"resolve_method_lazy\n");
+ printf("resolve_method_lazy\n");
#endif
/* the class containing the reference */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- /* the method reference */
-
- NEW_INSTRUCTION_GET_METHODREF(iptr, methodref);
-
/* check if the method itself is already resolved */
- if (IS_FMIREF_RESOLVED(methodref)) {
- mi = methodref->p.method;
- container = mi->class;
- goto resolved_the_method;
- }
+ if (IS_FMIREF_RESOLVED(methodref))
+ return resolveSucceeded;
/* first we must resolve the class containg the method */
/* 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 */
}
- if (iptr->opc == ICMD_INVOKESPECIAL) {
+ if (invokespecial) {
mi = resolve_method_invokespecial_lookup(refmethod, mi);
if (!mi)
return resolveFailed; /* exception */
methodref->p.method = mi;
-resolved_the_method:
-
-#if defined(ENABLE_VERIFIER)
- if (opt_verify) {
- result = resolve_method_verifier_checks(refmethod, methodref,
- container,
- mi,
- iptr->opc == ICMD_INVOKESTATIC,
- iptr->opc == ICMD_INVOKESPECIAL,
- curstack);
- if (result != resolveSucceeded)
- return result;
- }
-#endif /* defined(ENABLE_VERIFIER) */
-
- /* if this call is monomorphic, turn it into an INVOKESPECIAL */
-
- if ((iptr->opc == ICMD_INVOKEVIRTUAL)
- && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
- {
- iptr->opc = ICMD_INVOKESPECIAL;
- }
-
/* succeed */
- return resolveSucceeded;
-}
-
-resolve_result_t resolve_method_lazy(instruction *iptr,stackptr curstack,
- methodinfo *refmethod)
-{
- classinfo *referer;
- classinfo *container;
- methodinfo *mi;
- constant_FMIref *methodref;
- resolve_result_t result;
-
- assert(iptr);
- assert(refmethod);
-
-#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"resolve_method_lazy\n");
-#endif
-
- /* the class containing the reference */
-
- referer = refmethod->class;
- assert(referer);
-
- /* the method reference */
-
- INSTRUCTION_GET_METHODREF(iptr,methodref);
-
- /* check if the method itself is already resolved */
-
- if (IS_FMIREF_RESOLVED(methodref)) {
- mi = methodref->p.method;
- container = mi->class;
- goto resolved_the_method;
- }
-
- /* first we must resolve the class containg the method */
-
- if (!resolve_class_from_name(referer,refmethod,
- methodref->p.classref->name,resolveLazy,true,true,&container))
- {
- /* the class reference could not be resolved */
- return resolveFailed; /* exception */
- }
- if (!container)
- return resolveDeferred; /* be lazy */
-
- assert(container->state & CLASS_LINKED);
-
- /* now we must find the declaration of the method in `container`
- * or one of its superclasses */
-
- if (container->flags & ACC_INTERFACE) {
- mi = class_resolveinterfacemethod(container,
- methodref->name,
- methodref->descriptor,
- referer, true);
-
- } else {
- mi = class_resolveclassmethod(container,
- methodref->name,
- methodref->descriptor,
- referer, true);
- }
- if (!mi) {
- /* 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 resolveDeferred; /* be lazy */
- }
-
- if (iptr->opc == ICMD_INVOKESPECIAL) {
- mi = resolve_method_invokespecial_lookup(refmethod,mi);
- if (!mi)
- return resolveFailed; /* exception */
- }
-
- /* have the method params already been parsed? no, do it. */
-
- if (!mi->parseddesc->params)
- if (!descriptor_params_from_paramtypes(mi->parseddesc, mi->flags))
- return resolveFailed;
-
- /* cache the result of the resolution */
-
- methodref->p.method = mi;
-
-resolved_the_method:
-
-#if defined(ENABLE_VERIFIER)
- if (opt_verify) {
- result = resolve_method_verifier_checks(refmethod,methodref,container,
- mi,
- iptr->opc == ICMD_INVOKESTATIC,
- iptr->opc == ICMD_INVOKESPECIAL,
- curstack);
- if (result != resolveSucceeded)
- return result;
- }
-#endif /* defined(ENABLE_VERIFIER) */
-
- /* if this call is monomorphic, turn it into an INVOKESPECIAL */
-
- if ((iptr->opc == ICMD_INVOKEVIRTUAL)
- && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
- {
- iptr->opc = ICMD_INVOKESPECIAL;
- }
-
- /* succeed */
return resolveSucceeded;
}
assert(mode == resolveLazy || mode == resolveEager);
#ifdef RESOLVE_VERBOSE
- unresolved_method_debug_dump(ref,stderr);
+ unresolved_method_debug_dump(ref,stdout);
#endif
*result = NULL;
/* 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;
}
/* 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 */
}
#ifdef ENABLE_VERIFIER
if (opt_verify) {
- checkresult = resolve_method_verifier_checks(ref->referermethod,
+ checkresult = resolve_method_verifier_checks(
+ ref->referermethod,
ref->methodref,
- container,
mi,
- (ref->flags & RESOLVE_STATIC),
- (ref->flags & RESOLVE_SPECIAL),
- NULL);
+ (ref->flags & RESOLVE_STATIC));
if (checkresult != resolveSucceeded)
return (bool) checkresult;
- declarer = mi->class;
+ /* impose loading constraints on params and return type */
+
+ if (!resolve_method_loading_constraints(referer, mi))
+ return false;
+
+ 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,
- constant_classref *declaredtype)
+ typeinfo_t *tinfo,
+ utf *declaredclassname)
{
int count;
int i;
assert(tinfo);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"unresolved_subtype_set_from_typeinfo\n");
+ printf("unresolved_subtype_set_from_typeinfo\n");
#ifdef TYPEINFO_DEBUG
- typeinfo_print(stderr,tinfo,4);
+ typeinfo_print(stdout,tinfo,4);
#endif
- fprintf(stderr," declared type:");utf_fprint_printable_ascii(stderr,declaredtype->name);
- fprintf(stderr,"\n");
+ printf(" declared classname:");utf_fprint_printable_ascii(stdout,declaredclassname);
+ printf("\n");
#endif
if (TYPEINFO_IS_PRIMITIVE(*tinfo)) {
- *exceptionptr = new_verifyerror(refmethod,
+ exceptions_throw_verifyerror(refmethod,
"Invalid use of returnAddress");
return false;
}
if (TYPEINFO_IS_NEWOBJECT(*tinfo)) {
- *exceptionptr = new_verifyerror(refmethod,
+ exceptions_throw_verifyerror(refmethod,
"Invalid use of uninitialized object");
return false;
}
goto empty_set;
/* every type is assignable to (BOOTSTRAP)java.lang.Object */
- if (declaredtype->name == utf_java_lang_Object
- && referer->classloader == NULL)
+ if (declaredclassname == utf_java_lang_Object
+ && referer->classloader == NULL) /* XXX do loading constraints make the second check obsolete? */
{
goto empty_set;
}
else {
if ((IS_CLASSREF(tinfo->typeclass)
? tinfo->typeclass.ref->name
- : tinfo->typeclass.cls->name) == declaredtype->name)
+ : tinfo->typeclass.cls->name) == declaredclassname)
{
/* the class names are the same */
/* equality is guaranteed by the loading constraints */
#ifdef ENABLE_VERIFIER
unresolved_class * create_unresolved_class(methodinfo *refmethod,
constant_classref *classref,
- typeinfo *valuetype)
+ typeinfo_t *valuetype)
{
unresolved_class *ref;
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"create_unresolved_class\n");
- fprintf(stderr," referer: ");utf_fprint_printable_ascii(stderr,classref->referer->name);fputc('\n',stderr);
+ printf("create_unresolved_class\n");
+ printf(" referer: ");utf_fprint_printable_ascii(stdout,classref->referer->name);fputc('\n',stdout);
if (refmethod) {
- fprintf(stderr," rmethod: ");utf_fprint_printable_ascii(stderr,refmethod->name);fputc('\n',stderr);
- fprintf(stderr," rmdesc : ");utf_fprint_printable_ascii(stderr,refmethod->descriptor);fputc('\n',stderr);
+ printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+ printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
}
- fprintf(stderr," name : ");utf_fprint_printable_ascii(stderr,classref->name);fputc('\n',stderr);
+ printf(" name : ");utf_fprint_printable_ascii(stdout,classref->name);fputc('\n',stdout);
#endif
ref = NEW(unresolved_class);
if (valuetype) {
if (!unresolved_subtype_set_from_typeinfo(classref->referer,refmethod,
- &(ref->subtypeconstraints),valuetype,classref))
+ &(ref->subtypeconstraints),valuetype,classref->name))
return NULL;
}
else {
}
#endif /* ENABLE_VERIFIER */
-/* create_unresolved_field *****************************************************
+/* resolve_create_unresolved_field *********************************************
Create an unresolved_field struct for the given field access instruction
*******************************************************************************/
-unresolved_field * new_create_unresolved_field(classinfo *referer,
- methodinfo *refmethod,
- new_instruction *iptr)
+unresolved_field * resolve_create_unresolved_field(classinfo *referer,
+ methodinfo *refmethod,
+ instruction *iptr)
{
unresolved_field *ref;
constant_FMIref *fieldref = NULL;
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"create_unresolved_field\n");
- fprintf(stderr," referer: ");utf_fprint_printable_ascii(stderr,referer->name);fputc('\n',stderr);
- fprintf(stderr," rmethod: ");utf_fprint_printable_ascii(stderr,refmethod->name);fputc('\n',stderr);
- fprintf(stderr," rmdesc : ");utf_fprint_printable_ascii(stderr,refmethod->descriptor);fputc('\n',stderr);
+ printf("create_unresolved_field\n");
+ printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+ printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+ printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
#endif
ref = NEW(unresolved_field);
assert(fieldref);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr," class : ");utf_fprint_printable_ascii(stderr,fieldref->classref->name);fputc('\n',stderr);
- fprintf(stderr," name : ");utf_fprint_printable_ascii(stderr,fieldref->name);fputc('\n',stderr);
- fprintf(stderr," desc : ");utf_fprint_printable_ascii(stderr,fieldref->descriptor);fputc('\n',stderr);
- fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
- fputc('\n',stderr);
- /*fprintf(stderr," opcode : %d %s\n",iptr->opc,icmd_names[iptr->opc]);*/
-#endif
-
- ref->fieldref = fieldref;
-
- return ref;
-}
-
-unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refmethod,
- instruction *iptr)
-{
- unresolved_field *ref;
- constant_FMIref *fieldref = NULL;
-
-#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"create_unresolved_field\n");
- fprintf(stderr," referer: ");utf_fprint_printable_ascii(stderr,referer->name);fputc('\n',stderr);
- fprintf(stderr," rmethod: ");utf_fprint_printable_ascii(stderr,refmethod->name);fputc('\n',stderr);
- fprintf(stderr," rmdesc : ");utf_fprint_printable_ascii(stderr,refmethod->descriptor);fputc('\n',stderr);
-#endif
-
- ref = NEW(unresolved_field);
- ref->flags = 0;
- ref->referermethod = refmethod;
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
-
- switch (iptr[0].opc) {
- case ICMD_PUTFIELD:
- ref->flags |= RESOLVE_PUTFIELD;
- fieldref = (constant_FMIref *) iptr[0].val.a;
- break;
-
- case ICMD_PUTFIELDCONST:
- ref->flags |= RESOLVE_PUTFIELD;
- fieldref = (constant_FMIref *) iptr[1].val.a;
- break;
-
- case ICMD_PUTSTATIC:
- ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
- fieldref = (constant_FMIref *) iptr[0].val.a;
- break;
-
- case ICMD_PUTSTATICCONST:
- ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
- fieldref = (constant_FMIref *) iptr[1].val.a;
- break;
-
- case ICMD_GETFIELD:
- fieldref = (constant_FMIref *) iptr[0].val.a;
- break;
-
- case ICMD_GETSTATIC:
- ref->flags |= RESOLVE_STATIC;
- fieldref = (constant_FMIref *) iptr[0].val.a;
- break;
- }
-
- assert(fieldref);
-
-#ifdef RESOLVE_VERBOSE
- fprintf(stderr," class : ");utf_fprint_printable_ascii(stderr,fieldref->classref->name);fputc('\n',stderr);
- fprintf(stderr," name : ");utf_fprint_printable_ascii(stderr,fieldref->name);fputc('\n',stderr);
- fprintf(stderr," desc : ");utf_fprint_printable_ascii(stderr,fieldref->descriptor);fputc('\n',stderr);
- fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
- fputc('\n',stderr);
- /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
+/* printf(" class : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout);*/
+ printf(" name : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
+ 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);
#endif
ref->fieldref = fieldref;
return ref;
}
-/* constrain_unresolved_field **************************************************
+/* resolve_constrain_unresolved_field ******************************************
Record subtype constraints for a field access.
ref..............the unresolved_field structure of the access
referer..........the class containing the reference
refmethod........the method triggering the resolution (if any)
- iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
- stack............the input stack of the instruction
+ instanceti.......instance typeinfo, if available
+ valueti..........value typeinfo, if available
RETURN VALUE:
true.............everything ok
*******************************************************************************/
-#ifdef ENABLE_VERIFIER
-bool constrain_unresolved_field(unresolved_field *ref,
- classinfo *referer, methodinfo *refmethod,
- instruction *iptr,
- stackelement *stack)
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_field(unresolved_field *ref,
+ classinfo *referer,
+ methodinfo *refmethod,
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti)
{
constant_FMIref *fieldref;
- stackelement *instanceslot = NULL;
int type;
- typeinfo tinfo;
- typeinfo *tip = NULL;
+ typeinfo_t tinfo;
typedesc *fd;
assert(ref);
assert(fieldref);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"constrain_unresolved_field\n");
- fprintf(stderr," referer: ");utf_fprint_printable_ascii(stderr,referer->name);fputc('\n',stderr);
- fprintf(stderr," rmethod: ");utf_fprint_printable_ascii(stderr,refmethod->name);fputc('\n',stderr);
- fprintf(stderr," rmdesc : ");utf_fprint_printable_ascii(stderr,refmethod->descriptor);fputc('\n',stderr);
- fprintf(stderr," class : ");utf_fprint_printable_ascii(stderr,fieldref->classref->name);fputc('\n',stderr);
- fprintf(stderr," name : ");utf_fprint_printable_ascii(stderr,fieldref->name);fputc('\n',stderr);
- fprintf(stderr," desc : ");utf_fprint_printable_ascii(stderr,fieldref->descriptor);fputc('\n',stderr);
- fprintf(stderr," type : ");descriptor_debug_print_typedesc(stderr,fieldref->parseddesc.fd);
- fputc('\n',stderr);
- /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
+ printf("constrain_unresolved_field\n");
+ printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+ printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+ printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+/* printf(" class : ");utf_fprint_printable_ascii(stdout,fieldref->p.classref->name);fputc('\n',stdout); */
+ printf(" name : ");utf_fprint_printable_ascii(stdout,fieldref->name);fputc('\n',stdout);
+ 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);
#endif
- switch (iptr[0].opc) {
- case ICMD_PUTFIELD:
- instanceslot = stack->prev;
- tip = &(stack->typeinfo);
- break;
-
- case ICMD_PUTFIELDCONST:
- instanceslot = stack;
- break;
-
- case ICMD_PUTSTATIC:
- tip = &(stack->typeinfo);
- break;
-
- case ICMD_GETFIELD:
- instanceslot = stack;
- break;
- }
-
- assert(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
+ assert(instanceti || ((ref->flags & RESOLVE_STATIC) != 0));
fd = fieldref->parseddesc.fd;
assert(fd);
/* record subtype constraints for the instance type, if any */
- if (instanceslot) {
- typeinfo *insttip;
+ if (instanceti) {
+ typeinfo_t *insttip;
/* The instanceslot must contain a reference to a non-array type */
- if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
- *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on non-reference");
+ if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
+ exceptions_throw_verifyerror(refmethod,
+ "illegal instruction: field access on non-reference");
return false;
}
- if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
- *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on array");
+ if (TYPEINFO_IS_ARRAY(*instanceti)) {
+ exceptions_throw_verifyerror(refmethod,
+ "illegal instruction: field access on array");
return false;
}
if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
- TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
+ TYPEINFO_IS_NEWOBJECT(*instanceti))
{
/* The instruction writes a field in an uninitialized object. */
/* This is only allowed when a field of an uninitialized 'this' object is */
/* written inside an initialization method */
classinfo *initclass;
- instruction *ins = (instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
+ instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
if (ins != NULL) {
- *exceptionptr = new_verifyerror(refmethod,"accessing field of uninitialized object");
+ exceptions_throw_verifyerror(refmethod,
+ "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);
- typeinfo_init_classinfo(&tinfo,initclass);
+ typeinfo_init_classinfo(&tinfo, initclass);
insttip = &tinfo;
}
else {
- insttip = &(instanceslot->typeinfo);
+ insttip = instanceti;
}
- if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
- &(ref->instancetypes),insttip,fieldref->p.classref))
+ if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+ &(ref->instancetypes), insttip,
+ FIELDREF_CLASSNAME(fieldref)))
return false;
}
else {
/* record subtype constraints for the value type, if any */
type = fd->type;
if (type == TYPE_ADR && ((ref->flags & RESOLVE_PUTFIELD) != 0)) {
- if (!tip) {
- /* we have a PUTSTATICCONST or PUTFIELDCONST with TYPE_ADR */
- tip = &tinfo;
- if (INSTRUCTION_PUTCONST_VALUE_ADR(iptr)) {
- 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);
- }
- if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
- &(ref->valueconstraints),tip,fieldref->parseddesc.fd->classref))
+ assert(valueti);
+ if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+ &(ref->valueconstraints), valueti,
+ fieldref->parseddesc.fd->classref->name))
return false;
}
else {
}
#endif /* ENABLE_VERIFIER */
-/* create_unresolved_method ****************************************************
+/* resolve_create_unresolved_method ********************************************
Create an unresolved_method struct for the given method invocation
*******************************************************************************/
-unresolved_method * new_create_unresolved_method(classinfo *referer,
- methodinfo *refmethod,
- new_instruction *iptr)
+unresolved_method * resolve_create_unresolved_method(classinfo *referer,
+ methodinfo *refmethod,
+ constant_FMIref *methodref,
+ bool invokestatic,
+ bool invokespecial)
{
unresolved_method *ref;
- constant_FMIref *methodref;
- bool staticmethod;
- methodref = iptr->sx.s23.s3.fmiref;
assert(methodref);
- staticmethod = (iptr->opc == ICMD_INVOKESTATIC);
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"create_unresolved_method\n");
- fprintf(stderr," referer: ");utf_fprint_printable_ascii(stderr,referer->name);fputc('\n',stderr);
- fprintf(stderr," rmethod: ");utf_fprint_printable_ascii(stderr,refmethod->name);fputc('\n',stderr);
- fprintf(stderr," rmdesc : ");utf_fprint_printable_ascii(stderr,refmethod->descriptor);fputc('\n',stderr);
- fprintf(stderr," class : ");utf_fprint_printable_ascii(stderr,methodref->classref->name);fputc('\n',stderr);
- fprintf(stderr," name : ");utf_fprint_printable_ascii(stderr,methodref->name);fputc('\n',stderr);
- fprintf(stderr," desc : ");utf_fprint_printable_ascii(stderr,methodref->descriptor);fputc('\n',stderr);
- /*fprintf(stderr," opcode : %d %s\n",iptr->opc,icmd_names[iptr->opc]);*/
+ printf("create_unresolved_method\n");
+ printf(" referer: ");utf_fprint_printable_ascii(stdout,referer->name);fputc('\n',stdout);
+ printf(" rmethod: ");utf_fprint_printable_ascii(stdout,refmethod->name);fputc('\n',stdout);
+ printf(" rmdesc : ");utf_fprint_printable_ascii(stdout,refmethod->descriptor);fputc('\n',stdout);
+ printf(" name : ");utf_fprint_printable_ascii(stdout,methodref->name);fputc('\n',stdout);
+ printf(" desc : ");utf_fprint_printable_ascii(stdout,methodref->descriptor);fputc('\n',stdout);
#endif
/* allocate params if necessary */
if (!methodref->parseddesc.md->params)
if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
- (staticmethod) ? ACC_STATIC : ACC_NONE))
+ (invokestatic) ? ACC_STATIC : ACC_NONE))
return NULL;
/* create the data structure */
ref = NEW(unresolved_method);
- ref->flags = ((staticmethod) ? RESOLVE_STATIC : 0)
- | ((iptr->opc == ICMD_INVOKESPECIAL) ? RESOLVE_SPECIAL : 0);
+ ref->flags = ((invokestatic) ? RESOLVE_STATIC : 0)
+ | ((invokespecial) ? RESOLVE_SPECIAL : 0);
ref->referermethod = refmethod;
ref->methodref = methodref;
ref->paramconstraints = NULL;
return ref;
}
-unresolved_method * create_unresolved_method(classinfo *referer, methodinfo *refmethod,
- instruction *iptr)
+
+/* resolve_constrain_unresolved_method_instance ********************************
+
+ Record subtype constraints for the instance argument of a method call.
+
+ IN:
+ ref..............the unresolved_method structure of the call
+ referer..........the class containing the reference
+ refmethod........the method triggering the resolution (if any)
+ iptr.............the INVOKE* instruction
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
+ methodinfo *refmethod,
+ typeinfo_t *instanceti,
+ bool invokespecial)
{
- unresolved_method *ref;
- constant_FMIref *methodref;
- bool staticmethod;
+ constant_FMIref *methodref;
+ constant_classref *instanceref;
+ typeinfo_t tinfo;
+ typeinfo_t *tip;
- methodref = (constant_FMIref *) iptr[0].val.a;
+ assert(ref);
+ methodref = ref->methodref;
assert(methodref);
- staticmethod = (iptr[0].opc == ICMD_INVOKESTATIC);
+
+ /* XXX clean this up */
+ instanceref = IS_FMIREF_RESOLVED(methodref)
+ ? class_get_self_classref(methodref->p.method->clazz)
+ : methodref->p.classref;
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"create_unresolved_method\n");
- fprintf(stderr," referer: ");utf_fprint_printable_ascii(stderr,referer->name);fputc('\n',stderr);
- fprintf(stderr," rmethod: ");utf_fprint_printable_ascii(stderr,refmethod->name);fputc('\n',stderr);
- fprintf(stderr," rmdesc : ");utf_fprint_printable_ascii(stderr,refmethod->descriptor);fputc('\n',stderr);
- fprintf(stderr," class : ");utf_fprint_printable_ascii(stderr,methodref->classref->name);fputc('\n',stderr);
- fprintf(stderr," name : ");utf_fprint_printable_ascii(stderr,methodref->name);fputc('\n',stderr);
- fprintf(stderr," desc : ");utf_fprint_printable_ascii(stderr,methodref->descriptor);fputc('\n',stderr);
- /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
+ printf("resolve_constrain_unresolved_method_instance\n");
+ printf(" rmethod: "); method_println(refmethod);
+ printf(" mref : "); method_methodref_println(methodref);
#endif
- /* allocate params if necessary */
- if (!methodref->parseddesc.md->params)
- if (!descriptor_params_from_paramtypes(methodref->parseddesc.md,
- (staticmethod) ? ACC_STATIC : ACC_NONE))
- return NULL;
+ /* record subtype constraints for the instance type, if any */
- /* create the data structure */
- ref = NEW(unresolved_method);
- ref->flags = ((staticmethod) ? RESOLVE_STATIC : 0)
- | ((iptr[0].opc == ICMD_INVOKESPECIAL) ? RESOLVE_SPECIAL : 0);
- ref->referermethod = refmethod;
- ref->methodref = methodref;
- ref->paramconstraints = NULL;
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
+ 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->clazz);
+ tip = &tinfo;
+ if (!typeinfo_init_class(tip, initclass))
+ return false;
+ }
+ else {
+ tip = instanceti;
+ }
- return ref;
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
+ &(ref->instancetypes),tip,instanceref->name))
+ return false;
+
+ return true;
}
+#endif /* defined(ENABLE_VERIFIER) */
-/* constrain_unresolved_method *************************************************
+
+/* resolve_constrain_unresolved_method_params *********************************
- Record subtype constraints for the arguments of a method call.
+ Record subtype constraints for the non-instance arguments of a method call.
IN:
+ jd...............current jitdata (for looking up variables)
ref..............the unresolved_method structure of the call
- referer..........the class containing the reference
refmethod........the method triggering the resolution (if any)
iptr.............the INVOKE* instruction
- stack............the input stack of the instruction
RETURN VALUE:
true.............everything ok
*******************************************************************************/
-#ifdef ENABLE_VERIFIER
-bool constrain_unresolved_method(unresolved_method *ref,
- classinfo *referer, methodinfo *refmethod,
- instruction *iptr,
- stackelement *stack)
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_params(jitdata *jd,
+ unresolved_method *ref,
+ methodinfo *refmethod,
+ instruction *iptr)
{
constant_FMIref *methodref;
- constant_classref *instanceref;
- stackelement *instanceslot = NULL;
- stackelement *param;
+ varinfo *param;
methoddesc *md;
- typeinfo tinfo;
int i,j;
int type;
int instancecount;
assert(md);
assert(md->params != NULL);
- /* XXX clean this up */
- instanceref = IS_FMIREF_RESOLVED(methodref)
- ? class_get_self_classref(methodref->p.method->class)
- : methodref->p.classref;
-
#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"constrain_unresolved_method\n");
- fprintf(stderr," referer: ");utf_fprint_printable_ascii(stderr,referer->name);fputc('\n',stderr);
- fprintf(stderr," rmethod: ");utf_fprint_printable_ascii(stderr,refmethod->name);fputc('\n',stderr);
- fprintf(stderr," rmdesc : ");utf_fprint_printable_ascii(stderr,refmethod->descriptor);fputc('\n',stderr);
- fprintf(stderr," class : ");utf_fprint_printable_ascii(stderr,methodref->classref->name);fputc('\n',stderr);
- fprintf(stderr," name : ");utf_fprint_printable_ascii(stderr,methodref->name);fputc('\n',stderr);
- fprintf(stderr," desc : ");utf_fprint_printable_ascii(stderr,methodref->descriptor);fputc('\n',stderr);
- /*fprintf(stderr," opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
+ printf("resolve_constrain_unresolved_method_params\n");
+ printf(" rmethod: "); method_println(refmethod);
+ printf(" mref : "); method_methodref_println(methodref);
#endif
- if ((ref->flags & RESOLVE_STATIC) == 0) {
- /* find the instance slot under all the parameter slots on the stack */
- instanceslot = stack;
- for (i=1; i<md->paramcount; ++i)
- instanceslot = instanceslot->prev;
- instancecount = 1;
- }
- else {
- instancecount = 0;
- }
+ instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
- assert((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
+ /* record subtype constraints for the parameter types, if any */
- /* record subtype constraints for the instance type, if any */
- if (instanceslot) {
- typeinfo *tip;
-
- 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) ? ICMD_ACONST_CLASSREF_OR_CLASSINFO(ins-1)
- : CLASSREF_OR_CLASSINFO(refmethod->class);
- tip = &tinfo;
- if (!typeinfo_init_class(tip,initclass))
+ for (i=md->paramcount-1-instancecount; i>=0; --i) {
+ param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
+ type = md->paramtypes[i+instancecount].type;
+
+ assert(param);
+ assert(type == param->type);
+
+ if (type == TYPE_ADR) {
+ if (!ref->paramconstraints) {
+ ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
+ for (j=md->paramcount-1-instancecount; j>i; --j)
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
+ }
+ assert(ref->paramconstraints);
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
+ ref->paramconstraints + i,&(param->typeinfo),
+ md->paramtypes[i+instancecount].classref->name))
return false;
}
else {
- tip = &(instanceslot->typeinfo);
+ if (ref->paramconstraints)
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
}
- if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
- &(ref->instancetypes),tip,instanceref))
- return false;
}
+ return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+
+/* resolve_constrain_unresolved_method_params_stackbased ***********************
+
+ Record subtype constraints for the non-instance arguments of a method call.
+
+ IN:
+ ref..............the unresolved_method structure of the call
+ refmethod........the method triggering the resolution (if any)
+ stack............TOS before the INVOKE instruction
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_method_params_stackbased(
+ unresolved_method *ref,
+ methodinfo *refmethod,
+ typedescriptor_t *stack)
+{
+ constant_FMIref *methodref;
+ typedescriptor_t *param;
+ methoddesc *md;
+ int i,j;
+ int type;
+ int instancecount;
+
+ assert(ref);
+ methodref = ref->methodref;
+ assert(methodref);
+ md = methodref->parseddesc.md;
+ assert(md);
+ assert(md->params != NULL);
+
+#ifdef RESOLVE_VERBOSE
+ printf("resolve_constrain_unresolved_method_params_stackbased\n");
+ printf(" rmethod: "); method_println(refmethod);
+ printf(" mref : "); method_methodref_println(methodref);
+#endif
+
+ instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
+
/* record subtype constraints for the parameter types, if any */
- param = stack;
- for (i=md->paramcount-1-instancecount; i>=0; --i, param=param->prev) {
- type = md->paramtypes[i+instancecount].type;
- assert(param);
+ param = stack - (md->paramslots - 1 - instancecount);
+
+ for (i = instancecount; i < md->paramcount; ++i) {
+ type = md->paramtypes[i].type;
+
assert(type == param->type);
if (type == TYPE_ADR) {
if (!ref->paramconstraints) {
ref->paramconstraints = MNEW(unresolved_subtype_set,md->paramcount);
- for (j=md->paramcount-1-instancecount; j>i; --j)
+ for (j = 0; j < i - instancecount; ++j)
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
}
assert(ref->paramconstraints);
- if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
- ref->paramconstraints + i,&(param->typeinfo),
- md->paramtypes[i+instancecount].classref))
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
+ ref->paramconstraints + i - instancecount,&(param->typeinfo),
+ md->paramtypes[i].classref->name))
return false;
}
else {
if (ref->paramconstraints)
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[i]);
}
+
+ param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
}
return true;
}
#endif /* ENABLE_VERIFIER */
+
/******************************************************************************/
/* FREEING MEMORY */
/******************************************************************************/
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: ");
}
#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:
*/
-