/* 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 5293 2006-09-05 00:02:30Z 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);
*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) {
+ /* If the exception is a ClassNotFoundException,
+ convert it to a NoClassDefFoundError. */
+
+ exceptions_classnotfoundexception_to_noclassdeffounderror();
+
+ 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->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);
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->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
*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 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 */
}
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 */
}
#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 */
/******************************************************************************/
-/* new_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
- iptr.............field instruction or NULL
+ 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
*******************************************************************************/
#if defined(ENABLE_VERIFIER)
-resolve_result_t new_resolve_field_verifier_checks(methodinfo *refmethod,
+resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
constant_FMIref *fieldref,
classinfo *container,
fieldinfo *fi,
- s4 opc,
- new_instruction *iptr)
+ typeinfo *instanceti,
+ typeinfo *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);
fieldtyperef = fieldref->parseddesc.fd->classref;
- /* get opcode dependent values */
-
- switch (opc) {
- case ICMD_PUTFIELD:
- isput = true;
- if (iptr) {
- valueslot = iptr->sx.s23.s2.var;
- instanceslot = iptr->s1.var;
- }
- break;
-
- case ICMD_PUTFIELDCONST:
- isput = true;
- if (iptr)
- instanceslot = iptr->s1.var;
- break;
-
- case ICMD_PUTSTATIC:
- isput = true;
- isstatic = true;
- if (iptr)
- valueslot = iptr->s1.var;
- break;
-
- case ICMD_PUTSTATICCONST:
- isput = true;
- isstatic = true;
- break;
-
- case ICMD_GETFIELD:
- if (iptr)
- instanceslot = iptr->s1.var;
- 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) {
+ if (instanceti) {
typeinfo *insttip;
typeinfo 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)) {
+ if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
return resolveFailed;
}
- if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
+ 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;
- new_instruction *ins = (new_instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
+ instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
if (ins != NULL) {
- exceptions_throw_verifyerror(refmethod,"accessing field of uninitialized object");
+ exceptions_throw_verifyerror(refmethod, "accessing field of uninitialized object");
return resolveFailed;
}
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;
}
#endif /* defined(ENABLE_VERIFIER) */
-/* resolve_field_verifier_checks ***********************************************
+/* resolve_field_lazy **********************************************************
- Do the verifier checks necessary after field has been resolved.
+ 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:
- refmethod........the method containing the reference
+ refmethod........the referer method
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
RETURN VALUE:
- resolveSucceeded....everything ok
- resolveDeferred.....tests could not be done, have been deferred
- resolveFailed.......exception has been thrown
+ resolveSucceeded.....the reference has been resolved
+ resolveDeferred......the resolving could not be performed lazily
+ resolveFailed........resolving failed, an exception has been thrown.
*******************************************************************************/
-#if defined(ENABLE_VERIFIER)
-resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
- constant_FMIref *fieldref,
- classinfo *container,
- fieldinfo *fi,
- s4 opc,
- stackptr curstack)
+resolve_result_t resolve_field_lazy(methodinfo *refmethod,
+ constant_FMIref *fieldref)
{
- classinfo *declarer;
classinfo *referer;
- resolve_result_t result;
- bool isstatic = false;
- bool isput = false;
- stackelement *instanceslot = NULL;
- stackelement *valueslot = NULL;
- constant_classref *fieldtyperef;
+ classinfo *container;
+ fieldinfo *fi;
assert(refmethod);
- assert(fieldref);
- assert(container);
- assert(fi);
- /* get the classinfos and the field type */
+ /* the class containing the reference */
referer = refmethod->class;
assert(referer);
- declarer = fi->class;
- assert(declarer);
- assert(referer->state & CLASS_LINKED);
+ /* check if the field itself is already resolved */
- fieldtyperef = fieldref->parseddesc.fd->classref;
+ if (IS_FMIREF_RESOLVED(fieldref))
+ return resolveSucceeded;
- /* get opcode dependent values */
+ /* first we must resolve the class containg the field */
- switch (opc) {
- case ICMD_PUTFIELD:
- isput = true;
- if (curstack) {
- valueslot = curstack;
- instanceslot = curstack->prev;
- }
- break;
+ /* XXX can/may lazyResolving trigger linking? */
- case ICMD_PUTFIELDCONST:
- isput = true;
- instanceslot = curstack;
- break;
+ 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 */
- case ICMD_PUTSTATIC:
- isput = true;
- isstatic = true;
- valueslot = curstack;
- break;
+ assert(container->state & CLASS_LINKED);
- case ICMD_PUTSTATICCONST:
- isput = true;
- isstatic = true;
- break;
+ /* now we must find the declaration of the field in `container`
+ * or one of its superclasses */
- case ICMD_GETFIELD:
- instanceslot = curstack;
- break;
+ 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.) */
- case ICMD_GETSTATIC:
- isstatic = true;
- break;
+ exceptions_clear_exception();
+ return resolveDeferred; /* be lazy */
}
- /* check static */
+ /* cache the result of the resolution */
-#if true != 1
-#error This code assumes that `true` is `1`. Otherwise, use the ternary operator below.
-#endif
+ fieldref->p.field = fi;
- 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");
- return resolveFailed;
- }
+ /* everything ok */
+ return resolveSucceeded;
+}
- /* check access rights */
+/* resolve_field ***************************************************************
+
+ Resolve an unresolved field reference
+
+ IN:
+ ref..............struct containing the reference
+ mode.............mode of resolution:
+ resolveLazy...only resolve if it does not
+ require loading classes
+ resolveEager..load classes if necessary
+
+ OUT:
+ *result..........set to the result of resolution, or to NULL if
+ the reference has not been resolved
+ In the case of an exception, *result is
+ guaranteed to be set to NULL.
+
+ RETURN VALUE:
+ true.............everything ok
+ (*result may still be NULL for resolveLazy)
+ false............an exception has been thrown
+
+*******************************************************************************/
- 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);
- return resolveFailed; /* exception */
- }
+bool resolve_field(unresolved_field *ref,
+ resolve_mode_t mode,
+ fieldinfo **result)
+{
+ classinfo *referer;
+ classinfo *container;
+ classinfo *declarer;
+ constant_classref *fieldtyperef;
+ fieldinfo *fi;
+ resolve_result_t checkresult;
- /* for non-static methods we have to check the constraints on the */
- /* instance type */
+ assert(ref);
+ assert(result);
+ assert(mode == resolveLazy || mode == resolveEager);
- if (instanceslot) {
- typeinfo *insttip;
- typeinfo tinfo;
+ *result = NULL;
- /* The instanceslot must contain a reference to a non-array type */
+#ifdef RESOLVE_VERBOSE
+ unresolved_field_debug_dump(ref,stdout);
+#endif
- assert(instanceslot->type == TYPE_ADR); /* checked earlier */
-
- if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
- exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
- return resolveFailed;
- }
- if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
- exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on array");
- return resolveFailed;
- }
-
- if (isput && TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
- {
- /* 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);
-
- if (ins != NULL) {
- exceptions_throw_verifyerror(refmethod,"accessing field of uninitialized object");
- return resolveFailed;
- }
-
- /* XXX check that class of field == refmethod->class */
- initclass = referer; /* XXX classrefs */
- assert(initclass->state & CLASS_LINKED);
-
- typeinfo_init_classinfo(&tinfo,initclass);
- insttip = &tinfo;
- }
- else {
- insttip = &(instanceslot->typeinfo);
- }
-
- result = resolve_lazy_subtype_checks(refmethod,
- insttip,
- CLASSREF_OR_CLASSINFO(container),
- resolveLinkageError);
- if (result != resolveSucceeded)
- return result;
-
- /* check protected access */
-
- if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer))
- {
- result = resolve_lazy_subtype_checks(refmethod,
- &(instanceslot->typeinfo),
- CLASSREF_OR_CLASSINFO(referer),
- resolveIllegalAccessError);
- if (result != resolveSucceeded)
- return result;
- }
-
- }
-
- /* for PUT* instructions we have to check the constraints on the value type */
-
- if (valueslot && valueslot->type == TYPE_ADR) {
- assert(fieldtyperef);
-
- /* check subtype constraints */
- result = resolve_lazy_subtype_checks(refmethod,
- &(valueslot->typeinfo),
- CLASSREF_OR_CLASSINFO(fieldtyperef),
- resolveLinkageError);
-
- if (result != resolveSucceeded)
- return result;
- }
-
- /* impose loading constraint on field type */
-
- if (fi->type == TYPE_ADR) {
- assert(fieldtyperef);
- if (!classcache_add_constraint(declarer->classloader,
- referer->classloader,
- fieldtyperef->name))
- return resolveFailed;
- }
-
- /* XXX impose loading constraing on instance? */
-
- /* everything ok */
- return resolveSucceeded;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-/* resolve_field_lazy **********************************************************
-
- Resolve an unresolved field reference lazily
-
- IN:
- iptr.............instruction containing the field reference
- refmethod........the referer method
-
- RETURN VALUE:
- resolveSucceeded.....the reference has been resolved
- resolveDeferred......the resolving could not be performed lazily
- resolveFailed........resolving failed, an exception has been thrown.
-
-*******************************************************************************/
-
-resolve_result_t new_resolve_field_lazy(new_instruction *iptr,
- 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 */
-
- 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;
- }
-
- /* 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;
- 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 = new_resolve_field_verifier_checks(refmethod, fieldref, container,
- fi,
- iptr->opc,
- iptr);
-
- 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;
- 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_field ***************************************************************
-
- Resolve an unresolved field reference
-
- IN:
- ref..............struct containing the reference
- mode.............mode of resolution:
- resolveLazy...only resolve if it does not
- require loading classes
- resolveEager..load classes if necessary
-
- OUT:
- *result..........set to the result of resolution, or to NULL if
- the reference has not been resolved
- In the case of an exception, *result is
- guaranteed to be set to NULL.
-
- RETURN VALUE:
- true.............everything ok
- (*result may still be NULL for resolveLazy)
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool resolve_field(unresolved_field *ref,
- resolve_mode_t mode,
- fieldinfo **result)
-{
- classinfo *referer;
- classinfo *container;
- classinfo *declarer;
- constant_classref *fieldtyperef;
- fieldinfo *fi;
- resolve_result_t checkresult;
-
- assert(ref);
- assert(result);
- assert(mode == resolveLazy || mode == resolveEager);
-
- *result = NULL;
-
-#ifdef RESOLVE_VERBOSE
- unresolved_field_debug_dump(ref,stderr);
-#endif
-
- /* the class containing the reference */
+ /* the class containing the reference */
referer = ref->referermethod->class;
assert(referer);
* 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 = new_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;
if (mi == NULL) {
/* the spec calls for an AbstractMethodError in this case */
+
exceptions_throw_abstractmethoderror();
+
return NULL;
}
}
return mi;
}
-/* new_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
- iptr.............the invoke instruction, or NULL
RETURN VALUE:
resolveSucceeded....everything ok
*******************************************************************************/
#if defined(ENABLE_VERIFIER)
-resolve_result_t new_resolve_method_verifier_checks(methodinfo *refmethod,
+resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
constant_FMIref *methodref,
- classinfo *container,
methodinfo *mi,
- bool invokestatic,
- bool invokespecial,
- new_instruction *iptr)
+ 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 */
declarer = mi->class;
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 (iptr) {
- /* for non-static methods we have to check the constraints on the */
- /* instance type */
- if (!invokestatic) {
- /* find the instance slot under all the parameter slots on the stack */
- instanceslot = iptr->sx.s23.s2.args[0];
- }
-
- assert((instanceslot && instancecount == 1) || invokestatic);
-
- /* record subtype constraints for the instance type, if any */
- if (instanceslot) {
- typeinfo *tip;
+ msglen =
+ utf_bytes(declarer->name) +
+ utf_bytes(mi->name) +
+ utf_bytes(mi->descriptor) +
+ utf_bytes(referer->name) +
+ 100;
- assert(instanceslot->type == TYPE_ADR);
-
- if (invokespecial &&
- TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
- { /* XXX clean up */
- new_instruction *ins = (new_instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
- classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
- : CLASSREF_OR_CLASSINFO(refmethod->class);
- tip = &tinfo;
- if (!typeinfo_init_class(tip,initclass))
- return false;
- }
- else {
- tip = &(instanceslot->typeinfo);
- }
+ msg = MNEW(char, msglen);
- result = resolve_lazy_subtype_checks(refmethod,
- tip,
- CLASSREF_OR_CLASSINFO(container),
- resolveLinkageError);
- if (result != resolveSucceeded)
- return result;
+ 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, ")");
- /* check protected access */
+ u = utf_new_char(msg);
- 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;
- }
+ MFREE(msg, char, msglen);
- }
+ exceptions_throw_illegalaccessexception(u);
- /* check subtype constraints for TYPE_ADR parameters */
+ return resolveFailed; /* exception */
+ }
- assert(md->paramcount == methodref->parseddesc.md->paramcount);
- paramtypes = md->paramtypes;
+ /* everything ok */
- for (i = md->paramcount-1-instancecount; i>=0; --i) {
- param = iptr->sx.s23.s2.args[i+instancecount];
- type = md->paramtypes[i+instancecount].type;
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
- 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;
- }
- }
+/* resolve_method_instance_type_checks *****************************************
- } /* if (iptr) */
+ Check the instance type of a method invocation.
- /* impose loading constraints on parameters (including instance) */
+ 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
- paramtypes = md->paramtypes;
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
- 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;
- }
- else {
- name = paramtypes[i].classref->name;
- }
+#if defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
+ methodinfo *mi,
+ typeinfo *instanceti,
+ bool invokespecial)
+{
+ typeinfo tinfo;
+ typeinfo *tip;
+ resolve_result_t result;
- /* 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 */
- }
+ 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);
+ tip = &tinfo;
+ if (!typeinfo_init_class(tip, initclass))
+ return false;
+ }
+ else {
+ tip = instanceti;
}
- /* impose loading constraint onto return type */
+ result = resolve_lazy_subtype_checks(refmethod,
+ tip,
+ CLASSREF_OR_CLASSINFO(mi->class),
+ resolveLinkageError);
+ if (result != resolveSucceeded)
+ return result;
- 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 */
+ /* check protected access */
+
+ /* XXX use other `declarer` than mi->class? */
+ if (((mi->flags & ACC_PROTECTED) != 0)
+ && !SAME_PACKAGE(mi->class, refmethod->class))
+ {
+ result = resolve_lazy_subtype_checks(refmethod,
+ tip,
+ CLASSREF_OR_CLASSINFO(refmethod->class),
+ resolveIllegalAccessError);
+ if (result != resolveSucceeded)
+ return result;
}
/* everything ok */
+
return resolveSucceeded;
}
#endif /* defined(ENABLE_VERIFIER) */
-/* resolve_method_verifier_checks **********************************************
-
- Do the verifier checks necessary after a method has been resolved.
-
+
+/* 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
- methodref........the method reference
- container........the class where the method was found
+ 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_verifier_checks(methodinfo *refmethod,
- constant_FMIref *methodref,
- classinfo *container,
- methodinfo *mi,
- bool invokestatic,
- bool invokespecial,
- stackptr curstack)
+resolve_result_t resolve_method_param_type_checks(jitdata *jd,
+ methodinfo *refmethod,
+ instruction *iptr,
+ methodinfo *mi,
+ bool invokestatic)
{
- classinfo *declarer;
- classinfo *referer;
+ varinfo *param;
resolve_result_t result;
- int instancecount;
- typedesc *paramtypes;
- int i;
- stackelement *instanceslot = NULL;
- stackelement *param;
- methoddesc *md;
- typeinfo tinfo;
- int type;
+ methoddesc *md;
+ typedesc *paramtypes;
+ s4 type;
+ s4 instancecount;
+ s4 i;
- assert(refmethod);
- assert(methodref);
- assert(container);
- assert(mi);
+ assert(jd);
-#ifdef RESOLVE_VERBOSE
- fprintf(stderr,"resolve_method_verifier_checks\n");
- fprintf(stderr," flags: %02x\n",mi->flags);
-#endif
+ instancecount = (invokestatic) ? 0 : 1;
- /* get the classinfos and the method descriptor */
+ /* 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;
+ }
+ }
- referer = refmethod->class;
- assert(referer);
+ /* everything ok */
- declarer = mi->class;
- assert(declarer);
- assert(referer->state & CLASS_LINKED);
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
- md = methodref->parseddesc.md;
- assert(md);
- assert(md->params);
- instancecount = (invokestatic) ? 0 : 1;
+/* resolve_method_param_type_checks_stackbased *********************************
- /* check static */
+ Check non-instance parameter types of a method invocation.
- 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");
- return resolveFailed;
- }
+ 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
- /* check access rights */
+ RETURN VALUE:
+ resolveSucceeded....everything ok
+ resolveDeferred.....tests could not be done, have been deferred
+ resolveFailed.......exception has been thrown
- 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 defined(ENABLE_VERIFIER)
+resolve_result_t resolve_method_param_type_checks_stackbased(
+ methodinfo *refmethod,
+ methodinfo *mi,
+ bool invokestatic,
+ typedescriptor *stack)
+{
+ typedescriptor *param;
+ resolve_result_t result;
+ methoddesc *md;
+ typedesc *paramtypes;
+ s4 type;
+ s4 instancecount;
+ s4 i;
- if (curstack) {
- /* for non-static methods we have to check the constraints on the */
- /* instance type */
+ instancecount = (invokestatic) ? 0 : 1;
- 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;
- }
+ /* check subtype constraints for TYPE_ADR parameters */
- assert((instanceslot && instancecount == 1) || invokestatic);
+ md = mi->parseddesc;
+ paramtypes = md->paramtypes;
- /* record subtype constraints for the instance type, if any */
- if (instanceslot) {
- typeinfo *tip;
+ param = stack - (md->paramslots - 1 - instancecount);
- assert(instanceslot->type == TYPE_ADR);
+ for (i = instancecount; i < md->paramcount; ++i) {
+ type = md->paramtypes[i].type;
- 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);
- }
+ assert(type == param->type);
+ if (type == TYPE_ADR) {
result = resolve_lazy_subtype_checks(refmethod,
- tip,
- CLASSREF_OR_CLASSINFO(container),
- resolveLinkageError);
+ &(param->typeinfo),
+ CLASSREF_OR_CLASSINFO(paramtypes[i].classref),
+ resolveLinkageError);
if (result != resolveSucceeded)
return result;
+ }
- /* check protected access */
+ param += (IS_2_WORD_TYPE(type)) ? 2 : 1;
+ }
- 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;
- }
+ /* everything ok */
- }
+ return resolveSucceeded;
+}
+#endif /* defined(ENABLE_VERIFIER) */
- /* check subtype constraints for TYPE_ADR parameters */
- assert(md->paramcount == methodref->parseddesc.md->paramcount);
- paramtypes = md->paramtypes;
- param = curstack;
+/* resolve_method_loading_constraints ******************************************
- for (i = md->paramcount-1-instancecount; i>=0; --i, param = param->prev) {
- type = md->paramtypes[i+instancecount].type;
+ Impose loading constraints on the parameters and return type of the
+ given method.
- assert(param);
- assert(type == param->type);
+ IN:
+ referer..........the class refering to the method
+ mi...............the method
- 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;
- }
- }
+ RETURN VALUE:
+ true................everything ok
+ false...............an exception has been thrown
+
+*******************************************************************************/
- } /* if (curstack) */
+#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->class->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->class->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->class->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
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,
- 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;
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 = new_resolve_method_verifier_checks(refmethod, methodref,
- container,
- mi,
- iptr->opc == ICMD_INVOKESTATIC,
- iptr->opc == ICMD_INVOKESPECIAL,
- iptr);
- 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;
/* 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 = new_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;
+ /* impose loading constraints on params and return type */
+
+ if (!resolve_method_loading_constraints(referer, mi))
+ return false;
+
declarer = mi->class;
assert(declarer);
assert(referer->state & CLASS_LINKED);
methodinfo *refmethod,
unresolved_subtype_set *stset,
typeinfo *tinfo,
- constant_classref *declaredtype)
+ 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)) {
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 */
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))
- return NULL;
- }
- else {
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
- }
-
- return ref;
-}
-#endif /* ENABLE_VERIFIER */
-
-/* create_unresolved_field *****************************************************
-
- Create an unresolved_field struct for the given field access instruction
-
- IN:
- referer..........the class containing the reference
- refmethod........the method triggering the resolution (if any)
- iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
-
- RETURN VALUE:
- a pointer to a new unresolved_field struct, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-unresolved_field * new_create_unresolved_field(classinfo *referer,
- methodinfo *refmethod,
- new_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->opc) {
- case ICMD_PUTFIELD:
- ref->flags |= RESOLVE_PUTFIELD;
- break;
-
- case ICMD_PUTFIELDCONST:
- ref->flags |= RESOLVE_PUTFIELD;
- break;
-
- case ICMD_PUTSTATIC:
- ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
- break;
-
- case ICMD_PUTSTATICCONST:
- ref->flags |= RESOLVE_PUTFIELD | RESOLVE_STATIC;
- break;
-
- case ICMD_GETFIELD:
- break;
-
- case ICMD_GETSTATIC:
- ref->flags |= RESOLVE_STATIC;
- break;
-
-#if !defined(NDEBUG)
- default:
- assert(false);
-#endif
+ &(ref->subtypeconstraints),valuetype,classref->name))
+ return NULL;
+ }
+ else {
+ UNRESOLVED_SUBTYPE_SET_EMTPY(ref->subtypeconstraints);
}
- fieldref = iptr->sx.s23.s3.fmiref;
-
- assert(fieldref);
+ return ref;
+}
+#endif /* ENABLE_VERIFIER */
-#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
+/* resolve_create_unresolved_field *********************************************
+
+ Create an unresolved_field struct for the given field access instruction
+
+ IN:
+ referer..........the class containing the reference
+ refmethod........the method triggering the resolution (if any)
+ iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
- ref->fieldref = fieldref;
+ RETURN VALUE:
+ a pointer to a new unresolved_field struct, or
+ NULL if an exception has been thrown
- return ref;
-}
+*******************************************************************************/
-unresolved_field * create_unresolved_field(classinfo *referer, methodinfo *refmethod,
- 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);
ref->referermethod = refmethod;
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
- switch (iptr[0].opc) {
+ switch (iptr->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]);*/
+#if !defined(NDEBUG)
+ default:
+ assert(false);
#endif
+ }
- ref->fieldref = fieldref;
-
- return ref;
-}
-
-/* new_constrain_unresolved_field **********************************************
-
- Record subtype constraints for a field access.
-
- IN:
- 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
-
- RETURN VALUE:
- true.............everything ok
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-bool new_constrain_unresolved_field(unresolved_field *ref,
- classinfo *referer, methodinfo *refmethod,
- new_instruction *iptr)
-{
- constant_FMIref *fieldref;
- stackelement *instanceslot = NULL;
- int type;
- typeinfo tinfo;
- typeinfo *tip = NULL;
- typedesc *fd;
-
- assert(ref);
+ fieldref = iptr->sx.s23.s3.fmiref;
- fieldref = ref->fieldref;
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(" 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 = iptr->s1.var;
- tip = &(iptr->sx.s23.s2.var->typeinfo);
- break;
-
- case ICMD_PUTFIELDCONST:
- instanceslot = iptr->s1.var;
- break;
-
- case ICMD_PUTSTATIC:
- tip = &(iptr->s1.var->typeinfo);
- break;
-
- case ICMD_GETFIELD:
- instanceslot = iptr->s1.var;
- break;
- }
-
- assert(instanceslot || ((ref->flags & RESOLVE_STATIC) != 0));
- fd = fieldref->parseddesc.fd;
- assert(fd);
-
- /* record subtype constraints for the instance type, if any */
- if (instanceslot) {
- typeinfo *insttip;
-
- /* The instanceslot must contain a reference to a non-array type */
- if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
- exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on non-reference");
- return false;
- }
- if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
- exceptions_throw_verifyerror(refmethod, "illegal instruction: field access on array");
- return false;
- }
-
- if (((ref->flags & RESOLVE_PUTFIELD) != 0) &&
- TYPEINFO_IS_NEWOBJECT(instanceslot->typeinfo))
- {
- /* 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;
- new_instruction *ins = (new_instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
-
- if (ins != NULL) {
- exceptions_throw_verifyerror(refmethod,"accessing field of uninitialized object");
- return false;
- }
- /* XXX check that class of field == refmethod->class */
- initclass = refmethod->class; /* XXX classrefs */
- assert(initclass->state & CLASS_LOADED);
- assert(initclass->state & CLASS_LINKED);
-
- typeinfo_init_classinfo(&tinfo,initclass);
- insttip = &tinfo;
- }
- else {
- insttip = &(instanceslot->typeinfo);
- }
- if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
- &(ref->instancetypes),insttip,fieldref->p.classref))
- return false;
- }
- else {
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->instancetypes);
- }
-
- /* 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 (iptr->sx.val.anyptr) {
- 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))
- return false;
- }
- else {
- UNRESOLVED_SUBTYPE_SET_EMTPY(ref->valueconstraints);
- }
+ ref->fieldref = fieldref;
- return true;
+ return ref;
}
-#endif /* ENABLE_VERIFIER */
-/* 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 *instanceti,
+ typeinfo *valueti)
{
constant_FMIref *fieldref;
- stackelement *instanceslot = NULL;
int type;
typeinfo tinfo;
- typeinfo *tip = NULL;
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) {
+ if (instanceti) {
typeinfo *insttip;
/* The instanceslot must contain a reference to a non-array type */
- if (!TYPEINFO_IS_REFERENCE(instanceslot->typeinfo)) {
- exceptions_throw_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)) {
- exceptions_throw_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) {
- exceptions_throw_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 */
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 *instanceti,
+ bool invokespecial)
{
- unresolved_method *ref;
- constant_FMIref *methodref;
- bool staticmethod;
+ constant_FMIref *methodref;
+ constant_classref *instanceref;
+ typeinfo tinfo;
+ typeinfo *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->class)
+ : 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->class);
+ tip = &tinfo;
+ if (!typeinfo_init_class(tip, initclass))
+ return false;
+ }
+ else {
+ tip = instanceti;
+ }
- return ref;
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+ &(ref->instancetypes),tip,instanceref->name))
+ return false;
+
+ return true;
}
+#endif /* defined(ENABLE_VERIFIER) */
-/* new_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
*******************************************************************************/
-#ifdef ENABLE_VERIFIER
-bool new_constrain_unresolved_method(unresolved_method *ref,
- classinfo *referer, methodinfo *refmethod,
- new_instruction *iptr)
+#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 = iptr->sx.s23.s2.args[0];
- instancecount = 1;
- }
- else {
- instancecount = 0;
- }
-
- assert((instanceslot && instancecount==1) || ((ref->flags & RESOLVE_STATIC) != 0));
-
- /* 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 */
- new_instruction *ins = (new_instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(instanceslot->typeinfo);
- classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
- : CLASSREF_OR_CLASSINFO(refmethod->class);
- tip = &tinfo;
- if (!typeinfo_init_class(tip,initclass))
- return false;
- }
- else {
- tip = &(instanceslot->typeinfo);
- }
- if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
- &(ref->instancetypes),tip,instanceref))
- return false;
- }
+ instancecount = (ref->flags & RESOLVE_STATIC) ? 0 : 1;
/* record subtype constraints for the parameter types, if any */
+
for (i=md->paramcount-1-instancecount; i>=0; --i) {
- param = iptr->sx.s23.s2.args[i+instancecount];
+ param = VAR(iptr->sx.s23.s2.args[i+instancecount]);
type = md->paramtypes[i+instancecount].type;
assert(param);
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
}
assert(ref->paramconstraints);
- if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
ref->paramconstraints + i,&(param->typeinfo),
- md->paramtypes[i+instancecount].classref))
+ md->paramtypes[i+instancecount].classref->name))
return false;
}
else {
}
#endif /* ENABLE_VERIFIER */
-/* constrain_unresolved_method *************************************************
+
+/* resolve_constrain_unresolved_method_params_stackbased ***********************
- Record subtype constraints for the arguments of a method call.
+ Record subtype constraints for the non-instance arguments 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
- stack............the input stack of the instruction
+ stack............TOS before the INVOKE 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_stackbased(
+ unresolved_method *ref,
+ methodinfo *refmethod,
+ typedescriptor *stack)
{
constant_FMIref *methodref;
- constant_classref *instanceref;
- stackelement *instanceslot = NULL;
- stackelement *param;
+ typedescriptor *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_stackbased\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))
- return false;
- }
- else {
- tip = &(instanceslot->typeinfo);
- }
- if (!unresolved_subtype_set_from_typeinfo(referer,refmethod,
- &(ref->instancetypes),tip,instanceref))
- return false;
- }
+ param = stack - (md->paramslots - 1 - instancecount);
- /* 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;
+ for (i = instancecount; i < md->paramcount; ++i) {
+ type = md->paramtypes[i].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)
+ 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->class, 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 */
/******************************************************************************/
}
#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:
*/
-