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

          Line data    Source code
       1             : /* src/vm/jit/verify/typecheck-stackbased.c - stack-based verifier
       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             : 
      28             : #include <assert.h>
      29             : 
      30             : #include "vm/method.hpp"
      31             : #include "vm/types.hpp"
      32             : 
      33             : #include "mm/memory.hpp"
      34             : #include "mm/dumpmemory.hpp"
      35             : 
      36             : #include "vm/array.hpp"
      37             : #include "vm/descriptor.hpp"
      38             : #include "vm/exceptions.hpp"
      39             : #include "vm/field.hpp"
      40             : #include "vm/global.hpp"
      41             : #include "vm/globals.hpp"
      42             : #include "vm/primitive.hpp"
      43             : 
      44             : #include "vm/jit/builtin.hpp"
      45             : #include "vm/jit/parse.hpp"
      46             : #include "vm/jit/show.hpp"
      47             : #include "vm/jit/stack.hpp"
      48             : #include "vm/jit/ir/instruction.hpp"
      49             : #include "vm/jit/verify/typecheck-common.hpp"
      50             : 
      51             : 
      52             : /* this #if runs over the whole file: */
      53             : #if defined(ENABLE_VERIFIER)
      54             : 
      55             : typedef typedescriptor_t verifier_slot_t;
      56             : 
      57             : #if defined(TYPECHECK_VERBOSE)
      58             : static void typecheck_stackbased_show_state(verifier_state *state,
      59             :                                                                                         typedescriptor *stack,
      60             :                                                                                         typedescriptor *stackfloor,
      61             :                                                                                         bool showins);
      62             : #endif
      63             : 
      64             : 
      65             : #define CHECK_STACK_DEPTH(d)                                         \
      66             :     if (((u1*)stack - (u1*)stackfloor)                               \
      67             :             < (((d)-1) * (int)sizeof(verifier_slot_t)))              \
      68             :         goto throw_stack_underflow;
      69             : 
      70             : /* XXX don't need to check against ACONST for every ICMD */
      71             : #define CHECK_STACK_SPACE(d)                                         \
      72             :     if (((u1*)STATE->stackceiling - (u1*)stack)                      \
      73             :             < (((d)+1) * (int)sizeof(verifier_slot_t)))              \
      74             :         if (STATE->iptr->opc != ICMD_ACONST                          \
      75             :                 || INSTRUCTION_MUST_CHECK(STATE->iptr))              \
      76             :             goto throw_stack_overflow;
      77             : 
      78             : #define CHECK_STACK_TYPE(s, t)                                       \
      79             :     if ((s).type != (t))                                             \
      80             :         goto throw_stack_type_error;
      81             : 
      82             : /* XXX inefficient */
      83             : #define CHECK_LOCAL_TYPE(index, t)                                   \
      84             :     do {                                                             \
      85             :         if (state.locals[(index)].type != (t))                       \
      86             :             goto throw_local_type_error;                             \
      87             :         if (STATE->topjsr)                                           \
      88             :             STATE->topjsr->usedlocals[(index)] = 1;                  \
      89             :         if (STATE->topjsr && IS_2_WORD_TYPE(t))                      \
      90             :             STATE->topjsr->usedlocals[(index) + 1] = 1;              \
      91             :     } while(0)
      92             : 
      93             : /* XXX inefficient */
      94             : #define STORE_LOCAL(t, index)                                        \
      95             :     do {                                                             \
      96             :         state.locals[(index)].type = (t);                            \
      97             :         if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
      98             :             state.locals[(index-1)].type = TYPE_VOID;                \
      99             :         if (STATE->topjsr)                                           \
     100             :             STATE->topjsr->usedlocals[(index)] = 1;                  \
     101             :     } while (0)
     102             : 
     103             : /* XXX inefficient */
     104             : #define STORE_LOCAL_2_WORD(t, index)                                 \
     105             :     do {                                                             \
     106             :         STORE_LOCAL(t, index);                                       \
     107             :         state.locals[(index)+1].type = TYPE_VOID;                    \
     108             :         if (STATE->topjsr)                                           \
     109             :             STATE->topjsr->usedlocals[(index)] = 1;                  \
     110             :     } while (0)
     111             : 
     112             : #define VERIFY_ERROR_ret(msg,ret)                                    \
     113             :     do {                                                             \
     114             :         OLD_LOG1("VerifyError: %s", msg);                                \
     115             :         exceptions_throw_verifyerror(STATE->m, msg);                 \
     116             :         return ret;                                                  \
     117             :     } while (0)
     118             : 
     119             : #define VERIFY_ERROR(msg) VERIFY_ERROR_ret(msg,false)
     120             : 
     121             : #define IS_CAT1(slot)                                                \
     122             :     ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
     123             : 
     124             : #define IS_CAT2(slot)                                                \
     125             :     ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
     126             : 
     127             : #define CHECK_CAT1(slot)                                             \
     128             :     do {                                                             \
     129             :         if (!IS_CAT1(slot))                                          \
     130             :             goto throw_stack_category_error;                         \
     131             :     } while (0)
     132             : 
     133             : #define CHECK_CAT2(slot)                                             \
     134             :     do {                                                             \
     135             :         if (!IS_CAT2(slot))                                          \
     136             :             goto throw_stack_category_error;                         \
     137             :     } while (0)
     138             : 
     139             : #define COPY_SLOT(s, d)                                              \
     140             :     do { (d) = (s); } while (0)
     141             : 
     142             : #define REACH_BLOCK(target)                                          \
     143             :     do {                                                             \
     144             :         if (!typecheck_stackbased_reach(STATE, (target), stack,      \
     145             :                     (stack - stackfloor) + 1))                       \
     146             :             return false;                                            \
     147             :     } while (0)
     148             : 
     149             : #define REACH(target)                                                \
     150             :     do {                                                             \
     151             :         REACH_BLOCK((target).block);                                 \
     152             :     } while (0)
     153             : 
     154             : #undef TYPECHECK_INT
     155             : #undef TYPECHECK_LNG
     156             : #undef TYPECHECK_FLT
     157             : #undef TYPECHECK_DBL
     158             : #undef TYPECHECK_ADR
     159             : 
     160             : /* XXX should reuse typevector code */
     161           0 : static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
     162             :                                                                                                                   typedescriptor_t *dst,
     163             :                                                                                                                   typedescriptor_t *y,
     164             :                                                                                                                   int size)
     165             : {
     166           0 :         bool changed = false;
     167             :         typecheck_result r;
     168             : 
     169           0 :         typedescriptor_t *a = dst;
     170           0 :         typedescriptor_t *b = y;
     171           0 :         while (size--) {
     172           0 :                 if (a->type != TYPE_VOID && a->type != b->type) {
     173           0 :                         a->type = TYPE_VOID;
     174           0 :                         changed = true;
     175             :                 }
     176           0 :                 else if (a->type == TYPE_ADR) {
     177           0 :                         if (a->typeinfo.is_primitive()) {
     178             :                                 /* 'a' is a returnAddress */
     179           0 :                                 if (!b->typeinfo.is_primitive() || (a->typeinfo.returnaddress() != b->typeinfo.returnaddress()))
     180             :                                 {
     181           0 :                                         a->type = TYPE_VOID;
     182           0 :                                         changed = true;
     183             :                                 }
     184             :                         }
     185             :                         else {
     186             :                                 /* 'a' is a reference */
     187           0 :                                 if (b->typeinfo.is_primitive()) {
     188           0 :                                         a->type = TYPE_VOID;
     189           0 :                                         changed = true;
     190             :                                 }
     191             :                                 else {
     192             :                                         /* two reference types are merged. There cannot be */
     193             :                                         /* a merge error. In the worst case we get j.l.O.  */
     194           0 :                                         r = a->typeinfo.merge(m, &(b->typeinfo));
     195           0 :                                         if (r == typecheck_FAIL)
     196           0 :                                                 return r;
     197           0 :                                         changed |= r;
     198             :                                 }
     199             :                         }
     200             :                 }
     201           0 :                 a++;
     202           0 :                 b++;
     203             :         }
     204           0 :         return (typecheck_result) changed;
     205             : }
     206             : 
     207           0 : static typecheck_result typecheck_stackbased_merge(verifier_state *state,
     208             :                                                                                                    basicblock *destblock,
     209             :                                                                                                    typedescriptor_t *stack,
     210             :                                                                                                    s4 stackdepth)
     211             : {
     212             :         s4 i;
     213             :         s4 destidx;
     214             :         typedescriptor_t *stackfloor;
     215             :         typedescriptor_t *sp;
     216             :         typedescriptor_t *dp;
     217             :         typecheck_result r;
     218           0 :         bool changed = false;
     219             : 
     220           0 :         destidx = destblock->nr;
     221             : 
     222           0 :         if (stackdepth != state->indepth[destidx]) {
     223           0 :                 exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
     224           0 :                 return typecheck_FAIL;
     225             :         }
     226             : 
     227           0 :         stackfloor = stack - (stackdepth - 1);
     228             : 
     229           0 :         sp = stackfloor;
     230           0 :         dp = state->startstack + (destidx * state->m->maxstack);
     231             : 
     232           0 :         for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
     233           0 :                 if (sp->type != dp->type) {
     234           0 :                         exceptions_throw_verifyerror(state->m, "Mismatched stack types");
     235           0 :                         return typecheck_FAIL;
     236             :                 }
     237           0 :                 if (dp->type == TYPE_ADR) {
     238           0 :                         if (dp->typeinfo.is_primitive()) {
     239             :                                 /* dp has returnAddress type */
     240           0 :                                 if (sp->typeinfo.is_primitive()) {
     241           0 :                                         if (dp->typeinfo.returnaddress() != sp->typeinfo.returnaddress()) {
     242           0 :                                                 exceptions_throw_verifyerror(state->m, "Mismatched stack types");
     243           0 :                                                 return typecheck_FAIL;
     244             :                                         }
     245             :                                 }
     246             :                                 else {
     247           0 :                                         exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
     248           0 :                                         return typecheck_FAIL;
     249             :                                 }
     250             :                         }
     251             :                         else {
     252             :                                 /* dp has reference type */
     253           0 :                                 if (sp->typeinfo.is_primitive()) {
     254           0 :                                         exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
     255           0 :                                         return typecheck_FAIL;
     256             :                                 }
     257           0 :                                 r = dp->typeinfo.merge(state->m, &(sp->typeinfo));
     258           0 :                                 if (r == typecheck_FAIL)
     259           0 :                                         return r;
     260           0 :                                 changed |= r;
     261             :                         }
     262             :                 }
     263             :         }
     264             : 
     265           0 :         dp = state->startlocals + (destidx * state->numlocals);
     266           0 :         r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
     267           0 :         if (r == typecheck_FAIL)
     268           0 :                 return r;
     269           0 :         changed |= r;
     270             : 
     271           0 :         return (typecheck_result) changed;
     272             : }
     273             : 
     274           0 : static bool typecheck_stackbased_reach(verifier_state *state,
     275             :                                                                            basicblock *destblock,
     276             :                                                                            typedescriptor_t *stack,
     277             :                                                                            s4 stackdepth)
     278             : {
     279           0 :         bool changed = false;
     280             :         typecheck_result r;
     281             : 
     282           0 :         assert(destblock);
     283             : 
     284           0 :         if (destblock->state == basicblock::TYPECHECK_UNDEF) {
     285             :                 /* The destblock has never been reached before */
     286             : 
     287             :                 TYPECHECK_COUNT(stat_copied);
     288             :                 OLD_LOG1("block L%03d reached first time",destblock->nr); OLD_LOGSTR("\t");
     289             :                 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
     290             : 
     291           0 :                 state->indepth[destblock->nr] = stackdepth;
     292             : 
     293             :                 MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
     294             :                           stack - (stackdepth - 1),
     295             :                           typedescriptor_t,
     296           0 :                           stackdepth);
     297             : 
     298             :                 MCOPY(state->startlocals + (destblock->nr * state->numlocals),
     299             :                           state->locals,
     300             :                           typedescriptor_t,
     301           0 :                           state->numlocals);
     302             : 
     303           0 :                 changed = true;
     304             :         }
     305             :         else {
     306             :                 /* The destblock has already been reached before */
     307             : 
     308             :                 TYPECHECK_COUNT(stat_merged);
     309             :                 OLD_LOG1("block L%03d reached before", destblock->nr); OLD_LOGSTR("\t");
     310             :                 DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
     311             : 
     312           0 :                 r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
     313           0 :                 if (r == typecheck_FAIL)
     314           0 :                         return false;
     315           0 :                 changed = r;
     316             : 
     317             :                 TYPECHECK_COUNTIF(changed,stat_merging_changed);
     318             :         }
     319             : 
     320           0 :         if (changed) {
     321             :                 OLD_LOG("\tchanged!");
     322           0 :                 destblock->state = basicblock::TYPECHECK_REACHED;
     323             :                 /* XXX is this check ok? */
     324           0 :                 if (destblock->nr <= state->bptr->nr) {
     325             :                         OLD_LOG("\tREPEAT!");
     326           0 :                         state->repeat = true;
     327             :                 }
     328             :         }
     329           0 :         return true;
     330             : }
     331             : 
     332             : 
     333             : /* typecheck_stackbased_verify_fieldaccess *************************************
     334             : 
     335             :    Verify an ICMD_{GET,PUT}{STATIC,FIELD}
     336             : 
     337             :    IN:
     338             :        state............the current state of the verifier
     339             :            instance.........the instance slot, or NULL
     340             :            value............the value slot, or NULL
     341             :            stack............stack after popping the arguments
     342             : 
     343             :    RETURN VALUE:
     344             :        stack pointer....successful verification,
     345             :            NULL.............an exception has been thrown.
     346             : 
     347             : *******************************************************************************/
     348             : 
     349           0 : static typedescriptor_t *typecheck_stackbased_verify_fieldaccess(
     350             :                 verifier_state *state,
     351             :                 typedescriptor_t *instance,
     352             :                 typedescriptor_t *value,
     353             :                 typedescriptor_t *stack)
     354             : {
     355             :         //jitdata *jd;
     356             : 
     357             :         //jd = state->jd;
     358             : 
     359             : #define TYPECHECK_STACKBASED
     360             : #define EXCEPTION  do { return NULL; } while (0)
     361             : #define STATE  state
     362             : #undef  VERIFY_ERROR
     363             : #define VERIFY_ERROR(msg) VERIFY_ERROR_ret(msg,NULL)
     364             : #include <typecheck-fields.inc>
     365             : #undef  EXCEPTION
     366             : #undef  STATE
     367             : #undef  TYPECHECK_STACKBASED
     368             : #undef  VERIFY_ERROR
     369             : #define VERIFY_ERROR(msg) VERIFY_ERROR_ret(msg,false)
     370             : 
     371           0 :         return stack;
     372             : 
     373             : throw_stack_overflow:
     374             :         OLD_LOG("STACK OVERFLOW!");
     375           0 :         exceptions_throw_verifyerror(state->m, "Stack size too large");
     376           0 :         return NULL;
     377             : }
     378             : 
     379           0 : static bool typecheck_stackbased_verify_invocation(verifier_state *state,
     380             :                                                                                                    typedescriptor_t *stack,
     381             :                                                                                                    typedescriptor_t *stackfloor)
     382             : {
     383             :         s4 paramslots;
     384             :         methoddesc *md;
     385             :         typedescriptor_t *dv;
     386             : 
     387             :         /* check stack depth */
     388             : 
     389             :         /* XXX parse params */
     390             : 
     391           0 :         INSTRUCTION_GET_METHODDESC(state->iptr, md);
     392             : 
     393           0 :         paramslots = md->paramslots;
     394             : 
     395           0 :         if ((stack - stackfloor) + 1 < paramslots) {
     396             :                 exceptions_throw_verifyerror(state->m, 
     397           0 :                                 "Trying to pop operand of an empty stack");
     398           0 :                 return false;
     399             :         }
     400             : 
     401           0 :         dv = stack - (paramslots - 1);
     402             : 
     403             : #define TYPECHECK_STACKBASED
     404             : #define OP1   dv
     405             : #include <typecheck-invoke.inc>
     406             : #undef  OP1
     407             : #undef  TYPECHECK_STACKBASED
     408             : 
     409           0 :         return true;
     410             : }
     411             : 
     412           0 : static bool typecheck_stackbased_verify_builtin(verifier_state *state,
     413             :                                                                                                 typedescriptor_t *stack,
     414             :                                                                                                 typedescriptor_t *stackfloor)
     415             : {
     416             :         s4 paramslots;
     417             :         typedescriptor_t *dv;
     418             : 
     419             :         /* check stack depth */
     420             : 
     421             :         /* XXX parse params */
     422             : 
     423           0 :         paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
     424             : 
     425           0 :         if ((stack - stackfloor) + 1 < paramslots) {
     426             :                 exceptions_throw_verifyerror(state->m, 
     427           0 :                                 "Trying to pop operand of an empty stack");
     428           0 :                 return false;
     429             :         }
     430             : 
     431           0 :         dv = stack - (paramslots - 1);
     432             : 
     433             : #define TYPECHECK_STACKBASED
     434             : #define OP1   dv
     435             : #define TYPECHECK_INT(s)  CHECK_STACK_TYPE(*(s), TYPE_INT)
     436             : #define TYPECHECK_ADR(s)  CHECK_STACK_TYPE(*(s), TYPE_ADR)
     437             : #define TYPECHECK_LNG(s)  CHECK_STACK_TYPE(*(s), TYPE_LNG)
     438             : #define TYPECHECK_FLT(s)  CHECK_STACK_TYPE(*(s), TYPE_FLT)
     439             : #define TYPECHECK_DBL(s)  CHECK_STACK_TYPE(*(s), TYPE_DBL)
     440             : #include <typecheck-builtins.inc>
     441             : #undef  OP1
     442             : #undef  TYPECHECK_STACKBASED
     443             : 
     444           0 :         return true;
     445             : 
     446             : throw_stack_type_error:
     447           0 :         exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
     448           0 :         return false;
     449             : }
     450             : 
     451           0 : static bool typecheck_stackbased_multianewarray(verifier_state *state,
     452             :                                                                                                 typedescriptor_t *stack,
     453             :                                                                                                 typedescriptor_t *stackfloor)
     454             : {
     455             :         /* XXX recombine with verify_multianewarray */
     456             : 
     457             :         classinfo *arrayclass;
     458             :         arraydescriptor *desc;
     459             :         s4 i;
     460             :         typedescriptor_t *sp;
     461             :         typedescriptor_t *dst;
     462             : 
     463             :         /* destination slot */
     464             : 
     465           0 :         i = state->iptr->s1.argcount;
     466             : 
     467           0 :         dst = stack - (i-1);
     468             : 
     469             :         /* check the array lengths on the stack */
     470             : 
     471           0 :         if ((stack - stackfloor) + 1 < i) {
     472             :                 exceptions_throw_verifyerror(state->m, 
     473           0 :                                 "Trying to pop operand of an empty stack");
     474           0 :                 return false;
     475             :         }
     476             : 
     477           0 :         if (i < 1)
     478           0 :                 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
     479             : 
     480           0 :         for (sp = dst; sp <= stack; ++sp) {
     481           0 :                 if (sp->type != TYPE_INT) {
     482           0 :                         exceptions_throw_verifyerror_for_stack(state->m, TYPE_INT);
     483           0 :                         return false;
     484             :                 }
     485             :         }
     486             : 
     487             :         /* check array descriptor */
     488             : 
     489           0 :         if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
     490             :                 /* the array class reference has already been resolved */
     491           0 :                 arrayclass = state->iptr->sx.s23.s3.c.cls;
     492           0 :                 if (!arrayclass)
     493           0 :                         TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
     494           0 :                 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
     495           0 :                         TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
     496           0 :                 if (desc->dimension < state->iptr->s1.argcount)
     497           0 :                         TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
     498             : 
     499             :                 /* set the array type of the result */
     500           0 :                 dst->typeinfo.init_class(arrayclass);
     501             :         }
     502             :         else {
     503             :                 const char *p;
     504             :                 constant_classref *cr;
     505             : 
     506             :                 /* the array class reference is still unresolved */
     507             :                 /* check that the reference indicates an array class of correct dimension */
     508           0 :                 cr = state->iptr->sx.s23.s3.c.ref;
     509           0 :                 i = 0;
     510           0 :                 p = cr->name.begin();
     511           0 :                 while (p[i] == '[')
     512           0 :                         i++;
     513             :                 /* { the dimension of the array class == i } */
     514           0 :                 if (i < 1)
     515           0 :                         TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
     516           0 :                 if (i < state->iptr->s1.argcount)
     517           0 :                         TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
     518             : 
     519             :                 /* set the array type of the result */
     520           0 :                 if (!dst->typeinfo.init_class(cr))
     521           0 :                         return false;
     522             :         }
     523             : 
     524             :         /* everything ok */
     525           0 :         return true;
     526             : 
     527             : }
     528             : 
     529           0 : static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr,
     530             :                                                                                                 basicblock *bptr)
     531             : {
     532             :         typecheck_jsr_caller_t *jc;
     533             : 
     534           0 :         for (jc = jsr->callers; jc; jc = jc->next)
     535           0 :                 if (jc->callblock == bptr)
     536           0 :                         return;
     537             : 
     538           0 :         jc = (typecheck_jsr_caller_t*) DumpMemory::allocate(sizeof(typecheck_jsr_caller_t));
     539           0 :         jc->next = jsr->callers;
     540           0 :         jc->callblock = bptr;
     541           0 :         jsr->callers = jc;
     542             : }
     543             : 
     544           0 : static typedescriptor_t *typecheck_stackbased_jsr(verifier_state *state,
     545             :                                                                                                 typedescriptor_t *stack,
     546             :                                                                                                 typedescriptor_t *stackfloor)
     547             : {
     548             :         typecheck_jsr_t *jsr;
     549             :         basicblock *tbptr;
     550             :         //jitdata *jd;
     551             :         s4 i;
     552             : 
     553             :         //jd = state->jd;
     554             : 
     555           0 :         tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
     556           0 :         jsr = state->jsrinfos[tbptr->nr];
     557             : 
     558           0 :         if (jsr && tbptr->state == basicblock::FINISHED) {
     559             : 
     560             :                 OLD_LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
     561           0 :                 if (jsr->active) {
     562           0 :                         exceptions_throw_verifyerror(state->m, "Recursive JSR");
     563           0 :                         return NULL;
     564             :                 }
     565             : 
     566           0 :                 assert(jsr->callers);
     567           0 :                 assert(jsr->callers->callblock);
     568             : 
     569             :                 /* copy the stack of the RET edge */
     570             : 
     571           0 :                 MCOPY(stackfloor, jsr->retstack, typedescriptor_t, jsr->retdepth);
     572           0 :                 stack = stackfloor + (jsr->retdepth - 1);
     573             : 
     574             :                 /* copy variables that were used in the subroutine from the RET edge */
     575             : 
     576           0 :                 for (i=0; i<state->numlocals; ++i)
     577           0 :                         if (jsr->usedlocals[i])
     578           0 :                                 state->locals[i] = jsr->retlocals[i];
     579             : 
     580             :                 /* reach the following block */
     581             : 
     582           0 :                 if (!typecheck_stackbased_reach(state, state->bptr->next, stack, 
     583             :                                         (stack - stackfloor) + 1))
     584           0 :                         return NULL;
     585             :         }
     586             :         else {
     587           0 :                 if (!jsr) {
     588             :                         OLD_LOG1("first JSR to block L%03d", tbptr->nr);
     589             : 
     590           0 :                         jsr = (typecheck_jsr_t*) DumpMemory::allocate(sizeof(typecheck_jsr_t));
     591           0 :                         state->jsrinfos[tbptr->nr] = jsr;
     592           0 :                         jsr->callers = NULL;
     593           0 :                         jsr->blockflags = (char*) DumpMemory::allocate(sizeof(char) * state->basicblockcount);
     594           0 :                         jsr->retblock = NULL;
     595           0 :                         jsr->start = tbptr;
     596           0 :                         jsr->usedlocals = (char*) DumpMemory::allocate(sizeof(char) * state->numlocals);
     597           0 :                         MZERO(jsr->usedlocals, char, state->numlocals);
     598           0 :                         jsr->retlocals = (typedescriptor_t*) DumpMemory::allocate(sizeof(typedescriptor_t) * state->numlocals);
     599           0 :                         jsr->retstack = (typedescriptor_t*) DumpMemory::allocate(sizeof(typedescriptor_t) * state->m->maxstack);
     600           0 :                         jsr->retdepth = 0;
     601             :                 }
     602             :                 else {
     603             :                         OLD_LOG1("re-analysing JSR to block L%03d", tbptr->nr);
     604             :                 }
     605             : 
     606           0 :                 jsr->active = true;
     607           0 :                 jsr->next = state->topjsr;
     608           0 :                 state->topjsr = jsr;
     609             : 
     610           0 :                 assert(state->iptr->sx.s23.s3.jsrtarget.block->state == basicblock::TYPECHECK_REACHED);
     611             : 
     612           0 :                 tbptr->state = basicblock::FINISHED;
     613             : 
     614           0 :                 for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
     615           0 :                         jsr->blockflags[tbptr->nr] = tbptr->state;
     616             : 
     617           0 :                         if (tbptr->state == basicblock::TYPECHECK_REACHED)
     618           0 :                                 tbptr->state = basicblock::FINISHED;
     619             :                 }
     620             : 
     621           0 :                 state->iptr->sx.s23.s3.jsrtarget.block->state = basicblock::TYPECHECK_REACHED;
     622             :         }
     623             : 
     624             :         /* register this block as a caller, if not already done */
     625             : 
     626           0 :         typecheck_stackbased_add_jsr_caller(jsr, state->bptr);
     627             : 
     628           0 :         return stack;
     629             : }
     630             : 
     631           0 : static bool typecheck_stackbased_ret(verifier_state *state,
     632             :                                                                          typedescriptor_t *stack,
     633             :                                                                          typedescriptor_t *stackfloor)
     634             : {
     635             :         basicblock *tbptr;
     636             :         typecheck_jsr_caller_t *jsrcaller;
     637             :         typecheck_jsr_t *jsr;
     638             :         s4 i;
     639             : 
     640             :         /* get the subroutine we are RETurning from */
     641             : 
     642           0 :         tbptr = (basicblock*) state->locals[state->iptr->s1.varindex].typeinfo.returnaddress();
     643           0 :         if (tbptr == NULL) {
     644           0 :                 exceptions_throw_verifyerror(state->m, "Illegal RET");
     645           0 :                 return false;
     646             :         }
     647             : 
     648             :         OLD_LOG1("RET from subroutine L%03d", tbptr->nr);
     649           0 :         jsr = state->jsrinfos[tbptr->nr];
     650           0 :         assert(jsr);
     651             : 
     652             :         /* check against recursion */
     653             : 
     654           0 :         if (!jsr->active) {
     655           0 :                 exceptions_throw_verifyerror(state->m, "RET outside of local subroutine");
     656           0 :                 return false;
     657             :         }
     658             : 
     659             :         /* check against multiple RETs for one subroutine */
     660             : 
     661           0 :         if (jsr->retblock && jsr->retblock != state->bptr) {
     662           0 :                 exceptions_throw_verifyerror(state->m, "Multiple RETs from local subroutine");
     663           0 :                 return false;
     664             :         }
     665             : 
     666             :         /* store data-flow of the RET edge */
     667             : 
     668           0 :         jsr->retblock = state->bptr;
     669           0 :         jsr->retdepth = (stack - stackfloor) + 1;
     670           0 :         MCOPY(jsr->retstack, stackfloor, typedescriptor_t, jsr->retdepth);
     671           0 :         MCOPY(jsr->retlocals, state->locals, typedescriptor_t, state->numlocals);
     672             : 
     673             :         /* invalidate the returnAddress used by this RET */
     674             :         /* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
     675             : 
     676           0 :         for (i=0; i<state->numlocals; ++i) {
     677           0 :                 typedescriptor_t *lc = &(jsr->retlocals[i]);
     678           0 :                 if (lc->is_returnaddress())
     679           0 :                         if (lc->typeinfo.returnaddress() == tbptr) {
     680             :                                 OLD_LOG1("invalidating returnAddress in local %d", i);
     681           0 :                                 lc->typeinfo.init_returnaddress(NULL);
     682             :                         }
     683             :         }
     684             : 
     685             :         /* touch all callers of the subroutine, so they are analysed again */
     686             : 
     687           0 :         for (jsrcaller = jsr->callers; jsrcaller != NULL; jsrcaller = jsrcaller->next) {
     688           0 :                 tbptr = jsrcaller->callblock;
     689             :                 OLD_LOG1("touching caller L%03d from RET", tbptr->nr);
     690           0 :                 assert(jsr->blockflags[tbptr->nr] >= basicblock::FINISHED);
     691           0 :                 jsr->blockflags[tbptr->nr] = basicblock::TYPECHECK_REACHED; /* XXX repeat? */
     692             :         }
     693             : 
     694           0 :         return true;
     695             : }
     696             : 
     697           0 : bool typecheck_stackbased(jitdata *jd)
     698             : {
     699             :         register verifier_slot_t *stack;
     700             :         verifier_slot_t *stackfloor;
     701             :         s4 len;
     702             :         methoddesc *md;
     703             :         bool maythrow;
     704             :         bool superblockend;
     705             :         verifier_slot_t temp;
     706             :         branch_target_t *table;
     707             :         lookup_target_t *lookup;
     708             :         s4 i;
     709             :         typecheck_result r;
     710             :         verifier_slot_t *dst;
     711             :         verifier_state state;
     712             :         basicblock *tbptr;
     713             :         exception_entry *ex;
     714             :         typedescriptor_t exstack;
     715           0 :         s4 skip = 0;
     716             : 
     717             :         DOLOG( show_method(jd, SHOW_PARSE); );
     718             : 
     719             :         /* initialize verifier state */
     720             : 
     721           0 :         state.jd = jd;
     722           0 :         state.m = jd->m;
     723           0 :         state.cd = jd->cd;
     724           0 :         state.basicblocks = jd->basicblocks;
     725           0 :         state.basicblockcount = jd->basicblockcount;
     726           0 :         state.topjsr = NULL;
     727             : #   define STATE (&state)
     728             : 
     729             :         /* check that the basicblock numbers are valid */
     730             : 
     731             : #if !defined(NDEBUG)
     732           0 :         jit_check_basicblock_numbers(jd);
     733             : #endif
     734             : 
     735             :         /* check if this method is an instance initializer method */
     736             : 
     737           0 :     state.initmethod = (state.m->name == utf8::init);
     738             : 
     739             :         /* allocate parameter descriptors if necessary */
     740             : 
     741           0 :         state.m->parseddesc->params_from_paramtypes(state.m->flags);
     742             : 
     743             :         /* allocate the stack buffers */
     744             : 
     745           0 :         stackfloor = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * (state.m->maxstack + 1));
     746           0 :         state.stackceiling = stackfloor + state.m->maxstack;
     747           0 :         stack = stackfloor - 1;
     748           0 :         state.indepth = (s4*) DumpMemory::allocate(sizeof(s4) * state.basicblockcount);
     749           0 :         state.startstack = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * state.m->maxstack * state.basicblockcount);
     750             : 
     751             :         /* allocate the local variables buffers */
     752             : 
     753           0 :         state.numlocals = state.m->maxlocals;
     754           0 :         state.validlocals = state.m->maxlocals;
     755           0 :     if (state.initmethod)
     756           0 :                 state.numlocals++; /* extra marker variable */
     757             : 
     758           0 :         state.locals = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * state.numlocals);
     759           0 :         state.startlocals = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * state.numlocals * state.basicblockcount);
     760             : 
     761             :     /* allocate the buffer of active exception handlers */
     762             : 
     763           0 :     state.handlers = (exception_entry**) DumpMemory::allocate(sizeof(exception_entry*) * (state.jd->exceptiontablelength + 1));
     764             : 
     765             :     /* initialize instack of exception handlers */
     766             : 
     767           0 :         exstack.type = TYPE_ADR;
     768           0 :         exstack.typeinfo.init_class(class_java_lang_Throwable); /* changed later */
     769             : 
     770             :     OLD_LOG("Exception handler stacks set.\n");
     771             : 
     772             :         /* initialize jsr info buffer */
     773             : 
     774           0 :         state.jsrinfos = (typecheck_jsr_t**) DumpMemory::allocate(sizeof(typecheck_jsr_t*) * state.basicblockcount);
     775           0 :         MZERO(state.jsrinfos, typecheck_jsr_t *, state.basicblockcount);
     776             : 
     777             :         /* initialize stack of first block */
     778             : 
     779           0 :         state.indepth[0] = 0;
     780             : 
     781             :         /* initialize locals of first block */
     782             : 
     783             :     /* if this is an instance method initialize the "this" ref type */
     784             : 
     785           0 :     if (!(state.m->flags & ACC_STATIC)) {
     786           0 :                 if (state.validlocals < 1)
     787           0 :                         VERIFY_ERROR("Not enough local variables for method arguments");
     788           0 :                 dst = state.startlocals;
     789           0 :                 dst->type = TYPE_ADR;
     790           0 :                 if (state.initmethod)
     791           0 :                         dst->typeinfo.init_newobject(NULL);
     792             :                 else
     793           0 :                         dst->typeinfo.init_class(state.m->clazz);
     794             : 
     795           0 :                 skip = 1;
     796             :     }
     797             : 
     798             :     OLD_LOG("'this' argument set.\n");
     799             : 
     800             :         len = typedescriptors_init_from_methoddesc(state.startlocals + skip,
     801             :                         state.m->parseddesc,
     802           0 :                         state.validlocals, true, skip, &state.returntype);
     803           0 :         if (len < 0)
     804           0 :                 return false;
     805             : 
     806             :         /* set remaining locals to void */
     807             : 
     808           0 :         for (i = skip + len; i<state.numlocals; ++i)
     809           0 :                 state.startlocals[i].type = TYPE_VOID;
     810             : 
     811             :         /* initialize block flags */
     812             : 
     813           0 :         typecheck_init_state(&state, basicblock::UNDEF);
     814             : 
     815             :         /* iterate until fixpoint reached */
     816             : 
     817           0 :         do {
     818             : 
     819           0 :                 state.repeat = false;
     820             : 
     821             :                 /* iterate over the basic blocks */
     822             : 
     823           0 :                 for (state.bptr = state.basicblocks; state.bptr != NULL; state.bptr = state.bptr->next) {
     824             : 
     825           0 :                         if (state.bptr->state != basicblock::TYPECHECK_REACHED)
     826           0 :                                 continue;
     827             : 
     828             :                         DOLOG( show_basicblock(jd, state.bptr, SHOW_PARSE); );
     829             : 
     830             :                         /* mark this block as analysed */
     831             : 
     832           0 :                         state.bptr->state = basicblock::FINISHED;
     833             : 
     834             :                         /* determine the active exception handlers for this block */
     835             :                         /* XXX could use a faster algorithm with sorted lists or  */
     836             :                         /* something?                                             */
     837             :                         /* XXX reuse code from variables based verifer? */
     838           0 :                         len = 0;
     839           0 :                         for (ex = STATE->jd->exceptiontable; ex ; ex = ex->down) {
     840           0 :                                 if ((ex->start->nr <= STATE->bptr->nr) && (ex->end->nr > STATE->bptr->nr)) {
     841             :                                         OLD_LOG1("\tactive handler L%03d", ex->handler->nr);
     842           0 :                                         STATE->handlers[len++] = ex;
     843             :                                 }
     844             :                         }
     845           0 :                         STATE->handlers[len] = NULL;
     846             : 
     847             :                         /* initialize the locals */
     848             : 
     849             :                         MCOPY(state.locals,
     850             :                                   state.startlocals + (state.bptr->nr * state.numlocals),
     851           0 :                                   verifier_slot_t, state.numlocals);
     852             : 
     853             :                         /* initialize the stack */
     854             : 
     855           0 :                         len = state.indepth[state.bptr->nr];
     856             : 
     857             :                         MCOPY(stackfloor,
     858             :                                   state.startstack + (state.bptr->nr * state.m->maxstack),
     859           0 :                                   verifier_slot_t, len);
     860             : 
     861           0 :                         stack = stackfloor + (len - 1);
     862             : 
     863             :                         /* iterate over the instructions in this block */
     864             : 
     865           0 :                         state.iptr = state.bptr->iinstr;
     866           0 :                         len = state.bptr->icount;
     867             : 
     868           0 :                         superblockend = false;
     869             : 
     870           0 :                         for (; len--; state.iptr++) {
     871             : 
     872           0 :                                 maythrow = false;
     873             : 
     874             :                                 OLD_LOGNL;
     875             :                                 DOLOG( typecheck_stackbased_show_state(&state, stack, stackfloor, true); );
     876             : 
     877           0 :                                 switch (state.iptr->opc) {
     878             : #define TYPECHECK_STACKBASED 1
     879             : #define STATE (&state)
     880             : #define IPTR state.iptr
     881             : #define BPTR state.bptr
     882             : #define METHOD state.m
     883             : #define LOCAL_SLOT(index)  (state.locals + (index))
     884             : #define EXCEPTION                                                    \
     885             :     do {                                                             \
     886             :         OLD_LOG("EXCEPTION THROWN!\n");                                  \
     887             :         return false;                                                \
     888             :     } while (0)
     889             : 
     890             : #include <typecheck-stackbased-gen.inc>
     891             : #undef  TYPECHECK_STACKBASED
     892             :                                 }
     893             : 
     894             :                                 /* reach exception handlers for this instruction */
     895             : 
     896           0 :                                 if (maythrow) {
     897             :                                         TYPECHECK_COUNT(stat_ins_maythrow);
     898             :                                         TYPECHECK_MARK(STATE->stat_maythrow);
     899             :                                         OLD_LOG("\treaching exception handlers");
     900           0 :                                         i = 0;
     901           0 :                                         while (STATE->handlers[i]) {
     902             :                                                 TYPECHECK_COUNT(stat_handlers_reached);
     903           0 :                                                 if (STATE->handlers[i]->catchtype.any)
     904           0 :                                                         exstack.typeinfo.typeclass = STATE->handlers[i]->catchtype;
     905             :                                                 else
     906           0 :                                                         exstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
     907           0 :                                                 if (!typecheck_stackbased_reach(
     908             :                                                                 STATE,
     909           0 :                                                                 STATE->handlers[i]->handler,
     910             :                                                                 &exstack, 1))
     911           0 :                                                         EXCEPTION;
     912           0 :                                                 i++;
     913             :                                         }
     914             :                                 }
     915             :                         }
     916             : 
     917             :                         /* propagate types to the following block */
     918             : 
     919           0 :                         if (!superblockend) {
     920           0 :                                 if (!typecheck_stackbased_reach(&state, state.bptr->next,
     921             :                                                                                                 stack, stack - stackfloor + 1))
     922           0 :                                         EXCEPTION;
     923             :                         }
     924             :                 } /* end loop over blocks */
     925             : 
     926           0 :                 while (!state.repeat && state.topjsr) {
     927             :                         OLD_LOG1("done analysing subroutine L%03d", state.topjsr->start->nr);
     928             : 
     929             :                         /* propagate down used locals */
     930             : 
     931           0 :                         if (state.topjsr->next) {
     932           0 :                                 for (i=0; i<state.numlocals; ++i)
     933           0 :                                         state.topjsr->next->usedlocals[i] |= state.topjsr->usedlocals[i];
     934             :                         }
     935             : 
     936             :                         /* restore REACHED flags */
     937             : 
     938           0 :                         for (tbptr = state.basicblocks; tbptr != NULL; tbptr = tbptr->next) {
     939           0 :                                 assert(tbptr->state != basicblock::TYPECHECK_REACHED);
     940           0 :                                 if (state.topjsr->blockflags[tbptr->nr] == basicblock::TYPECHECK_REACHED) {
     941           0 :                                         tbptr->state = basicblock::TYPECHECK_REACHED;
     942           0 :                                         state.repeat = true;
     943             :                                 }
     944             :                         }
     945             : 
     946             :                         /* dactivate the subroutine */
     947             : 
     948           0 :                         state.topjsr->active = false;
     949           0 :                         state.topjsr = state.topjsr->next;
     950             :                 }
     951             :         } while (state.repeat);
     952             : 
     953             :         /* reset block flags */
     954             : 
     955           0 :         typecheck_reset_state(&state);
     956             : 
     957             :         OLD_LOG("typecheck_stackbased successful");
     958             : 
     959           0 :         return true;
     960             : 
     961             : throw_stack_underflow:
     962             :         OLD_LOG("STACK UNDERFLOW!");
     963           0 :         exceptions_throw_verifyerror(state.m, "Unable to pop operand off an empty stack");
     964           0 :         return false;
     965             : 
     966             : throw_stack_overflow:
     967             :         OLD_LOG("STACK OVERFLOW!");
     968           0 :         exceptions_throw_verifyerror(state.m, "Stack size too large");
     969           0 :         return false;
     970             : 
     971             : throw_stack_type_error:
     972             :         OLD_LOG("STACK TYPE ERROR!");
     973           0 :         exceptions_throw_verifyerror(state.m, "Mismatched stack types");
     974           0 :         return false;
     975             : 
     976             : throw_local_type_error:
     977             :         OLD_LOG("LOCAL TYPE ERROR!");
     978           0 :         exceptions_throw_verifyerror(state.m, "Local variable type mismatch");
     979           0 :         return false;
     980             : 
     981             : throw_stack_category_error:
     982             :         OLD_LOG("STACK CATEGORY ERROR!");
     983           0 :         exceptions_throw_verifyerror(state.m, "Attempt to split long or double on the stack");
     984           0 :         return false;
     985             : }
     986             : 
     987             : 
     988             : #if defined(TYPECHECK_VERBOSE)
     989             : static void typecheck_stackbased_show_state(verifier_state *state,
     990             :                                                                                         typedescriptor_t *stack,
     991             :                                                                                         typedescriptor_t *stackfloor,
     992             :                                                                                         bool showins)
     993             : {
     994             :         typedescriptor_t *sp;
     995             :         s4 i;
     996             : 
     997             :         OLD_LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
     998             :         for (sp=stackfloor; sp <= stack; sp++) {
     999             :                 OLD_LOGSTR(" ");
    1000             :                 DOLOG( typedescriptor_print(stdout, sp); );
    1001             :         }
    1002             :         OLD_LOGSTR(" ] locals [");
    1003             :         for (i=0; i<state->numlocals; ++i) {
    1004             :                 OLD_LOGSTR(" ");
    1005             :                 DOLOG( typedescriptor_print(stdout, state->locals + i); );
    1006             :         }
    1007             :         OLD_LOGSTR(" ]");
    1008             :         OLD_LOGNL;
    1009             :         if (showins && state->iptr < (state->bptr->iinstr + state->bptr->icount)) {
    1010             :                 OLD_LOGSTR("\t");
    1011             :                 DOLOG( show_icmd(state->jd, state->iptr, false, SHOW_PARSE); );
    1012             :                 OLD_LOGNL;
    1013             :         }
    1014             : }
    1015             : #endif
    1016             : 
    1017             : 
    1018             : #endif /* defined(ENABLE_VERIFIER) */
    1019             : 
    1020             : 
    1021             : /*
    1022             :  * These are local overrides for various environment variables in Emacs.
    1023             :  * Please do not remove this and leave it at the end of the file, where
    1024             :  * Emacs will automagically detect them.
    1025             :  * ---------------------------------------------------------------------
    1026             :  * Local variables:
    1027             :  * mode: c++
    1028             :  * indent-tabs-mode: t
    1029             :  * c-basic-offset: 4
    1030             :  * tab-width: 4
    1031             :  * End:
    1032             :  * vim:noexpandtab:sw=4:ts=4:
    1033             :  */

Generated by: LCOV version 1.11