* Updated header: Added 2006. Changed address of FSF. Changed email
[cacao.git] / src / vm / jit / verify / typecheck.c
index 9504918bfe184985521aa74bbfc96c67f30f4935..5d21065fb217f3bfebe1e580b310c638c8ad20d1 100644 (file)
@@ -1,9 +1,9 @@
 /* src/vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
 
-   Copyright (C) 1996-2005 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
+   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.
 
 
    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., 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
 
-   Contact: cacao@complang.tuwien.ac.at
+   Contact: cacao@cacaojvm.org
 
    Authors: Edwin Steiner
 
    Changes: Christian Thalinger
 
-   $Id: typecheck.c 3644 2005-11-09 19:32:03Z edwin $
+   $Id: typecheck.c 4357 2006-01-22 23:33:38Z twisti $
 
 */
 
@@ -165,11 +165,11 @@ of the typeinfo of the stack slot.
 #include <assert.h>
 #include <string.h>
 
+#include "config.h"
 #include "vm/types.h"
+#include "vm/global.h"
 
-#include "vm/global.h" /* must be here because of CACAO_TYPECHECK */
-
-#ifdef CACAO_TYPECHECK
+#ifdef ENABLE_VERIFIER
 
 #include "mm/memory.h"
 #include "toolbox/logging.h"
@@ -178,7 +178,6 @@ of the typeinfo of the stack slot.
 #include "vm/jit/patcher.h"
 #include "vm/loader.h"
 #include "vm/options.h"
-#include "vm/tables.h"
 #include "vm/jit/jit.h"
 #include "vm/jit/stack.h"
 #include "vm/access.h"
@@ -364,7 +363,7 @@ void typecheck_print_statistics(FILE *file) {
        fprintf(file,"      (uninit.)    : %8d\n",stat_ins_field_uninitialized);
        fprintf(file,"    invocations    : %8d\n",stat_ins_invoke);
        fprintf(file,"      (unresolved) : %8d\n",stat_ins_invoke_unresolved);
-       fprintf(file,"    load primitive : %8d\n",stat_ins_primload);
+       fprintf(file,"    load primitive : (currently not counted) %8d\n",stat_ins_primload);
        fprintf(file,"    load address   : %8d\n",stat_ins_aload);
        fprintf(file,"    builtins       : %8d\n",stat_ins_builtin);
        fprintf(file,"        generic    : %8d\n",stat_ins_builtin_gen);
@@ -515,6 +514,7 @@ typestack_copy(verifier_state *state,stackptr dst,stackptr y,typevector *selecte
        int k;
        
        for (;dst; dst=dst->prev, y=y->prev) {
+               /* XXX only check the following two in debug mode? */
                if (!y) {
                        *exceptionptr = new_verifyerror(state->m,"Stack depth mismatch");
                        return false;
@@ -703,8 +703,30 @@ typestack_add(stackptr dst,stackptr y,int ky)
        }
 }
 
-/* XXX document */
-/* 'a' and 'b' are assumed to have passed typestack_canmerge! */
+/* typestack_separable_with ****************************************************
+   This function answers the question: If variant 'kb' of typestack 'b' is
+   added to typestack 'a', will the result be separable?
+
+   A typestack is called 'separable' if it has at least one slot of type
+   returnAddress that contains at least two different return addresses.
+   (ie. a RET using the value in this slot could go to more than one target)
+   
+   IN:
+          a................the first typestack
+          b................the second typestack
+          kb...............the k-index of the variant that should be selected
+                           from typestack 'b'
+
+   OUT:
+       true.............the result would be separable
+          false............the result would not be separable
+
+   PRE-CONDITION:
+       'a' and 'b' are assumed to have passed typestack_canmerge!
+
+*******************************************************************************/
+
 static bool
 typestack_separable_with(stackptr a,stackptr b,int kb)
 {
@@ -727,8 +749,33 @@ typestack_separable_with(stackptr a,stackptr b,int kb)
        return false;
 }
 
-/* XXX document */
-/* 'a' and 'b' are assumed to have passed typestack_canmerge! */
+/* typestack_separable_from ****************************************************
+   This function answers the question: Is variant 'ka' of typestack 'a'
+   separable from variant 'kb' of typestack 'b'?
+
+   Two variants of typestacks are called 'separable' from each other, if there
+   is at least one slot for which the variants contain different return addresses.
+   (ie. a RET using the value in this slot would go to one target in the first
+   variant and to another target in the second variant)
+   
+   IN:
+          a................the first typestack
+          ka...............the k-index of the variant that should be selected
+                           from typestack 'a'
+          b................the second typestack
+          kb...............the k-index of the variant that should be selected
+                           from typestack 'b'
+
+   OUT:
+       true.............the variants are separable
+          false............the variants are not separable
+
+   PRE-CONDITION:
+       'a' and 'b' are assumed to have passed typestack_canmerge!
+
+*******************************************************************************/
+
 static bool
 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
 {
@@ -1452,7 +1499,7 @@ verify_multianewarray(verifier_state *state)
        }
 
        /* check array descriptor */
-       if (state->iptr[0].target == NULL) {
+       if (state->iptr[0].val.a != NULL) {
                /* the array class reference has already been resolved */
                arrayclass = (classinfo *) state->iptr[0].val.a;
                if (!arrayclass)
@@ -1471,7 +1518,7 @@ verify_multianewarray(verifier_state *state)
                
                /* the array class reference is still unresolved */
                /* check that the reference indicates an array class of correct dimension */
-               cr = (constant_classref *) state->iptr[0].val.a;
+               cr = (constant_classref *) state->iptr[0].target;
                i = 0;
                p = cr->name->text;
                while (p[i] == '[')
@@ -1483,7 +1530,7 @@ verify_multianewarray(verifier_state *state)
                        TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
 
                /* set the array type of the result */
-               if (!typeinfo_init_class(&(state->iptr->dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].val.a)))
+               if (!typeinfo_init_class(&(state->iptr->dst->typeinfo),CLASSREF_OR_CLASSINFO(state->iptr[0].target)))
                        return false;
        }
 
@@ -1566,7 +1613,7 @@ verify_basic_block(verifier_state *state)
                                        /* of eclipse 3.0.2                                                  */
                                        if (TYPEINFO_NEWOBJECT_INSTRUCTION(state->localset->td[i].info) != NULL) {
                                                /*show_icmd_method(state->m, state->cd, state->rd);*/
-                                               printf("Uninitialized variale: %d, block: %d\n", i, state->bptr->debug_nr);
+                                               printf("Uninitialized variable: %d, block: %d\n", i, state->bptr->debug_nr);
                                                TYPECHECK_VERIFYERROR_bool("Uninitialized object in local variable inside try block");
                                        }
                                }
@@ -1773,11 +1820,6 @@ fieldaccess_tail:
                                if (!resolve_field(uf,resolveLazy,fieldinfop))
                                        return false;
 
-                               /* we need a patcher, so this is not a leafmethod */
-#if defined(__MIPS__)
-                               if (!*fieldinfop || !(*fieldinfop)->class->initialized)
-                                       state->cd->method->isleafmethod = false;
-#endif
                                TYPECHECK_COUNTIF(!*fieldinfop,stat_ins_field_unresolved);
                                TYPECHECK_COUNTIF(*fieldinfop && !(*fieldinfop)->class->initialized,stat_ins_field_uninitialized);
                                        
@@ -2217,7 +2259,9 @@ return_tail:
                                 * Instructions below...
                                 *     *) don't operate on local variables,
                                 *     *) don't operate on references,
-                                *     *) don't operate on returnAddresses.
+                                *     *) don't operate on returnAddresses,
+                                *     *) don't affect control flow (except
+                                *        by throwing exceptions).
                                 *
                                 * (These instructions are typechecked in
                                 *  analyse_stack.)
@@ -2272,10 +2316,6 @@ return_tail:
                        case ICMD_LSHL:
                        case ICMD_LSHR:
                        case ICMD_LUSHR:
-#if 0
-                       case ICMD_IREM0X10001:
-                       case ICMD_LREM0X10001:
-#endif
                        case ICMD_IMULPOW2:
                        case ICMD_LMULPOW2:
                        case ICMD_IDIVPOW2:
@@ -2713,7 +2753,7 @@ methodinfo *typecheck(methodinfo *meth, codegendata *cdata, registerdata *rdata)
        return state.m;
 }
 
-#endif /* CACAO_TYPECHECK */
+#endif /* ENABLE_VERIFIER */
 
 /*
  * These are local overrides for various environment variables in Emacs.