Changes: Christian Thalinger
- $Id: typecheck.c 5656 2006-10-03 20:57:15Z edwin $
+ $Id: typecheck.c 5723 2006-10-09 15:42:02Z edwin $
*/
case ICMD_PUTSTATICCONST:
case ICMD_GETFIELD:
case ICMD_GETSTATIC:
- TYPECHECK_COUNT(stat_ins_field);
+ {
+ varinfo *valueslot = NULL;
+ typeinfo *instanceti = NULL;
+ typeinfo *valueti = NULL;
+ bool isstatic = false;
+ bool isput = false;
+ typeinfo constti;
+
+ TYPECHECK_COUNT(stat_ins_field);
+
+ if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
+ uf = state->iptr->sx.s23.s3.uf;
+ fieldref = uf->fieldref;
+ }
+ else {
+ uf = NULL;
+ fieldref = state->iptr->sx.s23.s3.fmiref;
+ }
- if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
- uf = state->iptr->sx.s23.s3.uf;
- fieldref = uf->fieldref;
- }
- else {
- uf = NULL;
- fieldref = state->iptr->sx.s23.s3.fmiref;
- }
+ /* get opcode dependent values */
+
+ switch (state->iptr->opc) {
+ case ICMD_PUTFIELD:
+ isput = true;
+ valueslot = VAROP(state->iptr->sx.s23.s2);
+ instanceti = &(VAROP(state->iptr->s1)->typeinfo);
+ break;
+
+ case ICMD_PUTFIELDCONST:
+ isput = true;
+ instanceti = &(VAROP(state->iptr->s1)->typeinfo);
+putfield_const_tail:
+ if (IS_ADR_TYPE(fieldref->parseddesc.fd->type)) {
+ /* XXX check for java.lang.Class constant values? */
+ if (state->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(&constti, class_java_lang_String);
+ }
+ else {
+ TYPEINFO_INIT_NULLTYPE(constti);
+ }
+ valueti = &constti;
+ }
+ break;
+
+ case ICMD_PUTSTATIC:
+ isput = true;
+ isstatic = true;
+ valueslot = VAROP(state->iptr->s1);
+ break;
+
+ case ICMD_PUTSTATICCONST:
+ isput = true;
+ isstatic = true;
+ goto putfield_const_tail;
+
+ case ICMD_GETFIELD:
+ instanceti = &(VAROP(state->iptr->s1)->typeinfo);
+ break;
+
+ case ICMD_GETSTATIC:
+ isstatic = true;
+ break;
+
+ default:
+ assert(false);
+ }
- /* try to resolve the field reference lazily */
- result = resolve_field_lazy(jd, state->iptr, state->m);
- if (result == resolveFailed)
- return false;
+ if (valueslot && IS_ADR_TYPE(valueslot->type)) {
+ valueti = &(valueslot->typeinfo);
+ }
+
+ /* try to resolve the field reference lazily */
+
+ result = resolve_field_lazy(state->m, fieldref);
+
+ if (result == resolveSucceeded) {
+ fieldinfo *fi;
- if (result != resolveSucceeded) {
- if (!uf) {
- uf = create_unresolved_field(state->m->class, state->m, state->iptr);
- if (!uf)
- return false;
+ /* perform verification checks now */
- state->iptr->sx.s23.s3.uf = uf;
- state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+ fi = fieldref->p.field;
+
+ result = resolve_field_verifier_checks(
+ state->m, fieldref, fi->class, fi,
+ instanceti, valueti, isstatic, isput);
}
- /* record the subtype constraints for this field access */
- if (!constrain_unresolved_field(jd, uf,state->m->class,state->m,state->iptr))
- return false; /* XXX maybe wrap exception? */
+ if (result == resolveFailed)
+ return false;
+
+ /* if not resolved, yet, create an unresolved field */
- TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(state->iptr),stat_ins_field_unresolved);
- TYPECHECK_COUNTIF(INSTRUCTION_IS_RESOLVED(state->iptr) && !state->iptr->sx.s23.s3.fmiref->p.field->class->initialized,stat_ins_field_uninitialized);
- }
-
- if (iptr->opc == ICMD_GETFIELD || iptr->opc == ICMD_GETSTATIC) {
+ if (result != resolveSucceeded) {
+ if (!uf) {
+ uf = resolve_create_unresolved_field(state->m->class,
+ state->m, state->iptr);
+ if (!uf)
+ return false;
+
+ state->iptr->sx.s23.s3.uf = uf;
+ state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+ }
+
+ /* record the subtype constraints for this field access */
+
+ if (!resolve_constrain_unresolved_field(
+ uf, state->m->class, state->m,
+ instanceti, valueti))
+ return false; /* XXX maybe wrap exception? */
+
+ TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(state->iptr),stat_ins_field_unresolved);
+ TYPECHECK_COUNTIF(INSTRUCTION_IS_RESOLVED(state->iptr) &&
+ !state->iptr->sx.s23.s3.fmiref->p.field->class->initialized,
+ stat_ins_field_uninitialized);
+ }
+
/* write the result type */
- dv->type = fieldref->parseddesc.fd->type;
- if (dv->type == TYPE_ADR) {
- if (!typeinfo_init_from_typedesc(fieldref->parseddesc.fd,NULL,&(dv->typeinfo)))
- return false;
+
+ if (iptr->opc == ICMD_GETFIELD || iptr->opc == ICMD_GETSTATIC) {
+ dv->type = fieldref->parseddesc.fd->type;
+ if (dv->type == TYPE_ADR) {
+ if (!typeinfo_init_from_typedesc(fieldref->parseddesc.fd,
+ NULL, &(dv->typeinfo)))
+ return false;
+ }
}
- }
- maythrow = true;
+ maythrow = true;
+ }
break;
/****************************************/
Changes: Christan Thalinger
- $Id: resolve.c 5655 2006-10-03 20:44:46Z edwin $
+ $Id: resolve.c 5723 2006-10-09 15:42:02Z edwin $
*/
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 resolve_field_verifier_checks(jitdata *jd,
- methodinfo *refmethod,
+resolve_result_t resolve_field_verifier_checks(methodinfo *refmethod,
constant_FMIref *fieldref,
classinfo *container,
fieldinfo *fi,
- s4 opc,
- instruction *iptr)
+ typeinfo *instanceti,
+ typeinfo *valueti,
+ bool isstatic,
+ bool isput)
{
classinfo *declarer;
classinfo *referer;
resolve_result_t result;
- bool isstatic = false;
- bool isput = false;
- varinfo *instanceslot = NULL;
- varinfo *valueslot = NULL;
constant_classref *fieldtyperef;
assert(refmethod);
assert(fieldref);
assert(container);
assert(fi);
- assert(!iptr || jd);
/* get the classinfos and the field type */
fieldtyperef = fieldref->parseddesc.fd->classref;
- /* get opcode dependent values */
-
- switch (opc) {
- case ICMD_PUTFIELD:
- isput = true;
- if (iptr) {
- valueslot = VAROP(iptr->sx.s23.s2);
- instanceslot = VAROP(iptr->s1);
- }
- break;
-
- case ICMD_PUTFIELDCONST:
- isput = true;
- if (iptr)
- instanceslot = VAROP(iptr->s1);
- break;
-
- case ICMD_PUTSTATIC:
- isput = true;
- isstatic = true;
- if (iptr)
- valueslot = VAROP(iptr->s1);
- break;
-
- case ICMD_PUTSTATICCONST:
- isput = true;
- isstatic = true;
- break;
-
- case ICMD_GETFIELD:
- if (iptr)
- instanceslot = VAROP(iptr->s1);
- break;
-
- case ICMD_GETSTATIC:
- isstatic = true;
- break;
- }
-
/* check static */
#if true != 1
/* 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;
- 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 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;
/* resolve_field_lazy **********************************************************
Resolve an unresolved field reference lazily
+
+ NOTE: This function does NOT do any verification checks. In case of a
+ successful resolution, you must call resolve_field_verifier_checks
+ in order to perform the necessary checks!
IN:
- iptr.............instruction containing the field reference
refmethod........the referer method
+ fieldref.........the field reference
RETURN VALUE:
resolveSucceeded.....the reference has been resolved
*******************************************************************************/
-resolve_result_t resolve_field_lazy(jitdata *jd,
- instruction *iptr,
- methodinfo *refmethod)
+resolve_result_t resolve_field_lazy(methodinfo *refmethod,
+ constant_FMIref *fieldref)
{
classinfo *referer;
classinfo *container;
fieldinfo *fi;
- constant_FMIref *fieldref;
- resolve_result_t result;
- assert(iptr);
assert(refmethod);
/* the class containing the reference */
referer = refmethod->class;
assert(referer);
- /* get the field reference */
-
- INSTRUCTION_GET_FIELDREF(iptr, fieldref);
-
/* check if the field itself is already resolved */
- if (IS_FMIREF_RESOLVED(fieldref)) {
- fi = fieldref->p.field;
- container = fi->class;
- goto resolved_the_field;
- }
+ if (IS_FMIREF_RESOLVED(fieldref))
+ return resolveSucceeded;
/* first we must resolve the class containg the field */
fieldref->p.field = fi;
-resolved_the_field:
-
-#if defined(ENABLE_VERIFIER)
- if (JITDATA_HAS_FLAG_VERIFY(jd)) {
- result = resolve_field_verifier_checks(jd,
- refmethod, fieldref, container, fi,
- iptr->opc, iptr);
-
- if (result != resolveSucceeded)
- return result;
- }
-#endif /* defined(ENABLE_VERIFIER) */
-
/* everything ok */
return resolveSucceeded;
}
/* Checking opt_verify is ok here, because the NULL iptr guarantees */
/* that no missing parts of an instruction will be accessed. */
if (opt_verify) {
- checkresult = resolve_field_verifier_checks(NULL,
+ checkresult = resolve_field_verifier_checks(
ref->referermethod,
ref->fieldref,
container,
fi,
- (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;
}
#endif /* ENABLE_VERIFIER */
-/* create_unresolved_field *****************************************************
+/* resolve_create_unresolved_field *********************************************
Create an unresolved_field struct for the given field access instruction
*******************************************************************************/
-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;
return ref;
}
-/* constrain_unresolved_field **********************************************
+/* resolve_constrain_unresolved_field ******************************************
Record subtype constraints for a field access.
ref..............the unresolved_field structure of the access
referer..........the class containing the reference
refmethod........the method triggering the resolution (if any)
- iptr.............the {GET,PUT}{FIELD,STATIC}{,CONST} instruction
+ instanceti.......instance typeinfo, if available
+ valueti..........value typeinfo, if available
RETURN VALUE:
true.............everything ok
*******************************************************************************/
-#ifdef ENABLE_VERIFIER
-bool constrain_unresolved_field(jitdata *jd,
- unresolved_field *ref,
- classinfo *referer, methodinfo *refmethod,
- instruction *iptr)
+#if defined(ENABLE_VERIFIER)
+bool resolve_constrain_unresolved_field(unresolved_field *ref,
+ classinfo *referer,
+ methodinfo *refmethod,
+ typeinfo *instanceti,
+ typeinfo *valueti)
{
constant_FMIref *fieldref;
- varinfo *instanceslot = NULL;
int type;
typeinfo tinfo;
- typeinfo *tip = NULL;
typedesc *fd;
assert(ref);
/*printf(" opcode : %d %s\n",iptr[0].opc,icmd_names[iptr[0].opc]);*/
#endif
- switch (iptr[0].opc) {
- case ICMD_PUTFIELD:
- instanceslot = VAROP(iptr->s1);
- tip = &(VAROP(iptr->sx.s23.s2)->typeinfo);
- break;
-
- case ICMD_PUTFIELDCONST:
- instanceslot = VAROP(iptr->s1);
- break;
-
- case ICMD_PUTSTATIC:
- tip = &(VAROP(iptr->s1)->typeinfo);
- break;
-
- case ICMD_GETFIELD:
- instanceslot = VAROP(iptr->s1);
- 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_CLASSNAME(fieldref)))
+ 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 (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->name))
+ assert(valueti);
+ if (!unresolved_subtype_set_from_typeinfo(referer, refmethod,
+ &(ref->valueconstraints), valueti,
+ fieldref->parseddesc.fd->classref->name))
return false;
}
else {