+#if true != 1
+#error This code assumes that `true` is `1`. Otherwise, use the ternary operator below.
+#endif
+
+ 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;
+ }
+
+ /* 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);
+ return resolveFailed; /* exception */
+ }
+
+ /* for non-static methods we have to check the constraints on the */
+ /* instance type */
+
+ if (instanceslot) {
+ 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)) {
+ *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on non-reference");
+ return resolveFailed;
+ }
+ if (TYPEINFO_IS_ARRAY(instanceslot->typeinfo)) {
+ *exceptionptr = new_verifyerror(refmethod, "illegal instruction: field access on array");
+ 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) {
+ *exceptionptr = new_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
+ curstack.........instack of the instruction
+ 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,
+ 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 */
+
+ 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 = resolve_field_verifier_checks(refmethod, fieldref, container,
+ fi,
+ iptr->opc,
+ curstack);
+
+ if (result != resolveSucceeded)
+ return result;
+ }
+#endif /* defined(ENABLE_VERIFIER) */
+
+ /* everything ok */
+ return resolveSucceeded;
+}
+
+resolve_result_t resolve_field_lazy(instruction *iptr,stackptr curstack,
+ methodinfo *refmethod)
+{
+ classinfo *referer;
+ classinfo *container;
+ fieldinfo *fi;
+ constant_FMIref *fieldref;
+ resolve_result_t result;
+
+ assert(iptr);
+ assert(refmethod);
+
+ /* the class containing the reference */
+
+ referer = refmethod->class;
+ assert(referer);
+
+ /* get the field reference */
+
+ if (iptr->opc == ICMD_PUTFIELDCONST || iptr->opc == ICMD_PUTSTATICCONST)
+ INSTRUCTION_GET_FIELDREF(iptr + 1,fieldref);
+ else
+ INSTRUCTION_GET_FIELDREF(iptr,fieldref);
+
+ /* check if the field itself is already resolved */
+
+ if (IS_FMIREF_RESOLVED(fieldref)) {
+ fi = fieldref->p.field;
+ container = fi->class;
+ goto resolved_the_field;
+ }
+
+ /* first we must resolve the class containg the field */
+
+ /* XXX can/may lazyResolving trigger linking? */
+
+ if (!resolve_class_from_name(referer,refmethod,
+ fieldref->p.classref->name,resolveLazy,true,true,&container))
+ {
+ /* the class reference could not be resolved */
+ return resolveFailed; /* exception */
+ }
+ if (!container)
+ return resolveDeferred; /* be lazy */
+
+ assert(container->state & CLASS_LINKED);
+
+ /* now we must find the declaration of the field in `container`
+ * or one of its superclasses */
+
+ fi = class_resolvefield(container,
+ fieldref->name,fieldref->descriptor,
+ referer,true);
+ if (!fi) {
+ /* The field does not exist. But since we were called lazily, */
+ /* this error must not be reported now. (It will be reported */
+ /* if eager resolving of this field is ever tried.) */
+
+ *exceptionptr = NULL;
+ 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 */
+
+ referer = ref->referermethod->class;
+ assert(referer);
+
+ /* check if the field itself is already resolved */
+ if (IS_FMIREF_RESOLVED(ref->fieldref)) {
+ fi = ref->fieldref->p.field;
+ container = fi->class;
+ goto resolved_the_field;
+ }
+
+ /* first we must resolve the class containg the field */
+ if (!resolve_class_from_name(referer,ref->referermethod,
+ ref->fieldref->p.classref->name,mode,true,true,&container))
+ {
+ /* the class reference could not be resolved */
+ return false; /* exception */
+ }
+ if (!container)
+ return true; /* be lazy */
+
+ assert(container);
+ assert(container->state & CLASS_LOADED);
+ assert(container->state & CLASS_LINKED);
+
+ /* now we must find the declaration of the field in `container`
+ * or one of its superclasses */
+
+#ifdef RESOLVE_VERBOSE
+ fprintf(stderr," resolving field in class...\n");
+#endif
+
+ fi = class_resolvefield(container,
+ ref->fieldref->name,ref->fieldref->descriptor,
+ referer,true);
+ if (!fi) {
+ if (mode == resolveLazy) {
+ /* The field does not exist. But since we were called lazily, */
+ /* this error must not be reported now. (It will be reported */
+ /* if eager resolving of this field is ever tried.) */
+
+ *exceptionptr = NULL;
+ return true; /* be lazy */
+ }
+
+ return false; /* exception */
+ }
+
+ /* cache the result of the resolution */
+ ref->fieldref->p.field = fi;
+
+resolved_the_field:
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ checkresult = resolve_field_verifier_checks(ref->referermethod,
+ ref->fieldref,
+ container,
+ fi,
+ /* XXX pass NULL instruction * */
+ (ref->flags & RESOLVE_STATIC) ? ICMD_GETSTATIC : ICMD_GETFIELD,
+ NULL);
+
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+
+ declarer = fi->class;
+ assert(declarer);
+ assert(declarer->state & CLASS_LOADED);
+ assert(declarer->state & CLASS_LINKED);
+
+ /* for non-static accesses we have to check the constraints on the */
+ /* instance type */
+
+ if (!(ref->flags & RESOLVE_STATIC)) {
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->instancetypes),
+ CLASSREF_OR_CLASSINFO(container),
+ mode, resolveLinkageError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ }
+
+ fieldtyperef = ref->fieldref->parseddesc.fd->classref;
+
+ /* for PUT* instructions we have to check the constraints on the value type */
+ if (((ref->flags & RESOLVE_PUTFIELD) != 0) && fi->type == TYPE_ADR) {
+ assert(fieldtyperef);
+ if (!SUBTYPESET_IS_EMPTY(ref->valueconstraints)) {
+ /* check subtype constraints */
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->valueconstraints),
+ CLASSREF_OR_CLASSINFO(fieldtyperef),
+ mode, resolveLinkageError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ }
+ }
+
+ /* check protected access */
+ if (((fi->flags & ACC_PROTECTED) != 0) && !SAME_PACKAGE(declarer,referer)) {
+ checkresult = resolve_and_check_subtype_set(ref->referermethod,
+ &(ref->instancetypes),
+ CLASSREF_OR_CLASSINFO(referer),
+ mode,
+ resolveIllegalAccessError);
+ if (checkresult != resolveSucceeded)
+ return (bool) checkresult;
+ }
+
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* succeed */
+ *result = fi;
+
+ return true;
+}
+
+/* resolve_field_eager *********************************************************
+
+ Resolve an unresolved field reference eagerly.
+
+ IN:
+ ref..............struct containing the reference
+
+ RETURN VALUE:
+ fieldinfo * to the field, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+fieldinfo * resolve_field_eager(unresolved_field *ref)
+{
+ fieldinfo *fi;
+
+ if (!resolve_field(ref,resolveEager,&fi))
+ return NULL;
+
+ return fi;
+}
+
+/******************************************************************************/
+/* METHOD RESOLUTION */
+/******************************************************************************/
+
+/* resolve_method_invokespecial_lookup *****************************************
+
+ Do the special lookup for methods invoked by INVOKESPECIAL
+
+ IN:
+ refmethod........the method containing the reference
+ mi...............the methodinfo of the resolved method
+
+ RETURN VALUE:
+ a methodinfo *...the result of the lookup,
+ NULL.............an exception has been thrown
+
+*******************************************************************************/
+
+methodinfo * resolve_method_invokespecial_lookup(methodinfo *refmethod,
+ methodinfo *mi)
+{
+ classinfo *declarer;
+ classinfo *referer;