--- /dev/null
+{
+ builtintable_entry *bte;
+ classref_or_classinfo cls;
+ varinfo *dv; /* output variable of current instruction */
+ jitdata *jd = state->jd;
+
+ bte = state->iptr->sx.s23.s3.bte;
+ dv = VAROP(state->iptr->dst);
+
+ /* XXX this is an ugly if-chain but twisti did not want a function */
+ /* pointer in builtintable_entry for this, so here you go.. ;) */
+
+ if (ISBUILTIN(BUILTIN_new)) {
+ if (state->iptr[-1].opc != ICMD_ACONST)
+ TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without class");
+ cls = state->iptr[-1].sx.val.c;
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_NEWOBJECT(dv->typeinfo,state->iptr);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BOOLEAN);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray_char)) {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_CHAR);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray_float)) {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_FLOAT);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray_double)) {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_DOUBLE);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray_byte)) {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BYTE);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray_short)) {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_SHORT);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray_int)) {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_INT);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray_long)) {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ dv->type = TYPE_ADR;
+ TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_LONG);
+ }
+ else if (ISBUILTIN(BUILTIN_newarray))
+ {
+ TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
+ if (state->iptr[-1].opc != ICMD_ACONST)
+ TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without class");
+ /* XXX check that it is an array class(ref) */
+ dv->type = TYPE_ADR;
+ typeinfo_init_class(&(dv->typeinfo),state->iptr[-1].sx.val.c);
+ }
+ else if (ISBUILTIN(BUILTIN_arrayinstanceof))
+ {
+ TYPECHECK_ADR(state->iptr->sx.s23.s2.args[0]);
+ if (state->iptr[-1].opc != ICMD_ACONST)
+ TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without class");
+ dv->type = TYPE_INT;
+ /* XXX check that it is an array class(ref) */
+ }
+ else {
+ methoddesc *md;
+ s4 i;
+ u1 rtype;
+ varinfo *av;
+
+ /* verify a generic builtin call */
+
+ TYPECHECK_COUNT(stat_ins_builtin_gen);
+
+ md = bte->md;
+ i = md->paramcount;
+
+ /* check the types of the arguments on the stack */
+
+ for (i--; i >= 0; i--) {
+ av = VAR(state->iptr->sx.s23.s2.args[i]);
+
+ if (av->type != md->paramtypes[i].type) {
+ TYPECHECK_VERIFYERROR_bool("parameter type mismatch for builtin method");
+ }
+
+#ifdef TYPECHECK_DEBUG
+ /* generic builtins may only take primitive types and java.lang.Object references */
+ if (av->type == TYPE_ADR && md->paramtypes[i].classref->name != utf_java_lang_Object) {
+ *exceptionptr = new_internalerror("generic builtin method with non-generic reference parameter");
+ return false;
+ }
+#endif
+ }
+
+ /* set the return type */
+
+ rtype = md->returntype.type;
+ if (rtype != TYPE_VOID) {
+ varinfo *dv;
+
+ dv = VAROP(state->iptr->dst);
+ dv->type = rtype;
+ if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
+ return false;
+ }
+
+ return true;
+ }
+}
+
+/*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:filetype=c:
+ */
--- /dev/null
+{
+ 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;
+ }
+
+ /* 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);
+ }
+
+ 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;
+
+ /* perform verification checks now */
+
+ fi = fieldref->p.field;
+
+ result = resolve_field_verifier_checks(
+ state->m, fieldref, fi->class, fi,
+ instanceti, valueti, isstatic, isput);
+ }
+
+ if (result == resolveFailed)
+ return false;
+
+ /* if not resolved, yet, create an unresolved field */
+
+ 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 */
+
+ 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;
+ }
+ }
+}
+
+/*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:filetype=c:
+ */
--- /dev/null
+{
+ unresolved_method *um; /* struct describing the called method */
+ constant_FMIref *mref; /* reference to the called method */
+ methodinfo *mi; /* resolved method (if any) */
+ methoddesc *md; /* descriptor of the called method */
+ utf *mname; /* method name */
+ utf *mclassname; /* name of the method's class */
+ bool specialmethod; /* true if a <...> method is called */
+ int opcode; /* invocation opcode */
+ bool callinginit; /* true if <init> is called */
+ instruction *ins;
+ classref_or_classinfo initclass;
+ typedesc *td;
+ s4 argindex; /* argument variable index */
+ varinfo *av; /* argument variable */
+ varinfo *dv; /* result variable of the invocation */
+ int i; /* counter */
+ u1 rtype; /* return type of called method */
+ resolve_result_t result;
+ jitdata *jd;
+ bool invokestatic;
+ bool invokespecial;
+
+ jd = state->jd;
+
+ /* get the FMIref and the unresolved_method struct (if any) */
+ /* from the instruction */
+
+ if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
+ /* unresolved method */
+ um = state->iptr->sx.s23.s3.um;
+ mref = um->methodref;
+ }
+ else {
+ /* resolved method */
+ um = NULL;
+ mref = state->iptr->sx.s23.s3.fmiref;
+ }
+
+ /* get method descriptor and name */
+
+ md = mref->parseddesc.md;
+ mname = mref->name;
+
+ /* get method info (if resolved) and classname */
+
+ if (IS_FMIREF_RESOLVED(mref)) {
+ mi = mref->p.method;
+ mclassname = mi->class->name;
+ }
+ else {
+ mi = NULL;
+ mclassname = mref->p.classref->name;
+ }
+
+ opcode = state->iptr[0].opc;
+ invokestatic = (opcode == ICMD_INVOKESTATIC);
+ invokespecial = (opcode == ICMD_INVOKESPECIAL);
+ specialmethod = (mname->text[0] == '<');
+ dv = VAROP(state->iptr->dst);
+
+ /* prevent compiler warnings */
+
+ ins = NULL;
+
+ /* check whether we are calling <init> */
+
+ callinginit = (invokespecial && mname == utf_init);
+ if (specialmethod && !callinginit)
+ TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
+
+ /* allocate parameters if necessary */
+
+ if (!md->params)
+ if (!descriptor_params_from_paramtypes(md,
+ (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
+ return false;
+
+ /* check parameter types */
+
+ i = md->paramcount; /* number of parameters including 'this'*/
+ while (--i >= 0) {
+ LOG1("param %d",i);
+ argindex = state->iptr->sx.s23.s2.args[i];
+ av = VAR(argindex);
+ td = md->paramtypes + i;
+
+ if (av->type != td->type)
+ TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
+
+ if (av->type == TYPE_ADR) {
+ LOGINFO(&(av->typeinfo));
+ if (i==0 && callinginit)
+ {
+ /* first argument to <init> method */
+ if (!TYPEINFO_IS_NEWOBJECT(av->typeinfo))
+ TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
+
+ /* get the address of the NEW instruction */
+ LOGINFO(&(av->typeinfo));
+ ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo);
+ if (ins)
+ initclass = ins[-1].sx.val.c;
+ else
+ initclass.cls = state->m->class;
+ LOGSTR("class: "); LOGNAME(initclass); LOGNL;
+ }
+ }
+ else {
+ /* non-adress argument. if this is the first argument and we are */
+ /* invoking an instance method, this is an error. */
+ if (i==0 && opcode != ICMD_INVOKESTATIC) {
+ TYPECHECK_VERIFYERROR_bool("Parameter type mismatch for 'this' argument");
+ }
+ }
+ LOG("ok");
+ }
+
+ if (callinginit) {
+ LOG("replacing uninitialized object");
+ /* replace uninitialized object type on stack */
+
+ /* for all live-in and live-through variables */
+ for (i=0; i<state->iptr->s1.argcount; ++i) {
+ argindex = state->iptr->sx.s23.s2.args[i];
+ av = VAR(argindex);
+ if (av->type == TYPE_ADR
+ && TYPEINFO_IS_NEWOBJECT(av->typeinfo)
+ && TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo) == ins)
+ {
+ LOG("replacing uninitialized type");
+
+ /* If this stackslot is in the instack of
+ * this basic block we must save the type(s)
+ * we are going to replace.
+ */
+ /* XXX this needs a new check */
+ if (state->bptr->invars
+ && argindex >= state->bptr->invars[0]
+ && argindex < state->bptr->varstart
+ && !state->savedinvars)
+ {
+ typestate_save_invars(state);
+ }
+
+ if (!typeinfo_init_class(&(av->typeinfo),initclass))
+ return false;
+ }
+ }
+
+ /* replace uninitialized object type in locals */
+ if (!typevector_init_object(state->jd->var, ins, initclass,
+ state->numlocals))
+ return false;
+
+ /* initializing the 'this' reference? */
+ if (!ins) {
+ classinfo *cls;
+ TYPECHECK_ASSERT(state->initmethod);
+ /* { we are initializing the 'this' reference } */
+ /* must be <init> of current class or direct superclass */
+ /* the current class is linked, so must be its superclass. thus we can be */
+ /* sure that resolving will be trivial. */
+ if (mi) {
+ cls = mi->class;
+ }
+ else {
+ if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
+ return false; /* exception */
+ }
+
+ /* if lazy resolving did not succeed, it's not one of the allowed classes */
+ /* otherwise we check it directly */
+ if (cls == NULL || (cls != state->m->class && cls != state->m->class->super.cls)) {
+ TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
+ }
+
+ /* set our marker variable to type int */
+ LOG("setting <init> marker");
+ typevector_store(jd->var, state->numlocals-1, TYPE_INT, NULL);
+ }
+ else {
+ /* { we are initializing an instance created with NEW } */
+ if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mclassname) {
+ TYPECHECK_VERIFYERROR_bool("wrong <init> called for uninitialized reference");
+ }
+ }
+ }
+
+ /* try to resolve the method lazily */
+
+ result = resolve_method_lazy(state->m, mref, invokespecial);
+
+ /* perform verification checks */
+
+ if (result == resolveSucceeded) {
+
+ assert(IS_FMIREF_RESOLVED(mref));
+
+ mi = mref->p.method;
+
+ result = resolve_method_verifier_checks(state->m,
+ mref,
+ mi,
+ invokestatic);
+ }
+
+ /* check types of parameters */
+
+ if (result == resolveSucceeded && !invokestatic)
+ result = resolve_method_instance_type_checks(
+ state->m, mi,
+ &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo),
+ invokespecial);
+
+ if (result == resolveSucceeded)
+ result = resolve_method_param_type_checks(
+ jd, state->m, state->iptr,
+ mi, invokestatic);
+
+ /* impose loading constraints */
+
+ if (result == resolveSucceeded) {
+ /* XXX state->m->class may have to be wrong when inlining */
+ if (!resolve_method_loading_constraints(state->m->class, mi))
+ return false;
+ }
+
+ if (result == resolveFailed)
+ return false;
+
+ if (result == resolveSucceeded) {
+ /* if this call is monomorphic, turn it into an INVOKESPECIAL */
+
+ if ((state->iptr->opc == ICMD_INVOKEVIRTUAL)
+ && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
+ {
+ state->iptr->opc = ICMD_INVOKESPECIAL;
+ }
+ }
+ else {
+ /* resolution must be deferred */
+
+ if (!um) {
+ um = resolve_create_unresolved_method(state->m->class, state->m,
+ mref,
+ state->iptr->opc == ICMD_INVOKESTATIC,
+ invokespecial);
+
+ if (!um)
+ return false;
+ }
+
+ /* record subtype constraints for parameters */
+
+ if (!invokestatic && !resolve_constrain_unresolved_method_instance(
+ um, state->m,
+ &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo),
+ invokespecial))
+ return false; /* XXX maybe wrap exception */
+
+ if (!resolve_constrain_unresolved_method_params(
+ jd, um, state->m, state->iptr))
+ return false; /* XXX maybe wrap exception */
+
+ /* store the unresolved_method pointer */
+
+ state->iptr->sx.s23.s3.um = um;
+ state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
+ }
+
+ /* set the return type */
+
+ rtype = md->returntype.type;
+ if (rtype != TYPE_VOID) {
+ dv->type = rtype;
+ if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
+ return false;
+ }
+}
+
+/*
+ * 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
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:filetype=c:
+ */
Changes: Christian Thalinger
- $Id: typecheck.c 5730 2006-10-10 00:29:26Z edwin $
+ $Id: typecheck.c 5740 2006-10-11 23:00:01Z edwin $
*/
static bool
verify_invocation(verifier_state *state)
{
- unresolved_method *um; /* struct describing the called method */
- constant_FMIref *mref; /* reference to the called method */
- methodinfo *mi; /* resolved method (if any) */
- methoddesc *md; /* descriptor of the called method */
- utf *mname; /* method name */
- utf *mclassname; /* name of the method's class */
- bool specialmethod; /* true if a <...> method is called */
- int opcode; /* invocation opcode */
- bool callinginit; /* true if <init> is called */
- instruction *ins;
- classref_or_classinfo initclass;
- typedesc *td;
- s4 argindex; /* argument variable index */
- varinfo *av; /* argument variable */
- varinfo *dv; /* result variable of the invocation */
- int i; /* counter */
- u1 rtype; /* return type of called method */
- resolve_result_t result;
- jitdata *jd;
- bool invokestatic;
- bool invokespecial;
-
- jd = state->jd;
-
- /* get the FMIref and the unresolved_method struct (if any) */
- /* from the instruction */
-
- if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
- /* unresolved method */
- um = state->iptr->sx.s23.s3.um;
- mref = um->methodref;
- }
- else {
- /* resolved method */
- um = NULL;
- mref = state->iptr->sx.s23.s3.fmiref;
- }
-
- /* get method descriptor and name */
-
- md = mref->parseddesc.md;
- mname = mref->name;
-
- /* get method info (if resolved) and classname */
-
- if (IS_FMIREF_RESOLVED(mref)) {
- mi = mref->p.method;
- mclassname = mi->class->name;
- }
- else {
- mi = NULL;
- mclassname = mref->p.classref->name;
- }
-
- opcode = state->iptr[0].opc;
- invokestatic = (opcode == ICMD_INVOKESTATIC);
- invokespecial = (opcode == ICMD_INVOKESPECIAL);
- specialmethod = (mname->text[0] == '<');
- dv = VAROP(state->iptr->dst);
-
- /* prevent compiler warnings */
-
- ins = NULL;
-
- /* check whether we are calling <init> */
-
- callinginit = (invokespecial && mname == utf_init);
- if (specialmethod && !callinginit)
- TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
-
- /* allocate parameters if necessary */
-
- if (!md->params)
- if (!descriptor_params_from_paramtypes(md,
- (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
- return false;
-
- /* check parameter types */
-
- i = md->paramcount; /* number of parameters including 'this'*/
- while (--i >= 0) {
- LOG1("param %d",i);
- argindex = state->iptr->sx.s23.s2.args[i];
- av = VAR(argindex);
- td = md->paramtypes + i;
-
- if (av->type != td->type)
- TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
-
- if (av->type == TYPE_ADR) {
- LOGINFO(&(av->typeinfo));
- if (i==0 && callinginit)
- {
- /* first argument to <init> method */
- if (!TYPEINFO_IS_NEWOBJECT(av->typeinfo))
- TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
-
- /* get the address of the NEW instruction */
- LOGINFO(&(av->typeinfo));
- ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo);
- if (ins)
- initclass = ins[-1].sx.val.c;
- else
- initclass.cls = state->m->class;
- LOGSTR("class: "); LOGNAME(initclass); LOGNL;
- }
- }
- else {
- /* non-adress argument. if this is the first argument and we are */
- /* invoking an instance method, this is an error. */
- if (i==0 && opcode != ICMD_INVOKESTATIC) {
- TYPECHECK_VERIFYERROR_bool("Parameter type mismatch for 'this' argument");
- }
- }
- LOG("ok");
- }
-
- if (callinginit) {
- LOG("replacing uninitialized object");
- /* replace uninitialized object type on stack */
-
- /* for all live-in and live-through variables */
- for (i=0; i<state->iptr->s1.argcount; ++i) {
- argindex = state->iptr->sx.s23.s2.args[i];
- av = VAR(argindex);
- if (av->type == TYPE_ADR
- && TYPEINFO_IS_NEWOBJECT(av->typeinfo)
- && TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo) == ins)
- {
- LOG("replacing uninitialized type");
-
- /* If this stackslot is in the instack of
- * this basic block we must save the type(s)
- * we are going to replace.
- */
- /* XXX this needs a new check */
- if (state->bptr->invars
- && argindex >= state->bptr->invars[0]
- && argindex < state->bptr->varstart
- && !state->savedinvars)
- {
- typestate_save_invars(state);
- }
-
- if (!typeinfo_init_class(&(av->typeinfo),initclass))
- return false;
- }
- }
-
- /* replace uninitialized object type in locals */
- if (!typevector_init_object(state->jd->var, ins, initclass,
- state->numlocals))
- return false;
-
- /* initializing the 'this' reference? */
- if (!ins) {
- classinfo *cls;
- TYPECHECK_ASSERT(state->initmethod);
- /* { we are initializing the 'this' reference } */
- /* must be <init> of current class or direct superclass */
- /* the current class is linked, so must be its superclass. thus we can be */
- /* sure that resolving will be trivial. */
- if (mi) {
- cls = mi->class;
- }
- else {
- if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
- return false; /* exception */
- }
-
- /* if lazy resolving did not succeed, it's not one of the allowed classes */
- /* otherwise we check it directly */
- if (cls == NULL || (cls != state->m->class && cls != state->m->class->super.cls)) {
- TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
- }
-
- /* set our marker variable to type int */
- LOG("setting <init> marker");
- typevector_store(jd->var, state->numlocals-1, TYPE_INT, NULL);
- }
- else {
- /* { we are initializing an instance created with NEW } */
- if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mclassname) {
- TYPECHECK_VERIFYERROR_bool("wrong <init> called for uninitialized reference");
- }
- }
- }
-
- /* try to resolve the method lazily */
-
- result = resolve_method_lazy(state->m, mref, invokespecial);
-
- /* perform verification checks */
-
- if (result == resolveSucceeded) {
-
- assert(IS_FMIREF_RESOLVED(mref));
-
- mi = mref->p.method;
-
- result = resolve_method_verifier_checks(state->m,
- mref,
- mi,
- invokestatic);
- }
-
- /* check types of parameters */
-
- if (result == resolveSucceeded && !invokestatic)
- result = resolve_method_instance_type_checks(
- state->m, mi,
- &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo),
- invokespecial);
-
- if (result == resolveSucceeded)
- result = resolve_method_param_type_checks(
- jd, state->m, state->iptr,
- mi, invokestatic);
-
- /* impose loading constraints */
-
- if (result == resolveSucceeded) {
- /* XXX state->m->class may have to be wrong when inlining */
- if (!resolve_method_loading_constraints(state->m->class, mi))
- return false;
- }
-
- if (result == resolveFailed)
- return false;
-
- if (result == resolveSucceeded) {
- /* if this call is monomorphic, turn it into an INVOKESPECIAL */
-
- if ((state->iptr->opc == ICMD_INVOKEVIRTUAL)
- && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
- {
- state->iptr->opc = ICMD_INVOKESPECIAL;
- }
- }
- else {
- /* resolution must be deferred */
-
- if (!um) {
- um = resolve_create_unresolved_method(state->m->class, state->m,
- mref,
- state->iptr->opc == ICMD_INVOKESTATIC,
- invokespecial);
-
- if (!um)
- return false;
- }
-
- /* record subtype constraints for parameters */
-
- if (!invokestatic && !resolve_constrain_unresolved_method_instance(
- um, state->m,
- &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo),
- invokespecial))
- return false; /* XXX maybe wrap exception */
-
- if (!resolve_constrain_unresolved_method_params(
- jd, um, state->m, state->iptr))
- return false; /* XXX maybe wrap exception */
-
- /* store the unresolved_method pointer */
-
- state->iptr->sx.s23.s3.um = um;
- state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
- }
-
- rtype = md->returntype.type;
- if (rtype != TYPE_VOID) {
- dv->type = rtype;
- if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
- return false;
- }
-
- return true;
-}
-
-
-/* verify_generic_builtin ******************************************************
-
- Verify the call of a generic builtin method.
-
- IN:
- state............the current state of the verifier
-
- RETURN VALUE:
- true.............successful verification,
- false............an exception has been thrown.
-
-*******************************************************************************/
-
-static bool
-verify_generic_builtin(verifier_state *state)
-{
- builtintable_entry *bte;
- s4 i;
- u1 rtype;
- methoddesc *md;
- varinfo *av;
- jitdata *jd = state->jd;
-
- TYPECHECK_COUNT(stat_ins_builtin_gen);
-
- bte = state->iptr->sx.s23.s3.bte;
- md = bte->md;
- i = md->paramcount;
-
- /* check the types of the arguments on the stack */
-
- for (i--; i >= 0; i--) {
- av = VAR(state->iptr->sx.s23.s2.args[i]);
-
- if (av->type != md->paramtypes[i].type) {
- TYPECHECK_VERIFYERROR_bool("parameter type mismatch for builtin method");
- }
-
-#ifdef TYPECHECK_DEBUG
- /* generic builtins may only take primitive types and java.lang.Object references */
- if (av->type == TYPE_ADR && md->paramtypes[i].classref->name != utf_java_lang_Object) {
- *exceptionptr = new_internalerror("generic builtin method with non-generic reference parameter");
- return false;
- }
-#endif
- }
-
- /* set the return type */
-
- rtype = md->returntype.type;
- if (rtype != TYPE_VOID) {
- varinfo *dv;
- dv = VAROP(state->iptr->dst);
- dv->type = rtype;
- if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
- return false;
- }
+#include <typecheck-invoke.inc>
return true;
}
static bool
verify_builtin(verifier_state *state)
{
- builtintable_entry *bte;
- classref_or_classinfo cls;
- varinfo *dv; /* output variable of current instruction */
- jitdata *jd = state->jd;
-
- bte = state->iptr->sx.s23.s3.bte;
- dv = VAROP(state->iptr->dst);
- /* XXX this is an ugly if-chain but twisti did not want a function */
- /* pointer in builtintable_entry for this, so here you go.. ;) */
+#include <typecheck-builtins.inc>
- if (ISBUILTIN(BUILTIN_new)) {
- if (state->iptr[-1].opc != ICMD_ACONST)
- TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without class");
- cls = state->iptr[-1].sx.val.c;
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_NEWOBJECT(dv->typeinfo,state->iptr);
- }
- else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BOOLEAN);
- }
- else if (ISBUILTIN(BUILTIN_newarray_char)) {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_CHAR);
- }
- else if (ISBUILTIN(BUILTIN_newarray_float)) {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_FLOAT);
- }
- else if (ISBUILTIN(BUILTIN_newarray_double)) {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_DOUBLE);
- }
- else if (ISBUILTIN(BUILTIN_newarray_byte)) {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BYTE);
- }
- else if (ISBUILTIN(BUILTIN_newarray_short)) {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_SHORT);
- }
- else if (ISBUILTIN(BUILTIN_newarray_int)) {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_INT);
- }
- else if (ISBUILTIN(BUILTIN_newarray_long)) {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- dv->type = TYPE_ADR;
- TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_LONG);
- }
- else if (ISBUILTIN(BUILTIN_newarray))
- {
- TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
- if (state->iptr[-1].opc != ICMD_ACONST)
- TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without class");
- /* XXX check that it is an array class(ref) */
- dv->type = TYPE_ADR;
- typeinfo_init_class(&(dv->typeinfo),state->iptr[-1].sx.val.c);
- }
- else if (ISBUILTIN(BUILTIN_arrayinstanceof))
- {
- TYPECHECK_ADR(state->iptr->sx.s23.s2.args[0]);
- if (state->iptr[-1].opc != ICMD_ACONST)
- TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without class");
- dv->type = TYPE_INT;
- /* XXX check that it is an array class(ref) */
- }
- else {
- return verify_generic_builtin(state);
- }
return true;
}
case ICMD_PUTSTATICCONST:
case ICMD_GETFIELD:
case ICMD_GETSTATIC:
- {
- 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;
- }
-
- /* 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);
- }
- 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;
-
- /* perform verification checks now */
-
- fi = fieldref->p.field;
-
- result = resolve_field_verifier_checks(
- state->m, fieldref, fi->class, fi,
- instanceti, valueti, isstatic, isput);
- }
-
- if (result == resolveFailed)
- return false;
+#include <typecheck-fields.inc>
- /* if not resolved, yet, create an unresolved field */
-
- 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 */
-
- 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;
/****************************************/