LCOV - code coverage report
Current view: top level - vm/jit/verify - typecheck-typeinferer.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 86 0.0 %
Date: 2017-07-14 10:03:36 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /* src/vm/jit/verify/typecheck-typeinferer.c - type inference pass
       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             : #include "vm/jit/verify/typecheck-typeinferer.hpp"
      26             : #include "config.h"
      27             : 
      28             : #include <assert.h>
      29             : #include <string.h>
      30             : 
      31             : #include "mm/memory.hpp"
      32             : #include "mm/dumpmemory.hpp"
      33             : 
      34             : #include "native/native.hpp"
      35             : 
      36             : #include "toolbox/logging.hpp"
      37             : 
      38             : #include "vm/access.hpp"
      39             : #include "vm/array.hpp"
      40             : #include "vm/descriptor.hpp"            // for typedesc, methoddesc, etc
      41             : #include "vm/exceptions.hpp"
      42             : #include "vm/global.hpp"
      43             : #include "vm/globals.hpp"
      44             : #include "vm/options.hpp"
      45             : #include "vm/primitive.hpp"
      46             : #include "vm/resolve.hpp"
      47             : #include "vm/types.hpp"
      48             : #include "vm/vm.hpp"
      49             : 
      50             : #include "vm/jit/builtin.hpp"
      51             : #include "vm/jit/jit.hpp"
      52             : #include "vm/jit/show.hpp"
      53             : #include "vm/jit/parse.hpp"
      54             : 
      55             : #include "vm/jit/ir/instruction.hpp"
      56             : 
      57             : #define TYPECHECK_NO_STATISTICS
      58             : #include "vm/jit/verify/typecheck-common.hpp"
      59             : 
      60             : 
      61             : /* macros used by the generated code ******************************************/
      62             : 
      63             : #define EXCEPTION          do { return false; } while (0)
      64             : #define VERIFY_ERROR(msg)  assert(false)
      65             : 
      66             : #define CHECK_LOCAL_TYPE(index, t)                                   \
      67             :         assert(jd->var[(index)].type == (t));
      68             : 
      69             : #define STORE_LOCAL(t, index)                                        \
      70             :     do {                                                             \
      71             :          typevector_store(jd->var, (index), (t), NULL);              \
      72             :     } while (0)
      73             : 
      74             : #define STORE_LOCAL_2_WORD(t, index)                                 \
      75             :     do {                                                             \
      76             :          typevector_store(jd->var, (index), (t), NULL);              \
      77             :     } while (0)
      78             : 
      79             : #define REACH_BLOCK(target)                                          \
      80             :     do {                                                             \
      81             :         if (!typestate_reach(state, (target),                        \
      82             :                              state->bptr->outvars, jd->var,          \
      83             :                              state->bptr->outdepth))                 \
      84             :                 return false;                                        \
      85             :     } while (0)
      86             : 
      87             : #define REACH(target)   REACH_BLOCK((target).block)
      88             : 
      89             : #define TYPECHECK_INT(v)  assert(jd->var[(v)].type == TYPE_INT)
      90             : #define TYPECHECK_ADR(v)  assert(jd->var[(v)].type == TYPE_ADR)
      91             : 
      92             : 
      93             : /* handle_fieldaccess **********************************************************
      94             :  
      95             :    Verify an ICMD_{GET,PUT}{STATIC,FIELD}(CONST)?
      96             :   
      97             :    IN:
      98             :        state............the current state of the verifier
      99             : 
     100             :    RETURN VALUE:
     101             :        true.............successful verification,
     102             :            false............an exception has been thrown.
     103             : 
     104             : *******************************************************************************/
     105             : 
     106             : static bool
     107           0 : handle_fieldaccess(verifier_state *state, 
     108             :                                    varinfo *instance,
     109             :                                    varinfo *value)
     110             : {
     111             :         jitdata *jd;
     112             : 
     113           0 :         jd = state->jd;
     114             : 
     115             : #define TYPECHECK_TYPEINFERER
     116             : #include <typecheck-fields.inc>
     117             : #undef  TYPECHECK_TYPEINFERER
     118             : 
     119           0 :         return true;
     120             : }
     121             : 
     122             : 
     123             : /* handle_invocation ***********************************************************
     124             :  
     125             :    Verify an ICMD_INVOKE* instruction.
     126             :   
     127             :    IN:
     128             :        state............the current state of the verifier
     129             : 
     130             :    RETURN VALUE:
     131             :        true.............successful verification,
     132             :            false............an exception has been thrown.
     133             : 
     134             : *******************************************************************************/
     135             : 
     136             : static bool
     137           0 : handle_invocation(verifier_state *state)
     138             : {
     139             :         jitdata *jd;
     140             :     varinfo *dv;               /* output variable of current instruction */
     141             : 
     142           0 :         jd = state->jd;
     143           0 :         dv = VAROP(state->iptr->dst);
     144             : 
     145             : #define TYPECHECK_TYPEINFERER
     146             : #define OP1   VAR(state->iptr->sx.s23.s2.args[0])
     147             : #include <typecheck-invoke.inc>
     148             : #undef  OP1
     149             : #undef  TYPECHECK_TYPEINFERER
     150             : 
     151           0 :         return true;
     152             : }
     153             : 
     154             : 
     155             : /* handle_builtin **************************************************************
     156             :  
     157             :    Verify the call of a builtin method.
     158             :   
     159             :    IN:
     160             :        state............the current state of the verifier
     161             : 
     162             :    RETURN VALUE:
     163             :        true.............successful verification,
     164             :            false............an exception has been thrown.
     165             : 
     166             : *******************************************************************************/
     167             : 
     168             : static bool
     169           0 : handle_builtin(verifier_state *state)
     170             : {
     171             :         jitdata *jd;
     172             :     varinfo *dv;               /* output variable of current instruction */
     173             : 
     174           0 :         jd = state->jd;
     175           0 :         dv = VAROP(state->iptr->dst);
     176             : 
     177             : #define TYPECHECK_TYPEINFERER
     178             : #define OP1   state->iptr->sx.s23.s2.args[0]
     179             : #include <typecheck-builtins.inc>
     180             : #undef  OP1
     181             : #undef  TYPECHECK_TYPEINFERER
     182             : 
     183           0 :         return true;
     184             : }
     185             : 
     186             : /* handle_multianewarray *******************************************************
     187             :  
     188             :    Verify a MULTIANEWARRAY instruction.
     189             :   
     190             :    IN:
     191             :        state............the current state of the verifier
     192             : 
     193             :    RETURN VALUE:
     194             :        true.............successful verification,
     195             :            false............an exception has been thrown.
     196             : 
     197             : *******************************************************************************/
     198             : 
     199             : static bool
     200           0 : handle_multianewarray(verifier_state *state)
     201             : {
     202             :         jitdata *jd;
     203             :     varinfo *dv;               /* output variable of current instruction */
     204             : 
     205           0 :         jd = state->jd;
     206           0 :         dv = VAROP(state->iptr->dst);
     207             : 
     208             : #define TYPECHECK_TYPEINFERER
     209             : #include <typecheck-multianewarray.inc>
     210             : #undef  TYPECHECK_TYPEINFERER
     211             : 
     212           0 :         return true;
     213             : }
     214             : 
     215             : 
     216             : /* handle_basic_block **********************************************************
     217             :  
     218             :    Perform bytecode verification of a basic block.
     219             :   
     220             :    IN:
     221             :        state............the current state of the verifier
     222             : 
     223             :    RETURN VALUE:
     224             :        true.............successful verification,
     225             :            false............an exception has been thrown.
     226             : 
     227             : *******************************************************************************/
     228             : 
     229             : static bool
     230           0 : handle_basic_block(verifier_state *state)
     231             : {
     232             :     int opcode;                                      /* current opcode */
     233             :     int len;                        /* for counting instructions, etc. */
     234             :     bool superblockend;        /* true if no fallthrough to next block */
     235             :         instruction *iptr;                      /* the current instruction */
     236             :     basicblock *tbptr;                   /* temporary for target block */
     237             :     bool maythrow;               /* true if this instruction may throw */
     238             :         s4 i;
     239             :         branch_target_t *table;
     240             :         lookup_target_t *lookup;
     241           0 :         jitdata *jd = state->jd;
     242             :         exception_entry *ex;
     243             : 
     244             :         OLD_LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
     245             :         OLD_LOGFLUSH;
     246             :         DOLOG(show_basicblock(jd, state->bptr, SHOW_STACK));
     247             : 
     248           0 :         superblockend = false;
     249           0 :         state->bptr->state = basicblock::FINISHED;
     250             : 
     251             :         /* prevent compiler warnings */
     252             : 
     253             : 
     254             :         /* determine the active exception handlers for this block */
     255             :         /* XXX could use a faster algorithm with sorted lists or  */
     256             :         /* something?                                             */
     257           0 :         len = 0;
     258           0 :         for (ex = state->jd->exceptiontable; ex ; ex = ex->down) {
     259           0 :                 if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
     260             :                         OLD_LOG1("active handler L%03d", ex->handler->nr);
     261           0 :                         state->handlers[len++] = ex;
     262             :                 }
     263             :         }
     264           0 :         state->handlers[len] = NULL;
     265             : 
     266             :         /* init variable types at the start of this block */
     267           0 :         typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
     268             : 
     269             :         DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars, 
     270             :                                 state->bptr->indepth));
     271             :         DOLOG(typevector_print(stdout, jd->var, state->numlocals));
     272             :         OLD_LOGNL; OLD_LOGFLUSH;
     273             : 
     274             :         /* loop over the instructions */
     275           0 :         len = state->bptr->icount;
     276           0 :         state->iptr = state->bptr->iinstr;
     277           0 :         while (--len >= 0)  {
     278             :                 TYPECHECK_COUNT(stat_ins);
     279             : 
     280           0 :                 iptr = state->iptr;
     281             : 
     282             :                 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
     283             :                 OLD_LOGNL; OLD_LOGFLUSH;
     284             :                 DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); OLD_LOGNL; OLD_LOGFLUSH;
     285             : 
     286           0 :                 opcode = iptr->opc;
     287           0 :                 maythrow = false;
     288             : 
     289           0 :                 switch (opcode) {
     290             : 
     291             :                         /* include generated code for ICMDs verification */
     292             : 
     293             : #define TYPECHECK_TYPEINFERER
     294             : #define STATE  state
     295             : #define METHOD (state->m)
     296             : #define IPTR   iptr
     297             : #define BPTR   (state->bptr)
     298             : #include <typecheck-typeinferer-gen.inc>
     299             : #undef  STATE
     300             : #undef  METHOD
     301             : #undef  IPTR
     302             : #undef  BPTR
     303             : #undef  TYPECHECK_TYPEINFERER
     304             : 
     305             :                         default:
     306           0 :                                 vm_abort("missing ICMD in type inferer: %d\n", opcode);
     307             :                 }
     308             : 
     309             :                 /* reach exception handlers for this instruction */
     310             : 
     311           0 :                 if (maythrow) {
     312             :                         TYPECHECK_COUNT(stat_ins_maythrow);
     313             :                         TYPECHECK_MARK(state->stat_maythrow);
     314             :                         OLD_LOG("reaching exception handlers");
     315           0 :                         i = 0;
     316           0 :                         while (state->handlers[i]) {
     317             :                                 TYPECHECK_COUNT(stat_handlers_reached);
     318           0 :                                 if (state->handlers[i]->catchtype.any)
     319           0 :                                         VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
     320             :                                 else
     321           0 :                                         VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
     322           0 :                                 if (!typestate_reach(state,
     323           0 :                                                 state->handlers[i]->handler,
     324             :                                                 &(state->exinvars), jd->var, 1))
     325           0 :                                         return false;
     326           0 :                                 i++;
     327             :                         }
     328             :                 }
     329             : 
     330             :                 OLD_LOG("\t\tnext instruction");
     331           0 :                 state->iptr++;
     332             :         } /* while instructions */
     333             : 
     334             :         OLD_LOG("instructions done");
     335             :         OLD_LOGSTR("RESULT=> ");
     336             :         DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
     337             :                                 state->bptr->outdepth));
     338             :         DOLOG(typevector_print(stdout, jd->var, state->numlocals));
     339             :         OLD_LOGNL; OLD_LOGFLUSH;
     340             : 
     341             :         /* propagate stack and variables to the following block */
     342           0 :         if (!superblockend) {
     343             :                 OLD_LOG("reaching following block");
     344           0 :                 tbptr = state->bptr->next;
     345           0 :                 while (tbptr->state == basicblock::DELETED) {
     346           0 :                         tbptr = tbptr->next;
     347             :                 }
     348           0 :                 if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
     349             :                                         state->bptr->outdepth))
     350           0 :                         return false;
     351             :         }
     352             : 
     353           0 :         return true;
     354             : }
     355             : 
     356             : 
     357           0 : bool typecheck_infer_types(jitdata *jd)
     358             : {
     359             :         methodinfo     *meth;
     360             :         codegendata    *cd;
     361             :         varinfo        *savedlocals;
     362             :         verifier_state  state;             /* current state of the verifier */
     363             : 
     364             :         /* get required compiler data */
     365             : 
     366           0 :         meth = jd->m;
     367           0 :         cd   = jd->cd;
     368             : 
     369             :         /* some logging on entry */
     370             : 
     371             : 
     372             :     OLD_LOGSTR("\n==============================================================================\n");
     373             :     DOLOG( show_method(jd, SHOW_STACK) );
     374             :     OLD_LOGSTR("\n==============================================================================\n");
     375             :     OLD_LOGMETHOD("Entering type inference: ",cd->method);
     376             : 
     377             :         /* initialize the verifier state */
     378             : 
     379           0 :         state.m = meth;
     380           0 :         state.jd = jd;
     381           0 :         state.cd = cd;
     382           0 :         state.basicblockcount = jd->basicblockcount;
     383           0 :         state.basicblocks = jd->basicblocks;
     384           0 :         state.savedindices = NULL;
     385           0 :         state.savedinvars = NULL;
     386             : 
     387             :         /* check that the basicblock numbers are valid */
     388             : 
     389             : #if !defined(NDEBUG)
     390           0 :         jit_check_basicblock_numbers(jd);
     391             : #endif
     392             : 
     393             :         /* check if this method is an instance initializer method */
     394             : 
     395           0 :     state.initmethod = (state.m->name == utf8::init);
     396             : 
     397             :         /* initialize the basic block flags for the following CFG traversal */
     398             : 
     399           0 :         typecheck_init_state(&state, basicblock::FINISHED);
     400             : 
     401             :     /* number of local variables */
     402             : 
     403             :     /* In <init> methods we use an extra local variable to indicate whether */
     404             :     /* the 'this' reference has been initialized.                           */
     405             :         /*         TYPE_VOID...means 'this' has not been initialized,           */
     406             :         /*         TYPE_INT....means 'this' has been initialized.               */
     407             : 
     408           0 :     state.numlocals = state.jd->localcount;
     409           0 :         state.validlocals = state.numlocals;
     410           0 :     if (state.initmethod)
     411           0 :                 state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
     412             : 
     413             :     /* allocate the buffer of active exception handlers */
     414             : 
     415           0 :     state.handlers = (exception_entry**) DumpMemory::allocate(sizeof(exception_entry*) * (state.jd->exceptiontablelength + 1));
     416             : 
     417             :         /* save local variables */
     418             : 
     419           0 :         savedlocals = (varinfo*) DumpMemory::allocate(sizeof(varinfo) * state.numlocals);
     420           0 :         MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
     421             : 
     422             :         /* initialized local variables of first block */
     423             : 
     424           0 :         if (!typecheck_init_locals(&state, false))
     425           0 :                 return false;
     426             : 
     427             :     /* initialize invars of exception handlers */
     428             : 
     429           0 :         state.exinvars = state.numlocals;
     430           0 :         VAR(state.exinvars)->type = TYPE_ADR;
     431           0 :         VAR(state.exinvars)->typeinfo.init_class(class_java_lang_Throwable); /* changed later */
     432             : 
     433             :     OLD_LOG("Exception handler stacks set.\n");
     434             : 
     435             :         // loop while there are still blocks to be checked
     436           0 :         do {
     437             :                 TYPECHECK_COUNT(count_iterations);
     438             : 
     439           0 :                 state.repeat = false;
     440           0 :                 state.bptr   = state.basicblocks;
     441             : 
     442           0 :                 for (; state.bptr; state.bptr = state.bptr->next) {
     443             :                         OLD_LOGSTR1("---- BLOCK %04d, ", state.bptr->nr);
     444             :                         OLD_LOGSTR1("blockflags: %d\n", state.bptr->state);
     445             :                         OLD_LOGFLUSH;
     446             : 
     447             :                         // verify reached block
     448           0 :                         if (state.bptr->state == basicblock::TYPECHECK_REACHED) {
     449           0 :                                 if (!handle_basic_block(&state))
     450           0 :                                         return false;
     451             :                         }
     452             :                 } // for blocks
     453             : 
     454             :                 OLD_LOGIF(state.repeat,"state.repeat == true");
     455             :         } while (state.repeat);
     456             : 
     457             :         /* statistics */
     458             :         /* reset the flags of blocks we haven't reached */
     459             : 
     460           0 :         typecheck_reset_state(&state);
     461             : 
     462             :         /* restore locals */
     463             : 
     464           0 :         MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
     465             : 
     466             :         /* everything's ok */
     467             : 
     468             :         OLD_LOGimp("exiting type inference");
     469           0 :         return true;
     470             : }
     471             : 
     472             : 
     473             : /*
     474             :  * These are local overrides for various environment variables in Emacs.
     475             :  * Please do not remove this and leave it at the end of the file, where
     476             :  * Emacs will automagically detect them.
     477             :  * ---------------------------------------------------------------------
     478             :  * Local variables:
     479             :  * mode: c++
     480             :  * indent-tabs-mode: t
     481             :  * c-basic-offset: 4
     482             :  * tab-width: 4
     483             :  * End:
     484             :  * vim:noexpandtab:sw=4:ts=4:
     485             :  */

Generated by: LCOV version 1.11