LCOV - code coverage report
Current view: top level - vm/jit/verify - typecheck.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 122 128 95.3 %
Date: 2015-06-10 18:10:59 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /* src/vm/jit/verify/typecheck.cpp - typechecking (part of bytecode verification)
       2             : 
       3             :    Copyright (C) 1996-2013
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             : 
       6             :    This file is part of CACAO.
       7             : 
       8             :    This program is free software; you can redistribute it and/or
       9             :    modify it under the terms of the GNU General Public License as
      10             :    published by the Free Software Foundation; either version 2, or (at
      11             :    your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful, but
      14             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :    General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program; if not, write to the Free Software
      20             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      21             :    02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : /**
      26             :  * @defgroup verify Bytecode Verification
      27             :  * Bytecode Verification
      28             :  */
      29             : 
      30             : /**
      31             : @file
      32             : @ingroup verify
      33             : 
      34             : Typechecker
      35             : 
      36             : What's the purpose of the `typechecker`?
      37             : ----------------------------------------
      38             : 
      39             : The typechecker analyses (the intermediate repr. of) the bytecode of
      40             : each method and ensures that for each instruction the values on the
      41             : stack and in local variables are of the correct type whenever the
      42             : instruction is executed.
      43             : 
      44             : type checking is a mandatory part of bytecode verification.
      45             : 
      46             : 
      47             : How does the typechecker work?
      48             : ------------------------------
      49             : 
      50             : The JVM stack and the local variables are not statically typed, so the
      51             : typechecker has to *infer* the static types of stack slots and local
      52             : variables at each point of the method. The JVM spec imposes a lot of
      53             : restrictions on the bytecode in order to guarantee that this is always
      54             : possible.
      55             : 
      56             : Basically the typechecker solves the data flow equations of the method.
      57             : This is done in the usual way for a forward data flow analysis: Starting
      58             : from the entry point of the method the typechecker follows the CFG and
      59             : records the type of each stack slot and local variable at each point @fn{1}.
      60             : When two or more control flow paths merge at a point, the union of the
      61             : types for each slot/variable is taken. The algorithm continues to follow
      62             : all possible paths @fn{2} until the recorded types do not change anymore (ie.
      63             : the equations have been solved).
      64             : 
      65             : If the solution has been reached and the resulting types are valid for
      66             : all instructions, then type checking terminates with success, otherwise
      67             : an exception is thrown.
      68             : 
      69             : 
      70             : Why is this code so damn complicated?
      71             : -------------------------------------
      72             : 
      73             : Short answer: The devil's in the details.
      74             : 
      75             : While the basic operation of the typechecker is no big deal, there are
      76             : many properties of Java bytecode which make type checking hard. Some of
      77             : them are not even addressed in the JVM spec. Some problems and their
      78             : solutions:
      79             : 
      80             : - Finding a good representation of the union of two reference types is
      81             : difficult because of multiple inheritance of interfaces. 
      82             : 
      83             :         Solution: The typeinfo system can represent such "merged" types by a
      84             :         list of proper subclasses of a class. Example:
      85             : 
      86             :                 typeclass=java.lang.Object merged={ InterfaceA, InterfaceB }
      87             :         
      88             :         represents the result of merging two interface types "InterfaceA"
      89             :         and "InterfaceB".
      90             : 
      91             : - When the code of a method is verified, there may still be unresolved
      92             : references to classes/methods/fields in the code, which we may not force
      93             : to be resolved eagerly. (A similar problem arises because of the special
      94             : checks for protected members.)@fn{3}
      95             : 
      96             :         Solution: The typeinfo system knows how to deal with unresolved
      97             :         class references. Whenever a check has to be performed for an
      98             :         unresolved type, the type is annotated with constraints representing
      99             :         the check. Later, when the type is resolved, the constraints are
     100             :         checked. (See the constrain_unresolved_... and the resolve_...
     101             :         methods.)
     102             : 
     103             : - Checks for uninitialized object instances are hard because after the
     104             : invocation of <init> on an uninitialized object *all* slots/variables
     105             : referring to this object (and exactly those slots/variables) must be
     106             : marked as initialized.
     107             : 
     108             :         Solution: The JVM spec describes a solution, which has been
     109             :         implemented in this typechecker.
     110             : 
     111             : Note that some checks mentioned in the JVM spec are unnecessary @fn{4} and
     112             : not performed by either the reference implementation, or this implementation.
     113             : 
     114             : 
     115             : --- Footnotes
     116             : 
     117             : @footnote{1} Actually only the types of slots/variables at the start of each
     118             : basic block are remembered. Within a basic block the algorithm only keeps
     119             : the types of the slots/variables for the "current" instruction which is
     120             : being analysed. 
     121             : 
     122             : @footnote{2} Actually the algorithm iterates through the basic block list until
     123             : there are no more changes. Theoretically it would be wise to sort the
     124             : basic blocks topologically beforehand, but the number of average/max
     125             : iterations observed is so low, that this was not deemed necessary.
     126             : 
     127             : @footnote{3} This is similar to a method proposed by: Alessandro Coglio et al.,
     128             : "A Formal Specification of Java Class Loading" @cite Coglio2000.
     129             : An important difference is that Coglio's subtype constraints are checked
     130             : after loading, while our constraints are checked when the field/method
     131             : is accessed for the first time, so we can guarantee lexically correct
     132             : error reporting.
     133             : 
     134             : @footnote{4} Alessandro Coglio "Improving the official specification of Java
     135             : bytecode verification" @cite Coglio2003.
     136             : */
     137             : 
     138             : 
     139             : #include "config.h"
     140             : 
     141             : #include <assert.h>
     142             : #include <string.h>
     143             : 
     144             : #include "vm/types.hpp"
     145             : 
     146             : #ifdef ENABLE_VERIFIER
     147             : 
     148             : #include "mm/memory.hpp"
     149             : #include "mm/dumpmemory.hpp"
     150             : 
     151             : #include "native/native.hpp"
     152             : 
     153             : #include "toolbox/logging.hpp"
     154             : 
     155             : #include "vm/access.hpp"
     156             : #include "vm/array.hpp"
     157             : #include "vm/descriptor.hpp"
     158             : #include "vm/exceptions.hpp"
     159             : #include "vm/field.hpp"
     160             : #include "vm/global.hpp"
     161             : #include "vm/globals.hpp"
     162             : #include "vm/options.hpp"
     163             : #include "vm/primitive.hpp"
     164             : #include "vm/resolve.hpp"
     165             : 
     166             : #include "vm/jit/builtin.hpp"
     167             : #include "vm/jit/jit.hpp"
     168             : #include "vm/jit/parse.hpp"
     169             : #include "vm/jit/show.hpp"
     170             : 
     171             : #include "vm/jit/ir/instruction.hpp"
     172             : 
     173             : #include "vm/jit/verify/typecheck-common.hpp"
     174             : 
     175             : 
     176             : /****************************************************************************/
     177             : /* MACROS FOR VARIABLE TYPE CHECKING                                        */
     178             : /****************************************************************************/
     179             : 
     180             : #define TYPECHECK_CHECK_TYPE(i,tp,msg)                               \
     181             :     do {                                                             \
     182             :         if (VAR(i)->type != (tp)) {                                  \
     183             :             exceptions_throw_verifyerror(state->m, (msg));           \
     184             :             return false;                                            \
     185             :         }                                                            \
     186             :     } while (0)
     187             : 
     188             : #define TYPECHECK_INT(i)                                             \
     189             :     TYPECHECK_CHECK_TYPE(i,TYPE_INT,"Expected to find integer value")
     190             : #define TYPECHECK_LNG(i)                                             \
     191             :     TYPECHECK_CHECK_TYPE(i,TYPE_LNG,"Expected to find long value")
     192             : #define TYPECHECK_FLT(i)                                             \
     193             :     TYPECHECK_CHECK_TYPE(i,TYPE_FLT,"Expected to find float value")
     194             : #define TYPECHECK_DBL(i)                                             \
     195             :     TYPECHECK_CHECK_TYPE(i,TYPE_DBL,"Expected to find double value")
     196             : #define TYPECHECK_ADR(i)                                             \
     197             :     TYPECHECK_CHECK_TYPE(i,TYPE_ADR,"Expected to find object value")
     198             : 
     199             : #define TYPECHECK_INT_OP(o)  TYPECHECK_INT((o).varindex)
     200             : #define TYPECHECK_LNG_OP(o)  TYPECHECK_LNG((o).varindex)
     201             : #define TYPECHECK_FLT_OP(o)  TYPECHECK_FLT((o).varindex)
     202             : #define TYPECHECK_DBL_OP(o)  TYPECHECK_DBL((o).varindex)
     203             : #define TYPECHECK_ADR_OP(o)  TYPECHECK_ADR((o).varindex)
     204             : 
     205             : 
     206             : /* typestate_save_invars *******************************************************
     207             :  
     208             :    Save the invars of the current basic block in the space reserved by
     209             :    parse.
     210             : 
     211             :    This function must be called before an instruction modifies a variable
     212             :    that is an invar of the current block. In such cases the invars of the
     213             :    block must be saved, and restored at the end of the analysis of this
     214             :    basic block, so that the invars again reflect the *input* to this basic
     215             :    block (and do not randomly contain types that appear within the block).
     216             : 
     217             :    IN:
     218             :        state............current state of the verifier
     219             : 
     220             : *******************************************************************************/
     221             : 
     222             : static void
     223         721 : typestate_save_invars(verifier_state *state)
     224             : {
     225             :         s4 i, index;
     226             :         s4 *pindex;
     227             :         
     228             :         OLD_LOG("saving invars");
     229             : 
     230         721 :         if (!state->savedindices) {
     231             :                 OLD_LOG("allocating savedindices buffer");
     232         574 :                 pindex = (s4*) DumpMemory::allocate(sizeof(s4) * state->m->maxstack);
     233         574 :                 state->savedindices = pindex;
     234         574 :                 index = state->numlocals + VERIFIER_EXTRA_VARS;
     235        3612 :                 for (i=0; i<state->m->maxstack; ++i)
     236        3038 :                         *pindex++ = index++;
     237             :         }
     238             : 
     239             :         /* save types */
     240             : 
     241             :         typecheck_copy_types(state, state->bptr->invars, state->savedindices, 
     242         721 :                         state->bptr->indepth);
     243             : 
     244             :         /* set the invars of the block to the saved variables */
     245             :         /* and remember the original invars                   */
     246             : 
     247         721 :         state->savedinvars = state->bptr->invars;
     248         721 :         state->bptr->invars = state->savedindices;
     249         721 : }
     250             : 
     251             : 
     252             : /* typestate_restore_invars  ***************************************************
     253             :  
     254             :    Restore the invars of the current basic block that have been previously
     255             :    saved by `typestate_save_invars`.
     256             : 
     257             :    IN:
     258             :        state............current state of the verifier
     259             : 
     260             : *******************************************************************************/
     261             : 
     262             : static void
     263         721 : typestate_restore_invars(verifier_state *state)
     264             : {
     265             :         TYPECHECK_COUNT(stat_savedstack);
     266             :         OLD_LOG("restoring saved invars");
     267             : 
     268             :         /* restore the invars pointer */
     269             : 
     270         721 :         state->bptr->invars = state->savedinvars;
     271             : 
     272             :         /* copy the types back */
     273             : 
     274             :         typecheck_copy_types(state, state->savedindices, state->bptr->invars,
     275         721 :                         state->bptr->indepth);
     276             : 
     277             :         /* mark that there are no saved invars currently */
     278             : 
     279         721 :         state->savedinvars = NULL;
     280         721 : }
     281             : 
     282             : 
     283             : /* handle_fieldaccess **********************************************************
     284             :  
     285             :    Verify an ICMD_{GET,PUT}{STATIC,FIELD}(CONST)?
     286             :   
     287             :    IN:
     288             :        state............the current state of the verifier
     289             : 
     290             :    RETURN VALUE:
     291             :        true.............successful verification,
     292             :            false............an exception has been thrown.
     293             : 
     294             : *******************************************************************************/
     295             : 
     296             : static bool
     297      225545 : handle_fieldaccess(verifier_state *state,
     298             :                                    varinfo *instance,
     299             :                                    varinfo *value)
     300             : {
     301             :         jitdata *jd;
     302             : 
     303      225545 :         jd = state->jd;
     304             : 
     305             : #define TYPECHECK_VARIABLESBASED
     306             : #define EXCEPTION  do { return false; } while (0)
     307             : #define VERIFY_ERROR(msg)  TYPECHECK_VERIFYERROR_bool(msg)
     308             : #include <typecheck-fields.inc>
     309             : #undef  EXCEPTION
     310             : #undef  VERIFY_ERROR
     311             : #undef  TYPECHECK_VARIABLESBASED
     312             : 
     313      225545 :         return true;
     314             : }
     315             : 
     316             : 
     317             : /* handle_invocation ***********************************************************
     318             :  
     319             :    Verify an ICMD_INVOKE* instruction.
     320             :   
     321             :    IN:
     322             :        state............the current state of the verifier
     323             : 
     324             :    RETURN VALUE:
     325             :        true.............successful verification,
     326             :            false............an exception has been thrown.
     327             : 
     328             : *******************************************************************************/
     329             : 
     330             : static bool
     331      289993 : handle_invocation(verifier_state *state)
     332             : {
     333             :         jitdata *jd;
     334             :     varinfo *dv;               /* output variable of current instruction */
     335             : 
     336      289993 :         jd = state->jd;
     337      289993 :         dv = VAROP(state->iptr->dst);
     338             : 
     339             : #define TYPECHECK_VARIABLESBASED
     340             : #define OP1   VAR(state->iptr->sx.s23.s2.args[0])
     341             : #include <typecheck-invoke.inc>
     342             : #undef  OP1
     343             : #undef  TYPECHECK_VARIABLESBASED
     344             : 
     345      289988 :         return true;
     346             : }
     347             : 
     348             : 
     349             : /* handle_builtin **************************************************************
     350             :  
     351             :    Verify the call of a builtin method.
     352             :   
     353             :    IN:
     354             :        state............the current state of the verifier
     355             : 
     356             :    RETURN VALUE:
     357             :        true.............successful verification,
     358             :            false............an exception has been thrown.
     359             : 
     360             : *******************************************************************************/
     361             : 
     362             : static bool
     363       79492 : handle_builtin(verifier_state *state)
     364             : {
     365             :         jitdata *jd;
     366             :     varinfo *dv;               /* output variable of current instruction */
     367             : 
     368       79492 :         jd = state->jd;
     369       79492 :         dv = VAROP(state->iptr->dst);
     370             : 
     371             : #define TYPECHECK_VARIABLESBASED
     372             : #define OP1   state->iptr->sx.s23.s2.args[0]
     373             : #include <typecheck-builtins.inc>
     374             : #undef  OP1
     375             : #undef  TYPECHECK_VARIABLESBASED
     376             : 
     377       79492 :         return true;
     378             : }
     379             : 
     380             : /* handle_multianewarray *******************************************************
     381             :  
     382             :    Verify a MULTIANEWARRAY instruction.
     383             :   
     384             :    IN:
     385             :        state............the current state of the verifier
     386             : 
     387             :    RETURN VALUE:
     388             :        true.............successful verification,
     389             :            false............an exception has been thrown.
     390             : 
     391             : *******************************************************************************/
     392             : 
     393             : static bool
     394          15 : handle_multianewarray(verifier_state *state)
     395             : {
     396             :         jitdata *jd;
     397             :     varinfo *dv;               /* output variable of current instruction */
     398             : 
     399          15 :         jd = state->jd;
     400          15 :         dv = VAROP(state->iptr->dst);
     401             : 
     402             : #define TYPECHECK_VARIABLESBASED
     403             : #define VERIFY_ERROR(msg)  TYPECHECK_VERIFYERROR_bool(msg)
     404             : #include <typecheck-multianewarray.inc>
     405             : #undef VERIFY_ERROR
     406             : #undef  TYPECHECK_VARIABLESBASED
     407             : 
     408          15 :         return true;
     409             : }
     410             : 
     411             : /* typecheck_invalidate_locals *************************************************
     412             :  
     413             :    Invalidate locals that are overwritten by writing to the given local.
     414             :   
     415             :    IN:
     416             :        state............the current state of the verifier
     417             :            index............the index of the local that is written
     418             :            twoword..........true, if a two-word type is written
     419             : 
     420             : *******************************************************************************/
     421             : 
     422      100480 : static void typecheck_invalidate_locals(verifier_state *state, s4 index, bool twoword)
     423             : {
     424             :         s4 javaindex;
     425             :         s4 t;
     426             :         s4 varindex;
     427      100480 :         jitdata *jd = state->jd;
     428      100480 :         s4 *localmap = jd->local_map;
     429      100480 :         varinfo *vars = jd->var;
     430             : 
     431      100480 :         javaindex = jd->reverselocalmap[index];
     432             : 
     433             :         /* invalidate locals of two-word type at index javaindex-1 */
     434             : 
     435      100480 :         if (javaindex > 0) {
     436       96281 :                 localmap += 5 * (javaindex-1);
     437      577686 :                 for (t=0; t<5; ++t) {
     438      481405 :                         varindex = *localmap++;
     439      481405 :                         if (varindex >= 0 && IS_2_WORD_TYPE(vars[varindex].type)) {
     440             :                                 OLD_LOG1("invalidate local %d", varindex);
     441           3 :                                 vars[varindex].type = TYPE_VOID;
     442             :                         }
     443             :                 }
     444             :         }
     445             :         else {
     446        4199 :                 localmap += 5 * javaindex;
     447             :         }
     448             : 
     449             :         /* invalidate locals at index javaindex */
     450             : 
     451      602880 :         for (t=0; t<5; ++t) {
     452      502400 :                 varindex = *localmap++;
     453      502400 :                 if (varindex >= 0) {
     454             :                         OLD_LOG1("invalidate local %d", varindex);
     455      109170 :                         vars[varindex].type = TYPE_VOID;
     456             :                 }
     457             :         }
     458             : 
     459             :         /* if a two-word type is written, invalidate locals at index javaindex+1 */
     460             : 
     461      100480 :         if (twoword) {
     462       31380 :                 for (t=0; t<5; ++t) {
     463       26150 :                         varindex = *localmap++;
     464       26150 :                         if (varindex >= 0) {
     465             :                                 OLD_LOG1("invalidate local %d", varindex);
     466           9 :                                 vars[varindex].type = TYPE_VOID;
     467             :                         }
     468             :                 }
     469             :         }
     470      100480 : }
     471             : 
     472             : 
     473             : /* macros used by the generated code ******************************************/
     474             : 
     475             : #define EXCEPTION          do { return false; } while (0)
     476             : #define VERIFY_ERROR(msg)  TYPECHECK_VERIFYERROR_bool(msg)
     477             : 
     478             : #define CHECK_LOCAL_TYPE(index, t)                                   \
     479             :     do {                                                             \
     480             :         if (!typevector_checktype(jd->var, (index), (t)))            \
     481             :              VERIFY_ERROR("Local variable type mismatch");           \
     482             :     } while (0)
     483             : 
     484             : #define STORE_LOCAL(t, index)                                        \
     485             :     do {                                                             \
     486             :          Type temp_t = (t);                                          \
     487             :          typecheck_invalidate_locals(state, (index), false);         \
     488             :          typevector_store(jd->var, (index), (temp_t), NULL);         \
     489             :     } while (0)
     490             : 
     491             : #define STORE_LOCAL_2_WORD(t, index)                                 \
     492             :     do {                                                             \
     493             :          Type temp_t = (t);                                          \
     494             :          typecheck_invalidate_locals(state, (index), true);          \
     495             :          typevector_store(jd->var, (index), (temp_t), NULL);         \
     496             :     } while (0)
     497             : 
     498             : #define REACH_BLOCK(target)                                          \
     499             :     do {                                                             \
     500             :         if (!typestate_reach(state, (target),                        \
     501             :                              state->bptr->outvars, jd->var,          \
     502             :                              state->bptr->outdepth))                 \
     503             :                 return false;                                        \
     504             :     } while (0)
     505             : 
     506             : #define REACH(target)   REACH_BLOCK((target).block)
     507             : 
     508             : 
     509             : /* handle_basic_block **********************************************************
     510             :  
     511             :    Perform bytecode verification of a basic block.
     512             :   
     513             :    IN:
     514             :        state............the current state of the verifier
     515             : 
     516             :    RETURN VALUE:
     517             :        true.............successful verification,
     518             :            false............an exception has been thrown.
     519             : 
     520             : *******************************************************************************/
     521             : 
     522             : static bool
     523      327877 : handle_basic_block(verifier_state *state)
     524             : {
     525             :     int opcode;                                      /* current opcode */
     526             :     int len;                        /* for counting instructions, etc. */
     527             :     bool superblockend;        /* true if no fallthrough to next block */
     528             :         instruction *iptr;                      /* the current instruction */
     529             :     basicblock *tbptr;                   /* temporary for target block */
     530             :     bool maythrow;               /* true if this instruction may throw */
     531             :         s4 i;
     532             :         typecheck_result r;
     533             :         branch_target_t *table;
     534             :         lookup_target_t *lookup;
     535      327877 :         jitdata *jd = state->jd;
     536             :         exception_entry *ex;
     537             :         varinfo constvalue;                               /* for PUT*CONST */
     538             :         constant_FMIref *fieldref;
     539             : 
     540             :         OLD_LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
     541             :         OLD_LOGFLUSH;
     542             : 
     543      327877 :         superblockend      = false;
     544      327877 :         state->bptr->state = basicblock::FINISHED;
     545             : 
     546             :         /* prevent compiler warnings */
     547             : 
     548             : 
     549             :         /* determine the active exception handlers for this block */
     550             :         /* XXX could use a faster algorithm with sorted lists or  */
     551             :         /* something?                                             */
     552      327877 :         len = 0;
     553      645025 :         for (ex = state->jd->exceptiontable; ex ; ex = ex->down) {
     554      317148 :                 if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
     555             :                         OLD_LOG1("active handler L%03d", ex->handler->nr);
     556       36802 :                         state->handlers[len++] = ex;
     557             :                 }
     558             :         }
     559      327877 :         state->handlers[len] = NULL;
     560             : 
     561             :         /* init variable types at the start of this block */
     562      327877 :         typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
     563             : 
     564             :         DOLOG(show_basicblock(jd, state->bptr, SHOW_STACK));
     565             :         DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars, 
     566             :                                 state->bptr->indepth));
     567             :         DOLOG(typevector_print(stdout, jd->var, state->numlocals));
     568             :         OLD_LOGNL; OLD_LOGFLUSH;
     569             : 
     570             :         /* loop over the instructions */
     571      327876 :         len = state->bptr->icount;
     572      327876 :         state->iptr = state->bptr->iinstr;
     573     5133432 :         while (--len >= 0)  {
     574             :                 TYPECHECK_COUNT(stat_ins);
     575             : 
     576     4477694 :                 iptr = state->iptr;
     577             : 
     578             :                 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
     579             :                 OLD_LOGNL; OLD_LOGFLUSH;
     580             :                 DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); OLD_LOGNL; OLD_LOGFLUSH;
     581             : 
     582     4477694 :                 opcode = iptr->opc;
     583     4477694 :                 maythrow = false;
     584             : 
     585     4477694 :                 switch (opcode) {
     586             : 
     587             :                         /* include generated code for ICMDs verification */
     588             : 
     589             : #define TYPECHECK_VARIABLESBASED
     590             : #define STATE  state
     591             : #define METHOD (state->m)
     592             : #define IPTR   iptr
     593             : #define BPTR   (state->bptr)
     594             : #include <typecheck-variablesbased-gen.inc>
     595             : #undef  STATE
     596             : #undef  METHOD
     597             : #undef  IPTR
     598             : #undef  BPTR
     599             : #undef  TYPECHECK_VARIABLESBASED
     600             : 
     601             :                         default:
     602             :                                 OLD_LOG1("ICMD %d\n", opcode);
     603           0 :                                 TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
     604             :                 }
     605             : 
     606             :                 /* reach exception handlers for this instruction */
     607             : 
     608     4477680 :                 if (maythrow) {
     609             :                         TYPECHECK_COUNT(stat_ins_maythrow);
     610             :                         TYPECHECK_MARK(state->stat_maythrow);
     611             :                         OLD_LOG("reaching exception handlers");
     612     1450758 :                         i = 0;
     613     3008816 :                         while (state->handlers[i]) {
     614             :                                 TYPECHECK_COUNT(stat_handlers_reached);
     615      107300 :                                 if (state->handlers[i]->catchtype.any)
     616       70839 :                                         VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
     617             :                                 else
     618       36461 :                                         VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
     619      214600 :                                 if (!typestate_reach(state,
     620      107300 :                                                 state->handlers[i]->handler,
     621             :                                                 &(state->exinvars), jd->var, 1))
     622           0 :                                         return false;
     623      107300 :                                 i++;
     624             :                         }
     625             :                 }
     626             : 
     627             :                 OLD_LOG("\t\tnext instruction");
     628     4477680 :                 state->iptr++;
     629             :         } /* while instructions */
     630             : 
     631             :         OLD_LOG("instructions done");
     632             :         OLD_LOGSTR("RESULT=> ");
     633             :         DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
     634             :                                 state->bptr->outdepth));
     635             :         DOLOG(typevector_print(stdout, jd->var, state->numlocals));
     636             :         OLD_LOGNL; OLD_LOGFLUSH;
     637             : 
     638             :         /* propagate stack and variables to the following block */
     639      327862 :         if (!superblockend) {
     640             :                 OLD_LOG("reaching following block");
     641      168579 :                 tbptr = state->bptr->next;
     642      337158 :                 while (tbptr->state == basicblock::DELETED) {
     643           0 :                         tbptr = tbptr->next;
     644             : #ifdef TYPECHECK_DEBUG
     645             :                         /* this must be checked in parse.c */
     646           0 :                         if ((tbptr->nr) >= state->basicblockcount)
     647           0 :                                 TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
     648             : #endif
     649             :                 }
     650      168579 :                 if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
     651             :                                         state->bptr->outdepth))
     652           2 :                         return false;
     653             :         }
     654             : 
     655             :         /* We may have to restore the types of the instack slots. They
     656             :          * have been saved if an <init> call inside the block has
     657             :          * modified the instack types. (see INVOKESPECIAL) */
     658             : 
     659      327860 :         if (state->savedinvars)
     660         721 :                 typestate_restore_invars(state);
     661             : 
     662      327860 :         return true;
     663             : }
     664             : 
     665             : 
     666             : /****************************************************************************/
     667             : /* typecheck()                                                              */
     668             : /* This is the main function of the bytecode verifier. It is called         */
     669             : /* directly after analyse_stack.                                            */
     670             : /*                                                                          */
     671             : /* IN:                                                                      */
     672             : /*    meth.............the method to verify                                 */
     673             : /*    cdata............codegendata for the method                           */
     674             : /*    rdata............registerdata for the method                          */
     675             : /*                                                                          */
     676             : /* RETURN VALUE:                                                            */
     677             : /*     true.............successful verification                             */
     678             : /*     false............an exception has been thrown                        */
     679             : /*                                                                          */
     680             : /****************************************************************************/
     681             : 
     682             : #define MAXPARAMS 255
     683             : 
     684       86416 : bool typecheck(jitdata *jd)
     685             : {
     686             :         methodinfo     *meth;
     687             :         codegendata    *cd;
     688             :         varinfo        *savedlocals;
     689             :         verifier_state  state;             /* current state of the verifier */
     690             : 
     691             :         /* collect statistics */
     692             : 
     693             : #ifdef TYPECHECK_STATISTICS
     694             :         int count_iterations = 0;
     695             :         TYPECHECK_COUNT(stat_typechecked);
     696             :         TYPECHECK_COUNT_FREQ(stat_locals,jd->maxlocals,STAT_LOCALS);
     697             :         TYPECHECK_COUNT_FREQ(stat_blocks,cdata->method->basicblockcount/10,STAT_BLOCKS);
     698             :         TYPECHECK_COUNTIF(cdata->method->exceptiontablelength != 0,stat_methods_with_handlers);
     699             :         state.stat_maythrow = false;
     700             : #endif
     701             : 
     702             :         /* get required compiler data */
     703             : 
     704       86416 :         meth = jd->m;
     705       86416 :         cd   = jd->cd;
     706             : 
     707             :         /* some logging on entry */
     708             : 
     709             : 
     710             :     OLD_LOGSTR("\n==============================================================================\n");
     711             :     DOLOG( show_method(jd, SHOW_STACK) );
     712             :     OLD_LOGSTR("\n==============================================================================\n");
     713             :     OLD_LOGMETHOD("Entering typecheck: ",cd->method);
     714             : 
     715             :         /* initialize the verifier state */
     716             : 
     717       86416 :         state.m = meth;
     718       86416 :         state.jd = jd;
     719       86416 :         state.cd = cd;
     720       86416 :         state.basicblockcount = jd->basicblockcount;
     721       86416 :         state.basicblocks = jd->basicblocks;
     722       86416 :         state.savedindices = NULL;
     723       86416 :         state.savedinvars = NULL;
     724             : 
     725             :         /* check that the basicblock numbers are valid */
     726             : 
     727             : #if !defined(NDEBUG)
     728       86416 :         jit_check_basicblock_numbers(jd);
     729             : #endif
     730             : 
     731             :         /* check if this method is an instance initializer method */
     732             : 
     733       86416 :     state.initmethod = (state.m->name == utf8::init);
     734             : 
     735             :         /* initialize the basic block flags for the following CFG traversal */
     736             : 
     737       86416 :         typecheck_init_state(&state, basicblock::FINISHED);
     738             : 
     739             :     /* number of local variables */
     740             : 
     741             :     /* In <init> methods we use an extra local variable to indicate whether */
     742             :     /* the 'this' reference has been initialized.                           */
     743             :         /*         TYPE_VOID...means 'this' has not been initialized,           */
     744             :         /*         TYPE_INT....means 'this' has been initialized.               */
     745             : 
     746       86416 :     state.numlocals = state.jd->localcount;
     747       86416 :         state.validlocals = state.numlocals;
     748       86416 :     if (state.initmethod)
     749       25532 :                 state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
     750             : 
     751             :         DOLOG(
     752             :                 s4 i;
     753             :                 s4 t;
     754             :                 OLD_LOG("reverselocalmap:");
     755             :                 for (i=0; i<state.validlocals; ++i) {
     756             :                         OLD_LOG2("    %i => javaindex %i", i, jd->reverselocalmap[i]);
     757             :                 });
     758             : 
     759             :     /* allocate the buffer of active exception handlers */
     760             : 
     761       86416 :     state.handlers = (exception_entry**) DumpMemory::allocate(sizeof(exception_entry*) * (state.jd->exceptiontablelength + 1));
     762             : 
     763             :         /* save local variables */
     764             : 
     765       86416 :         savedlocals = (varinfo*) DumpMemory::allocate(sizeof(varinfo) * state.numlocals);
     766       86416 :         MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
     767             : 
     768             :         /* initialized local variables of first block */
     769             : 
     770       86416 :         if (!typecheck_init_locals(&state, true))
     771           0 :                 return false;
     772             : 
     773             :     /* initialize invars of exception handlers */
     774             : 
     775       86416 :         state.exinvars = state.numlocals;
     776       86416 :         VAR(state.exinvars)->type = TYPE_ADR;
     777       86416 :         VAR(state.exinvars)->typeinfo.init_class(class_java_lang_Throwable); /* changed later */
     778             : 
     779             :         OLD_LOG("Exception handler stacks set.\n");
     780             : 
     781             :         // loop while there are still blocks to be checked
     782       94946 :         do {
     783             :                 TYPECHECK_COUNT(count_iterations);
     784             : 
     785       94963 :                 state.repeat = false;
     786       94963 :                 state.bptr   = state.basicblocks;
     787             : 
     788      640062 :                 for (; state.bptr; state.bptr = state.bptr->next) {
     789             :                         OLD_LOGSTR1("---- BLOCK %04d, ",state.bptr->nr);
     790             :                         OLD_LOGSTR1("blockflags: %d\n",state.bptr->state);
     791             :                         OLD_LOGFLUSH;
     792             : 
     793             :                         // verify reached block
     794      545116 :                         if (state.bptr->state == basicblock::TYPECHECK_REACHED) {
     795      327877 :                                 if (!handle_basic_block(&state))
     796          17 :                                         return false;
     797             :                         }
     798             :                 } // for blocks
     799             : 
     800             :                 OLD_LOGIF(state.repeat,"state.repeat == true");
     801             :         } while (state.repeat);
     802             : 
     803             :         /* statistics */
     804             : 
     805             : #ifdef TYPECHECK_STATISTICS
     806             :         OLD_LOG1("Typechecker did %4d iterations",count_iterations);
     807             :         TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
     808             :         TYPECHECK_COUNTIF(state.jsrencountered,stat_typechecked_jsr);
     809             :         TYPECHECK_COUNTIF(state.stat_maythrow,stat_methods_maythrow);
     810             : #endif
     811             : 
     812             :         /* reset the flags of blocks we haven't reached */
     813             : 
     814       86399 :         typecheck_reset_state(&state);
     815             : 
     816             :         /* restore locals */
     817             : 
     818       86399 :         MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
     819             : 
     820             :         /* everything's ok */
     821             : 
     822             :     OLD_LOGimp("exiting typecheck");
     823       86399 :         return true;
     824             : }
     825             : 
     826             : #endif /* ENABLE_VERIFIER */
     827             : 
     828             : /*
     829             :  * These are local overrides for various environment variables in Emacs.
     830             :  * Please do not remove this and leave it at the end of the file, where
     831             :  * Emacs will automagically detect them.
     832             :  * ---------------------------------------------------------------------
     833             :  * Local variables:
     834             :  * mode: c++
     835             :  * indent-tabs-mode: t
     836             :  * c-basic-offset: 4
     837             :  * tab-width: 4
     838             :  * End:
     839             :  * vim:noexpandtab:sw=4:ts=4:
     840             :  */

Generated by: LCOV version 1.11