LCOV - code coverage report
Current view: top level - vm/jit/verify - typecheck-common.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 85 99 85.9 %
Date: 2017-07-14 10:03:36 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* src/vm/jit/verify/typecheck-common.cpp - shared verifier code
       2             : 
       3             :    Copyright (C) 1996-2014
       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             : #include "config.h"
      27             : #include "vm/types.hpp"
      28             : #include "vm/global.hpp"
      29             : 
      30             : #include <assert.h>
      31             : 
      32             : #include "vm/descriptor.hpp"            // for typedesc, methoddesc, etc
      33             : #include "vm/exceptions.hpp"
      34             : #include "vm/globals.hpp"
      35             : #include "vm/method.hpp"
      36             : 
      37             : #include "vm/jit/show.hpp"
      38             : 
      39             : #include "typecheck-common.hpp"
      40             : 
      41             : 
      42             : /****************************************************************************/
      43             : /* DEBUG HELPERS                                                            */
      44             : /****************************************************************************/
      45             : 
      46             : #ifdef TYPECHECK_VERBOSE_OPT
      47             : bool opt_typecheckverbose = false;
      48             : #endif
      49             : 
      50             : #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
      51             : 
      52             : void typecheck_print_var(FILE *file, jitdata *jd, s4 index)
      53             : {
      54             :         varinfo *var;
      55             : 
      56             :         assert(index >= 0 && index < jd->varcount);
      57             :         var = VAR(index);
      58             :         typeinfo_print_type(file, var->type, &(var->typeinfo));
      59             : }
      60             : 
      61             : void typecheck_print_vararray(FILE *file, jitdata *jd, s4 *vars, int len)
      62             : {
      63             :         s4 i;
      64             : 
      65             :         for (i=0; i<len; ++i) {
      66             :                 if (i)
      67             :                         fputc(' ', file);
      68             :                 typecheck_print_var(file, jd, *vars++);
      69             :         }
      70             : }
      71             : 
      72             : #endif /* defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT) */
      73             : 
      74             : 
      75             : /****************************************************************************/
      76             : /* STATISTICS                                                               */
      77             : /****************************************************************************/
      78             : 
      79             : #if defined(TYPECHECK_STATISTICS)
      80             : #warning port to new statistics framework
      81             : int stat_typechecked = 0;
      82             : int stat_methods_with_handlers = 0;
      83             : int stat_methods_maythrow = 0;
      84             : int stat_iterations[STAT_ITERATIONS+1] = { 0 };
      85             : int stat_reached = 0;
      86             : int stat_copied = 0;
      87             : int stat_merged = 0;
      88             : int stat_merging_changed = 0;
      89             : int stat_blocks[STAT_BLOCKS+1] = { 0 };
      90             : int stat_locals[STAT_LOCALS+1] = { 0 };
      91             : int stat_ins = 0;
      92             : int stat_ins_maythrow = 0;
      93             : int stat_ins_stack = 0;
      94             : int stat_ins_field = 0;
      95             : int stat_ins_field_unresolved = 0;
      96             : int stat_ins_field_uninitialized = 0;
      97             : int stat_ins_invoke = 0;
      98             : int stat_ins_invoke_unresolved = 0;
      99             : int stat_ins_primload = 0;
     100             : int stat_ins_aload = 0;
     101             : int stat_ins_builtin = 0;
     102             : int stat_ins_builtin_gen = 0;
     103             : int stat_ins_branch = 0;
     104             : int stat_ins_switch = 0;
     105             : int stat_ins_primitive_return = 0;
     106             : int stat_ins_areturn = 0;
     107             : int stat_ins_areturn_unresolved = 0;
     108             : int stat_ins_athrow = 0;
     109             : int stat_ins_athrow_unresolved = 0;
     110             : int stat_ins_unchecked = 0;
     111             : int stat_handlers_reached = 0;
     112             : int stat_savedstack = 0;
     113             : 
     114             : static void print_freq(FILE *file,int *array,int limit)
     115             : {
     116             :         int i;
     117             :         for (i=0; i<limit; ++i)
     118             :                 fprintf(file,"      %3d: %8d\n",i,array[i]);
     119             :         fprintf(file,"    >=%3d: %8d\n",limit,array[limit]);
     120             : }
     121             : 
     122             : void typecheck_print_statistics(FILE *file) {
     123             :         fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
     124             :         fprintf(file,"    with handler(s): %8d\n",stat_methods_with_handlers);
     125             :         fprintf(file,"    with throw(s)  : %8d\n",stat_methods_maythrow);
     126             :         fprintf(file,"reached blocks     : %8d\n",stat_reached);
     127             :         fprintf(file,"copied states      : %8d\n",stat_copied);
     128             :         fprintf(file,"merged states      : %8d\n",stat_merged);
     129             :         fprintf(file,"merging changed    : %8d\n",stat_merging_changed);
     130             :         fprintf(file,"handlers reached   : %8d\n",stat_handlers_reached);
     131             :         fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
     132             :         fprintf(file,"instructions       : %8d\n",stat_ins);
     133             :         fprintf(file,"    stack          : %8d\n",stat_ins_stack);
     134             :         fprintf(file,"    field access   : %8d\n",stat_ins_field);
     135             :         fprintf(file,"      (unresolved) : %8d\n",stat_ins_field_unresolved);
     136             :         fprintf(file,"      (uninit.)    : %8d\n",stat_ins_field_uninitialized);
     137             :         fprintf(file,"    invocations    : %8d\n",stat_ins_invoke);
     138             :         fprintf(file,"      (unresolved) : %8d\n",stat_ins_invoke_unresolved);
     139             :         fprintf(file,"    load primitive : (currently not counted) %8d\n",stat_ins_primload);
     140             :         fprintf(file,"    load address   : %8d\n",stat_ins_aload);
     141             :         fprintf(file,"    builtins       : %8d\n",stat_ins_builtin);
     142             :         fprintf(file,"        generic    : %8d\n",stat_ins_builtin_gen);
     143             :         fprintf(file,"    branches       : %8d\n",stat_ins_branch);
     144             :         fprintf(file,"    switches       : %8d\n",stat_ins_switch);
     145             :         fprintf(file,"    prim. return   : %8d\n",stat_ins_primitive_return);
     146             :         fprintf(file,"    areturn        : %8d\n",stat_ins_areturn);
     147             :         fprintf(file,"      (unresolved) : %8d\n",stat_ins_areturn_unresolved);
     148             :         fprintf(file,"    athrow         : %8d\n",stat_ins_athrow);
     149             :         fprintf(file,"      (unresolved) : %8d\n",stat_ins_athrow_unresolved);
     150             :         fprintf(file,"    unchecked      : %8d\n",stat_ins_unchecked);
     151             :         fprintf(file,"    maythrow       : %8d\n",stat_ins_maythrow);
     152             :         fprintf(file,"iterations used:\n");
     153             :         print_freq(file,stat_iterations,STAT_ITERATIONS);
     154             :         fprintf(file,"basic blocks per method / 10:\n");
     155             :         print_freq(file,stat_blocks,STAT_BLOCKS);
     156             :         fprintf(file,"locals:\n");
     157             :         print_freq(file,stat_locals,STAT_LOCALS);
     158             : }
     159             : #endif /* defined(TYPECHECK_STATISTICS) */
     160             : 
     161             : 
     162             : /* typecheck_init_state ********************************************************
     163             : 
     164             :    Initialize the basic block state for the following CFG traversal.
     165             : 
     166             :    IN:
     167             :        state............the current state of the verifier
     168             :        minflags.........minimum state value of blocks that should be
     169             :                         considered
     170             : 
     171             : *******************************************************************************/
     172             : 
     173       86416 : void typecheck_init_state(verifier_state *state, basicblock::State minstate)
     174             : {
     175             :         basicblock *block;
     176             : 
     177             :         // set all FINISHED blocks to TYPECHECK_UNDEF
     178             : 
     179      492156 :         for (block = state->basicblocks; block; block = block->next) {
     180             : 
     181             : #ifdef TYPECHECK_DEBUG
     182             :                 // check for invalid state
     183      405740 :                 if (block->state != basicblock::FINISHED &&
     184             :                     block->state != basicblock::DELETED  &&
     185             :                     block->state != basicblock::UNDEF)
     186             :                 {
     187             :                         OLD_LOGSTR1("block state: %d\n",block->state); OLD_LOGFLUSH;
     188           0 :                         TYPECHECK_ASSERT(false);
     189             :                 }
     190             : #endif
     191             : 
     192      405740 :                 if (block->state >= minstate) {
     193      319321 :                         block->state = basicblock::TYPECHECK_UNDEF;
     194             :                 }
     195             :         }
     196             : 
     197             :         // the first block is always reached
     198             : 
     199       86416 :         if (state->basicblockcount && state->basicblocks[0].state == basicblock::TYPECHECK_UNDEF)
     200       86416 :                 state->basicblocks[0].state = basicblock::TYPECHECK_REACHED;
     201       86416 : }
     202             : 
     203             : 
     204             : /* typecheck_reset_state *******************************************************
     205             : 
     206             :    Reset the state of basic blocks we have not reached.
     207             : 
     208             :    IN:
     209             :        state............the current state of the verifier
     210             : 
     211             : *******************************************************************************/
     212             : 
     213       86399 : void typecheck_reset_state(verifier_state *state)
     214             : {
     215             :         // check for invalid state at exit
     216             : 
     217             : #ifdef TYPECHECK_DEBUG
     218      492080 :         for (basicblock *block = state->basicblocks; block; block = block->next) {
     219      405681 :                 if (block->state != basicblock::DELETED  &&
     220             :                     block->state != basicblock::UNDEF    &&
     221             :                     block->state != basicblock::FINISHED &&
     222             :                     block->state != basicblock::TYPECHECK_UNDEF) // typecheck may never reach
     223             :                                                                  // some exception handlers,
     224             :                                                                  // that's ok.
     225             :                 {
     226             :                         OLD_LOG2("block L%03d has invalid state after typecheck: %d",
     227             :                                  block->nr,block->state);
     228           0 :                         TYPECHECK_ASSERT(false);
     229             :                 }
     230             :         }
     231             : #endif
     232             : 
     233             :         // Delete blocks we never reached
     234             : 
     235      492080 :         for (basicblock *block = state->basicblocks; block; block = block->next) {
     236      405681 :                 if (block->state == basicblock::TYPECHECK_UNDEF)
     237           0 :                         block->state = basicblock::DELETED;
     238             :         }
     239       86399 : }
     240             : 
     241             : 
     242             : /****************************************************************************/
     243             : /* TYPESTACK MACROS AND FUNCTIONS                                           */
     244             : /*                                                                          */
     245             : /* These macros and functions act on the 'type stack', which is a shorthand */
     246             : /* for the types of the stackslots of the current stack. The type of a      */
     247             : /* stack slot is usually described by a TYPE_* constant and -- for TYPE_ADR */
     248             : /* -- by the typeinfo of the slot. The only thing that makes the type stack */
     249             : /* more complicated are returnAddresses of local subroutines, because a     */
     250             : /* single stack slot may contain a set of more than one possible return     */
     251             : /* address. This is handled by 'return address sets'. A return address set  */
     252             : /* is kept as a linked list dangling off the typeinfo of the stack slot.    */
     253             : /****************************************************************************/
     254             : 
     255             : /* typecheck_copy_types ********************************************************
     256             : 
     257             :    Copy the types of the source variables to the destination variables.
     258             : 
     259             :    IN:
     260             :            state............current verifier state
     261             :            srcvars..........array of variable indices to copy
     262             :            dstvars..........array of the destination variables
     263             :            n................number of variables to copy
     264             : 
     265             :    RETURN VALUE:
     266             :        true.............success
     267             :            false............an exception has been thrown
     268             : 
     269             : *******************************************************************************/
     270             : 
     271      234346 : bool typecheck_copy_types(verifier_state *state, s4 *srcvars, s4 *dstvars, s4 n)
     272             : {
     273             :         s4 i;
     274             :         varinfo *sv;
     275             :         varinfo *dv;
     276      234346 :         jitdata *jd = state->jd;
     277             : 
     278      271157 :         for (i=0; i < n; ++i, ++srcvars, ++dstvars) {
     279       36811 :                 sv = VAR(*srcvars);
     280       36811 :                 dv = VAR(*dstvars);
     281             : 
     282       36811 :                 dv->type = sv->type;
     283       36811 :                 if (dv->type == TYPE_ADR) {
     284       29759 :                         typeinfo_t::clone(sv->typeinfo, dv->typeinfo);
     285             :                 }
     286             :         }
     287      234346 :         return true;
     288             : }
     289             : 
     290             : 
     291             : /* typecheck_merge_types *******************************************************
     292             : 
     293             :    Merge the types of the source variables into the destination variables.
     294             : 
     295             :    IN:
     296             :        state............current state of the verifier
     297             :            srcvars..........source variable indices
     298             :            dstvars..........destination variable indices
     299             :            n................number of variables
     300             : 
     301             :    RETURN VALUE:
     302             :        typecheck_TRUE...the destination variables have been modified
     303             :            typecheck_FALSE..the destination variables are unchanged
     304             :            typecheck_FAIL...an exception has been thrown
     305             : 
     306             : *******************************************************************************/
     307             : 
     308      191333 : typecheck_result typecheck_merge_types(verifier_state *state,
     309             :                                                                            s4 *srcvars,
     310             :                                                                            s4 *dstvars,
     311             :                                                                            s4 n)
     312             : {
     313             :         s4 i;
     314             :         varinfo *sv;
     315             :         varinfo *dv;
     316      191333 :         jitdata *jd = state->jd;
     317             :         typecheck_result r;
     318      191333 :         bool changed = false;
     319             : 
     320      298938 :         for (i=0; i < n; ++i, ++srcvars, ++dstvars) {
     321      107608 :                 sv = VAR(*srcvars);
     322      107608 :                 dv = VAR(*dstvars);
     323             : 
     324      107608 :                 if (dv->type != sv->type) {
     325           0 :                         exceptions_throw_verifyerror(state->m,"Stack type mismatch");
     326           0 :                         return typecheck_FAIL;
     327             :                 }
     328      107608 :                 if (dv->type == TYPE_ADR) {
     329      102631 :                         if (dv->typeinfo.is_primitive()) {
     330             :                                 /* dv has returnAddress type */
     331           0 :                                 if (!sv->typeinfo.is_primitive()) {
     332           0 :                                         exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
     333           0 :                                         return typecheck_FAIL;
     334             :                                 }
     335             :                         }
     336             :                         else {
     337             :                                 /* dv has reference type */
     338      102631 :                                 if (sv->typeinfo.is_primitive()) {
     339           0 :                                         exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
     340           0 :                                         return typecheck_FAIL;
     341             :                                 }
     342      102631 :                                 r = dv->typeinfo.merge(state->m, &(sv->typeinfo));
     343      102631 :                                 if (r == typecheck_FAIL)
     344           3 :                                         return r;
     345      102628 :                                 changed |= r;
     346             :                         }
     347             :                 }
     348             :         }
     349      191330 :         return (typecheck_result) changed;
     350             : }
     351             : 
     352             : 
     353             : /* typestate_merge *************************************************************
     354             : 
     355             :    Merge the types of one state into the destination state.
     356             : 
     357             :    IN:
     358             :        state............current state of the verifier
     359             :            dstvars..........indices of the destinations invars
     360             :            dstlocals........the destinations inlocals
     361             :            srcvars..........indices of the source's outvars
     362             :            srclocals........the source locals
     363             :            n................number of invars (== number of outvars)
     364             : 
     365             :    RETURN VALUE:
     366             :        typecheck_TRUE...destination state has been modified
     367             :            typecheck_FALSE..destination state has not been modified
     368             :            typecheck_FAIL...an exception has been thrown
     369             : 
     370             : *******************************************************************************/
     371             : 
     372      191333 : typecheck_result typestate_merge(verifier_state *state,
     373             :                                                  s4 *srcvars, varinfo *srclocals,
     374             :                                                  s4 *dstvars, varinfo *dstlocals,
     375             :                                                  s4 n)
     376             : {
     377      191333 :         bool changed = false;
     378             :         typecheck_result r;
     379             : 
     380             :         /* The stack is always merged. If there are returnAddresses on
     381             :          * the stack they are ignored in this step. */
     382             : 
     383      191333 :         r = typecheck_merge_types(state, srcvars, dstvars, n);
     384      191333 :         if (r == typecheck_FAIL)
     385           3 :                 return r;
     386      191330 :         changed |= r;
     387             : 
     388             :         /* merge the locals */
     389             : 
     390      191330 :         r = typevector_merge(state->m, dstlocals, srclocals, state->numlocals);
     391      191330 :         if (r == typecheck_FAIL)
     392           0 :                 return r;
     393      191330 :         return (typecheck_result) (changed | r);
     394             : }
     395             : 
     396             : 
     397             : /* typestate_reach *************************************************************
     398             : 
     399             :    Reach a destination block and propagate stack and local variable types
     400             : 
     401             :    IN:
     402             :        state............current state of the verifier
     403             :            destblock........destination basic block
     404             :            srcvars..........variable indices of the outvars to propagate
     405             :            srclocals........local variables to propagate
     406             :            n................number of srcvars
     407             : 
     408             :    OUT:
     409             :        state->repeat....set to true if the verifier must iterate again
     410             :                             over the basic blocks
     411             : 
     412             :    RETURN VALUE:
     413             :        true.............success
     414             :            false............an exception has been thrown
     415             : 
     416             : *******************************************************************************/
     417             : 
     418      424237 : bool typestate_reach(verifier_state *state,
     419             :                                          basicblock *destblock,
     420             :                                          s4 *srcvars, varinfo *srclocals, s4 n)
     421             : {
     422             :         varinfo *destloc;
     423      424237 :         bool changed = false;
     424             :         typecheck_result r;
     425             : 
     426             :         OLD_LOG1("reaching block L%03d",destblock->nr);
     427             :         TYPECHECK_COUNT(stat_reached);
     428             : 
     429      424237 :         destloc = destblock->inlocals;
     430             : 
     431      424237 :         if (destblock->state == basicblock::TYPECHECK_UNDEF) {
     432             :                 /* The destblock has never been reached before */
     433             : 
     434             :                 TYPECHECK_COUNT(stat_copied);
     435             :                 OLD_LOG1("block L%03d reached first time",destblock->nr);
     436             : 
     437      232904 :                 if (!typecheck_copy_types(state, srcvars, destblock->invars, n))
     438           0 :                         return false;
     439      232904 :                 typevector_copy_inplace(srclocals, destloc, state->numlocals);
     440      232904 :                 changed = true;
     441             :         }
     442             :         else {
     443             :                 /* The destblock has already been reached before */
     444             : 
     445             :                 TYPECHECK_COUNT(stat_merged);
     446             :                 OLD_LOG1("block L%03d reached before", destblock->nr);
     447             : 
     448             :                 r = typestate_merge(state, srcvars, srclocals,
     449      191333 :                                 destblock->invars, destblock->inlocals, n);
     450      191333 :                 if (r == typecheck_FAIL)
     451           3 :                         return false;
     452      191330 :                 changed = r;
     453             :                 TYPECHECK_COUNTIF(changed,stat_merging_changed);
     454             :         }
     455             : 
     456      424234 :         if (changed) {
     457             :                 OLD_LOG("changed!");
     458      247448 :                 destblock->state = basicblock::TYPECHECK_REACHED;
     459      247448 :                 if (destblock->nr <= state->bptr->nr) {
     460             :                         OLD_LOG("REPEAT!");
     461       10264 :                         state->repeat = true;
     462             :                 }
     463             :         }
     464      424234 :         return true;
     465             : }
     466             : 
     467             : 
     468             : /* typecheck_init_locals *******************************************************
     469             : 
     470             :    Initialize the local variables in the verifier state.
     471             : 
     472             :    IN:
     473             :        state............the current state of the verifier
     474             :            newthis..........if true, mark the instance in <init> methods as
     475             :                             uninitialized object.
     476             : 
     477             :    RETURN VALUE:
     478             :        true.............success,
     479             :            false............an exception has been thrown.
     480             : 
     481             : *******************************************************************************/
     482             : 
     483       86416 : bool typecheck_init_locals(verifier_state *state, bool newthis)
     484             : {
     485             :         int i;
     486             :         int varindex;
     487             :         varinfo *locals;
     488             :         varinfo *v;
     489       86416 :         jitdata *jd = state->jd;
     490       86416 :         int skip = 0;
     491             : 
     492       86416 :         locals = state->basicblocks[0].inlocals;
     493             : 
     494             :         /* allocate parameter descriptors if necessary */
     495             : 
     496       86416 :         state->m->parseddesc->params_from_paramtypes(state->m->flags);
     497             : 
     498             :         /* pre-initialize variables as TYPE_VOID */
     499             : 
     500       86416 :         i = state->numlocals;
     501       86416 :         v = locals;
     502      393775 :         while (i--) {
     503      220943 :                 v->type = TYPE_VOID;
     504      220943 :                 v++;
     505             :         }
     506             : 
     507             :     /* if this is an instance method initialize the "this" ref type */
     508             : 
     509       86416 :     if (!(state->m->flags & ACC_STATIC)) {
     510       67593 :                 varindex = jd->local_map[5*0 + TYPE_ADR];
     511       67593 :                 if (varindex != jitdata::UNUSED) {
     512       63512 :                         if (state->validlocals < 1)
     513           0 :                                 TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
     514       63512 :                         v = locals + varindex;
     515       63512 :                         v->type = TYPE_ADR;
     516       88881 :                         if (state->initmethod && newthis)
     517       25369 :                                 v->typeinfo.init_newobject(NULL);
     518             :                         else
     519       38143 :                                 v->typeinfo.init_class(state->m->clazz);
     520             :                 }
     521             : 
     522       67593 :                 skip = 1;
     523             :     }
     524             : 
     525             :     OLD_LOG("'this' argument set.\n");
     526             : 
     527             :     /* the rest of the arguments and the return type */
     528             : 
     529       86416 :     if (!typeinfo_init_varinfos_from_methoddesc(locals, state->m->parseddesc,
     530             :                                                                                           state->validlocals,
     531             :                                                                                           skip, /* skip 'this' pointer */
     532             :                                                                                           jd->local_map,
     533             :                                                                                           &state->returntype))
     534           0 :                 return false;
     535             : 
     536             :     OLD_LOG("Arguments set.\n");
     537       86416 :         return true;
     538             : }
     539             : 
     540             : 
     541             : /*
     542             :  * These are local overrides for various environment variables in Emacs.
     543             :  * Please do not remove this and leave it at the end of the file, where
     544             :  * Emacs will automagically detect them.
     545             :  * ---------------------------------------------------------------------
     546             :  * Local variables:
     547             :  * mode: c++
     548             :  * indent-tabs-mode: t
     549             :  * c-basic-offset: 4
     550             :  * tab-width: 4
     551             :  * End:
     552             :  * vim:noexpandtab:sw=4:ts=4:
     553             :  */

Generated by: LCOV version 1.11