+/* src/vm/jit/verify/typecheck-invoke.inc - type checking for invocations
+
+ Copyright (C) 1996-2005, 2006 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
+
+ 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.
+
+ Contact: cacao@cacaojvm.org
+
+ Authors: Edwin Steiner
+
+ $Id$
+
+*/
+
+
{
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 *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)) {
/* 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)
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) {
/* 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 ((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 {
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;
}
}