PR163: descriptor_params_from_paramtypes is protected by a mutex now (per descriptor...
[cacao.git] / src / vm / jit / verify / typecheck-invoke.inc
index 7a256dae6fc208370d801e4a114dcf29c9b45539..781defe657b27190610ca85cf0a7b801ac1168d0 100644 (file)
@@ -1,9 +1,36 @@
+/* src/vm/jit/verify/typecheck-invoke.inc - type checking for invocations
+
+   Copyright (C) 1996-2011
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
 {
        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 */
+    u1 rtype;                          /* return type of called method */
+#if !defined(TYPECHECK_TYPEINFERER)
+       methodinfo *mi;                        /* resolved method (if any) */
        utf *mclassname;                     /* name of the method's class */
        bool specialmethod;            /* true if a <...> method is called */
        int opcode;                                   /* invocation opcode */
        instruction *ins;
        classref_or_classinfo initclass;
        typedesc *td;
+#if defined(TYPECHECK_VARIABLESBASED)
        s4 argindex;                            /* argument variable index */
        varinfo *av;                                  /* argument variable */
+#else
+       typedescriptor_t *av;                       /* argument stack slot */
+#endif
        int i;                                                  /* counter */
-    u1 rtype;                          /* return type of called method */
        resolve_result_t result;
        bool invokestatic;
        bool invokespecial;
+#endif /* !defined(TYPECHECK_TYPEINFERER) */
 
        /* get the FMIref and the unresolved_method struct (if any) */
        /* from the instruction                                     */
        md = mref->parseddesc.md;
        mname = mref->name;
 
+#if !defined(TYPECHECK_TYPEINFERER)
        /* get method info (if resolved) and classname */
 
        if (IS_FMIREF_RESOLVED(mref)) {
                mi = mref->p.method;
-               mclassname = mi->class->name;
+               mclassname = mi->clazz->name;
        }
        else {
                mi = NULL;
 
        /* allocate parameters if necessary */
        
-       if (!md->params)
-               if (!descriptor_params_from_paramtypes(md,
-                                       (invokestatic) ? ACC_STATIC : ACC_NONE))
-                       return false;
+       descriptor_params_from_paramtypes(
+               md,
+               (invokestatic) ? ACC_STATIC : ACC_NONE);
 
        /* check parameter types */
 
+#if defined(TYPECHECK_STACKBASED)
+       av = stack - (md->paramslots - 1);
+       for (i=0; i<md->paramcount; ++i) {
+#else
        i = md->paramcount; /* number of parameters including 'this'*/
        while (--i >= 0) {
-               LOG1("\t\tparam %d",i);
                argindex = state->iptr->sx.s23.s2.args[i];
                av = VAR(argindex);
+#endif
+               LOG1("\t\tparam %d",i);
                td = md->paramtypes + i;
 
                if (av->type != td->type)
                                if (ins)
                                        initclass = ins[-1].sx.val.c;
                                else
-                                       initclass.cls = state->m->class;
+                                       initclass.cls = state->m->clazz;
                                LOGSTR("\t\tclass: "); LOGNAME(initclass); LOGNL;
                        }
                }
                                TYPECHECK_VERIFYERROR_bool("Parameter type mismatch for 'this' argument");
                        }
                }
-               LOG("\tok");
+               LOG("\t\tok");
+
+#if defined(TYPECHECK_STACKBASED)
+               av += (IS_2_WORD_TYPE(av->type)) ? 2 : 1;
+#endif
        }
 
        if (callinginit) {
                /* replace uninitialized object type on stack */
 
                /* for all live-in and live-through variables */ 
+#if defined(TYPECHECK_VARIABLESBASED)
                for (i=0; i<state->iptr->s1.argcount; ++i) {
                        argindex = state->iptr->sx.s23.s2.args[i];
                        av = VAR(argindex);
+#else
+               for (av=stackfloor; av <= stack; ++av) {
+#endif
                        if (av->type == TYPE_ADR
                                        && TYPEINFO_IS_NEWOBJECT(av->typeinfo)
                                        && TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo) == ins)
                        {
                                LOG("\treplacing uninitialized type");
 
+#if defined(TYPECHECK_VARIABLESBASED)
                                /* 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->invars[0]
                                                && argindex < state->bptr->varstart 
                                                && !state->savedinvars)
                                {
                                        typestate_save_invars(state);
                                }
+#endif /* defined(TYPECHECK_VARIABLESBASED) */
 
                                if (!typeinfo_init_class(&(av->typeinfo),initclass))
                                        return false;
                }
 
                /* replace uninitialized object type in locals */
+#if defined(TYPECHECK_VARIABLESBASED)
                if (!typevector_init_object(state->jd->var, ins, initclass,
                                        state->numlocals))
                        return false;
+#else
+               /* XXX should reuse typevector code */
+               for (i=0; i<state->numlocals; ++i) {
+                       if (state->locals[i].type == TYPE_ADR
+                               && TYPEINFO_IS_NEWOBJECT(state->locals[i].typeinfo)
+                               && TYPEINFO_NEWOBJECT_INSTRUCTION(state->locals[i].typeinfo) == ins)
+                       {
+                               if (!typeinfo_init_class(&(state->locals[i].typeinfo), initclass))
+                                       return false;
+                       }
+               }
+#endif
 
                /* initializing the 'this' reference? */
                if (!ins) {
                        /* 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;
+                               cls = mi->clazz;
                        }
                        else {
                                if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
 
                        /* 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)) {
+                       if (cls == NULL || (cls != state->m->clazz && cls != state->m->clazz->super)) {
                                TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
                        }
 
                        /* set our marker variable to type int */
                        LOG("\tsetting <init> marker");
+#if defined(TYPECHECK_VARIABLESBASED)
                        typevector_store(jd->var, state->numlocals-1, TYPE_INT, NULL);
+#else
+                       state->locals[state->numlocals-1].type = TYPE_INT;
+#endif
                }
                else {
                        /* { we are initializing an instance created with NEW } */
 
        if (result == resolveSucceeded && !invokestatic)
                result = resolve_method_instance_type_checks(
-                               state->m, mi, 
-                               &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo), 
+                               state->m, mi,
+                               &(OP1->typeinfo),
                                invokespecial);
 
+#if defined(TYPECHECK_VARIABLESBASED)
        if (result == resolveSucceeded)
                result = resolve_method_param_type_checks(
                                jd, state->m, state->iptr,
                                mi, invokestatic);
+#else
+       if (result == resolveSucceeded)
+               result = resolve_method_param_type_checks_stackbased(
+                               state->m, mi, invokestatic, stack);
+#endif
 
        /* 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))
+               /* XXX state->m->clazz may have to be wrong when inlining */
+               if (!resolve_method_loading_constraints(state->m->clazz, mi))
                        return false;
        }
 
                if ((state->iptr->opc == ICMD_INVOKEVIRTUAL)
                        && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
                {
-                       state->iptr->opc = ICMD_INVOKESPECIAL;
+                       state->iptr->opc         = ICMD_INVOKESPECIAL;
+                       state->iptr->flags.bits |= INS_FLAG_CHECK;
                }
        }
        else {
                /* resolution must be deferred */
 
                if (!um) {
-                       um = resolve_create_unresolved_method(state->m->class, state->m,
+                       um = resolve_create_unresolved_method(state->m->clazz, state->m,
                                        mref, 
                                        invokestatic,
                                        invokespecial);
 
                if (!invokestatic && !resolve_constrain_unresolved_method_instance(
                                        um, state->m, 
-                                       &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo),
+                                       &(OP1->typeinfo),
                                        invokespecial))
                        return false; /* XXX maybe wrap exception */
 
+#if defined(TYPECHECK_VARIABLESBASED)
                if (!resolve_constrain_unresolved_method_params(
                                        jd, um, state->m, state->iptr))
                        return false; /* XXX maybe wrap exception */
+#else
+               if (!resolve_constrain_unresolved_method_params_stackbased(
+                                       um, state->m, stack))
+                       return false; /* XXX maybe wrap exception */
+#endif
 
                /* store the unresolved_method pointer */
 
                state->iptr->sx.s23.s3.um = um;
                state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
        }
+#endif /* !defined(TYPECHECK_TYPEINFERER) */
 
        /* 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)))
+               if (!typeinfo_init_from_typedesc(&(md->returntype), NULL, &(dv->typeinfo)))
                        return false;
        }
 }