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

          Line data    Source code
       1             : /* src/vm/jit/verify/icmds.cpp - ICMD-specific type checking 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             : #if 0 /* (needed for code examples in the following comment) */
      26             : /******************************************************************************/
      27             : /* This file contains ICMD-specific code for type checking and type
      28             :  * inference. It is an input file for the verifier generator
      29             :  * (src/vm/jit/verify/generate.pl). The verifier generator creates
      30             :  * code for three compiler passes:
      31             :  *     - stack-based type-infering verification
      32             :  *     - vasiables-based type-infering verification
      33             :  *     - type inference pass (no verification - used for optimizing compiler)
      34             :  *
      35             :  * The rest of this file must consist of "case" clauses starting in
      36             :  * the first column. Each clause can be marked with tags like this:
      37             :  *
      38             :  */          case ICMD_CONSTANT: /* {TAG, TAG, ...} */
      39             : /*
      40             :  * This must be on one line. The following tags are defined:
      41             :  *     STACKBASED..........use this clause for the stack-based verifier
      42             :  *     VARIABLESBASED......use this clause for the variables-based verifier
      43             :  *     TYPEINFERER.........use this clause for the type inference pass
      44             :  *     ALL.................use for all passes
      45             :  *
      46             :  * If no tag is specified, {STACKBASED,VARIABLESBASED} is assumed.
      47             :  *
      48             :  * There are also tags that can be used inside a clause like this:
      49             :  *
      50             :  */          /* {TAG} */
      51             : /*
      52             :  * The following tags are defined within clauses:
      53             :  *     RESULTNOW...........generate code for modelling the stack action
      54             :  *                         _before_ the user-defined code in the clause
      55             :  *                         (Default is to model the stack action afterwards.)
      56             :  *
      57             :  * The following macros are pre-defined:
      58             :  *
      59             :  *     TYPECHECK_STACKBASED.......iff compiling the stack-based verifier
      60             :  *     TYPECHECK_VARIABLESBASED...iff compiling the variables-based verifier
      61             :  *     TYPECHECK_TYPEINFERER......iff compiling the type inference pass
      62             :  *
      63             : /******************************************************************************/
      64             : #endif /* (end #if 0) */
      65             : 
      66             : 
      67             : /* this marker is needed by generate.pl: */
      68             : /* {START_OF_CODE} */
      69             : 
      70             :         /****************************************/
      71             :         /* MOVE/COPY                            */
      72             : 
      73             :         /* We just need to copy the typeinfo */
      74             :         /* for slots containing addresses.   */
      75             : 
      76             :         /* (These are only used by the variables based verifier.) */
      77             : 
      78             : case ICMD_MOVE: /* {VARIABLESBASED,TYPEINFERER} */
      79             : case ICMD_COPY: /* {VARIABLESBASED,TYPEINFERER} */
      80        6325 :         TYPECHECK_COUNT(stat_ins_stack);
      81      650172 :         COPYTYPE(IPTR->s1, IPTR->dst);
      82      643847 :         DST->type = OP1->type;
      83             :         break;
      84             : 
      85             :         /****************************************/
      86             :         /* LOADING ADDRESS FROM VARIABLE        */
      87             : 
      88             : case ICMD_ALOAD: /* {ALL} */
      89             :         TYPECHECK_COUNT(stat_ins_aload);
      90             : 
      91             : #if !defined(TYPECHECK_TYPEINFERER)
      92             :         /* loading a returnAddress is not allowed */
      93             :         if (!OP1->is_reference()) {
      94      413174 :                 VERIFY_ERROR("illegal instruction: ALOAD loading non-reference");
      95           0 :         }
      96             : #endif
      97             :         DST->typeinfo = OP1->typeinfo;
      98             :         break;
      99      413174 : 
     100             :         /****************************************/
     101             :         /* STORING ADDRESS TO VARIABLE          */
     102             : 
     103             : case ICMD_ASTORE: /* {ALL} */
     104       62611 :         DST->typeinfo = OP1->typeinfo;
     105             :         break;
     106             : 
     107             :         /****************************************/
     108             :         /* LOADING ADDRESS FROM ARRAY           */
     109             : 
     110             : case ICMD_AALOAD: /* {ALL} */
     111             : #if !defined(TYPECHECK_TYPEINFERER)
     112             :         if (!OP1->typeinfo.maybe_array_of_refs())
     113       21280 :                 VERIFY_ERROR("illegal instruction: AALOAD on non-reference array");
     114           0 : #endif
     115             : 
     116             :         if (!DST->typeinfo.init_component(OP1->typeinfo))
     117             :                 EXCEPTION;
     118       21280 :         break;
     119           0 : 
     120             :         /****************************************/
     121             :         /* FIELD ACCESS                         */
     122             : 
     123             : case ICMD_PUTFIELD: /* {STACKBASED} */
     124           0 :         CHECK_STACK_DEPTH(2);
     125           0 :         if (!IS_CAT1(stack[0])) {
     126           0 :                 CHECK_STACK_DEPTH(3);
     127           0 :                 stack -= 1;
     128             :         }
     129           0 :         CHECK_STACK_TYPE(stack[-1], TYPE_ADR);
     130           0 :         stack = typecheck_stackbased_verify_fieldaccess(STATE, stack-1, stack, stack-2);
     131           0 :         if (stack == NULL)
     132           0 :                 EXCEPTION;
     133             :         break;
     134             : 
     135             : case ICMD_PUTSTATIC: /* {STACKBASED} */
     136           0 :         CHECK_STACK_DEPTH(1);
     137           0 :         if (!IS_CAT1(stack[0])) {
     138             :                 /* (stack depth >= 2 is guaranteed) */
     139           0 :                 stack -= 1;
     140             :         }
     141           0 :         stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, stack, stack-1);
     142           0 :         if (stack == NULL)
     143           0 :                 EXCEPTION;
     144             :         break;
     145             : 
     146             : case ICMD_GETFIELD: /* {STACKBASED} */
     147           0 :         CHECK_STACK_TYPE(stack[0], TYPE_ADR);
     148           0 :         stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
     149           0 :         if (stack == NULL)
     150           0 :                 EXCEPTION;
     151             :         break;
     152             : 
     153             : case ICMD_GETSTATIC:      /* {STACKBASED} */
     154           0 :         stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
     155           0 :         if (stack == NULL)
     156           0 :                 EXCEPTION;
     157             :         break;
     158             : 
     159             : case ICMD_PUTFIELD:       /* {VARIABLESBASED} */
     160       40170 :         if (!handle_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
     161           0 :                 return false;
     162       40170 :         maythrow = true;
     163             :         break;
     164             : 
     165             : case ICMD_PUTSTATIC:      /* {VARIABLESBASED} */
     166       21810 :         if (!handle_fieldaccess(state, NULL, VAROP(iptr->s1)))
     167           0 :                 return false;
     168       21810 :         maythrow = true;
     169             :         break;
     170             : 
     171             : case ICMD_PUTFIELDCONST:  /* {VARIABLESBASED} */
     172             :         /* XXX this mess will go away with const operands */
     173       12233 :         INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
     174       12233 :         constvalue.type = fieldref->parseddesc.fd->type;
     175       12233 :         if (IS_ADR_TYPE(constvalue.type)) {
     176        3807 :                 if (state->iptr->sx.val.anyptr) {
     177             :                         classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
     178         339 :                                 ? class_java_lang_Class : class_java_lang_String;
     179         339 :                         assert(cc);
     180         339 :                         assert(cc->state & CLASS_LINKED);
     181         339 :                         constvalue.typeinfo.init_class(cc);
     182             :                 }
     183             :                 else {
     184        3468 :                         constvalue.typeinfo.init_nulltype();
     185             :                 }
     186             :         }
     187       12233 :         if (!handle_fieldaccess(state, VAROP(iptr->s1), &constvalue))
     188           0 :                 return false;
     189       12233 :         maythrow = true;
     190             :         break;
     191             : 
     192             : case ICMD_PUTSTATICCONST: /* {VARIABLESBASED} */
     193             :         /* XXX this mess will go away with const operands */
     194         814 :         INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
     195         814 :         constvalue.type = fieldref->parseddesc.fd->type;
     196         814 :         if (IS_ADR_TYPE(constvalue.type)) {
     197         290 :                 if (state->iptr->sx.val.anyptr) {
     198             :                         classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
     199           1 :                                 ? class_java_lang_Class : class_java_lang_String;
     200           1 :                         assert(cc);
     201           1 :                         assert(cc->state & CLASS_LINKED);
     202           1 :                         constvalue.typeinfo.init_class(cc);
     203             :                 }
     204             :                 else {
     205         289 :                         constvalue.typeinfo.init_nulltype();
     206             :                 }
     207             :         }
     208         814 :         if (!handle_fieldaccess(state, NULL, &constvalue))
     209           0 :                 return false;
     210         814 :         maythrow = true;
     211             :         break;
     212             : 
     213             : case ICMD_GETFIELD:       /* {VARIABLESBASED,TYPEINFERER} */
     214      101999 :         if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
     215           0 :                 return false;
     216      101999 :         maythrow = true;
     217             :         break;
     218             : 
     219             : case ICMD_GETSTATIC:      /* {VARIABLESBASED,TYPEINFERER} */
     220       48519 :         if (!handle_fieldaccess(state, NULL, NULL))
     221           0 :                 return false;
     222       48519 :         maythrow = true;
     223             :         break;
     224             : 
     225             :         /****************************************/
     226             :         /* PRIMITIVE ARRAY ACCESS               */
     227             : 
     228             : case ICMD_ARRAYLENGTH:
     229        9830 :         if (!OP1->typeinfo.maybe_array() && OP1->typeinfo.typeclass.cls != pseudo_class_Arraystub)
     230           0 :                 VERIFY_ERROR("illegal instruction: ARRAYLENGTH on non-array");
     231             :         break;
     232             : 
     233             : case ICMD_BALOAD:
     234         160 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BOOLEAN)
     235             :                         && !OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BYTE))
     236           0 :                 VERIFY_ERROR("Array type mismatch");
     237             :         break;
     238             : 
     239             : case ICMD_CALOAD:
     240        3610 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_CHAR))
     241           0 :                 VERIFY_ERROR("Array type mismatch");
     242             :         break;
     243             : 
     244             : case ICMD_DALOAD:
     245           3 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_DOUBLE))
     246           0 :                 VERIFY_ERROR("Array type mismatch");
     247             :         break;
     248             : 
     249             : case ICMD_FALOAD:
     250           3 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_FLOAT))
     251           0 :                 VERIFY_ERROR("Array type mismatch");
     252             :         break;
     253             : 
     254             : case ICMD_IALOAD:
     255         301 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_INT))
     256           0 :                 VERIFY_ERROR("Array type mismatch");
     257             :         break;
     258             : 
     259             : case ICMD_SALOAD:
     260          59 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_SHORT))
     261           0 :                 VERIFY_ERROR("Array type mismatch");
     262             :         break;
     263             : 
     264             : case ICMD_LALOAD:
     265          21 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_LONG))
     266           0 :                 VERIFY_ERROR("Array type mismatch");
     267             :         break;
     268             : 
     269             : case ICMD_BASTORE:
     270         360 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BOOLEAN)
     271             :                         && !OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BYTE))
     272           0 :                 VERIFY_ERROR("Array type mismatch");
     273             :         break;
     274             : 
     275             : case ICMD_CASTORE:
     276        1032 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_CHAR))
     277           0 :                 VERIFY_ERROR("Array type mismatch");
     278             :         break;
     279             : 
     280             : case ICMD_DASTORE:
     281           4 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_DOUBLE))
     282           0 :                 VERIFY_ERROR("Array type mismatch");
     283             :         break;
     284             : 
     285             : case ICMD_FASTORE:
     286           6 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_FLOAT))
     287           0 :                 VERIFY_ERROR("Array type mismatch");
     288             :         break;
     289             : 
     290             : case ICMD_IASTORE:
     291          86 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_INT))
     292           0 :                 VERIFY_ERROR("Array type mismatch");
     293             :         break;
     294             : 
     295             : case ICMD_SASTORE:
     296          52 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_SHORT))
     297           0 :                 VERIFY_ERROR("Array type mismatch");
     298             :         break;
     299             : 
     300             : case ICMD_LASTORE:
     301          10 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_LONG))
     302           0 :                 VERIFY_ERROR("Array type mismatch");
     303             :         break;
     304             : 
     305             : case ICMD_AASTORE:
     306             :         /* we just check the basic input types and that the           */
     307             :         /* destination is an array of references. Assignability to    */
     308             :         /* the actual array must be checked at runtime, each time the */
     309             :         /* instruction is performed. (See builtin_canstore.)          */
     310       64570 :         if (!OP1->typeinfo.maybe_array_of_refs())
     311           0 :                 VERIFY_ERROR("illegal instruction: AASTORE to non-reference array");
     312             :         break;
     313             : 
     314             : case ICMD_IASTORECONST:
     315        4735 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_INT))
     316           0 :                 VERIFY_ERROR("Array type mismatch");
     317             :         break;
     318             : 
     319             : case ICMD_LASTORECONST:
     320           6 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_LONG))
     321           0 :                 VERIFY_ERROR("Array type mismatch");
     322             :         break;
     323             : 
     324             : case ICMD_BASTORECONST:
     325         725 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BOOLEAN)
     326             :                         && !OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BYTE))
     327           0 :                 VERIFY_ERROR("Array type mismatch");
     328             :         break;
     329             : 
     330             : case ICMD_CASTORECONST:
     331      508614 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_CHAR))
     332           0 :                 VERIFY_ERROR("Array type mismatch");
     333             :         break;
     334             : 
     335             : case ICMD_SASTORECONST:
     336           4 :         if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_SHORT))
     337           0 :                 VERIFY_ERROR("Array type mismatch");
     338             :         break;
     339             : 
     340             :         /****************************************/
     341             :         /* ADDRESS CONSTANTS                    */
     342             : 
     343             : case ICMD_ACONST: /* {ALL} */
     344      168685 :         if (IPTR->flags.bits & INS_FLAG_CLASS) {
     345             :                 /* a java.lang.Class reference */
     346       64184 :                 DST->typeinfo.init_java_lang_class(IPTR->sx.val.c);
     347             :         }
     348             :         else {
     349      104501 :                 if (IPTR->sx.val.anyptr == NULL)
     350       13152 :                         DST->typeinfo.init_nulltype();
     351             :                 else {
     352             :                         /* string constant (or constant for builtin function) */
     353       91349 :                         DST->typeinfo.init_class(class_java_lang_String);
     354             :                 }
     355             :         }
     356             :         break;
     357             : 
     358             :         /****************************************/
     359             :         /* CHECKCAST AND INSTANCEOF             */
     360             : 
     361             : case ICMD_CHECKCAST: /* {ALL} */
     362             : #if !defined(TYPECHECK_TYPEINFERER)
     363             :         /* returnAddress is not allowed */
     364             :         if (!OP1->typeinfo.is_reference())
     365        9506 :                 VERIFY_ERROR("Illegal instruction: CHECKCAST on non-reference");
     366           0 : #endif
     367             : 
     368             :     /* XXX only if narrower */
     369             :         if (!DST->typeinfo.init_class(IPTR->sx.s23.s3.c))
     370             :                 EXCEPTION;
     371        9506 :         break;
     372           0 : 
     373             : case ICMD_INSTANCEOF:
     374             :         /* returnAddress is not allowed */
     375        1339 :         if (!OP1->typeinfo.is_reference())
     376           0 :                 VERIFY_ERROR("Illegal instruction: INSTANCEOF on non-reference");
     377             : 
     378             :         /* XXX should propagate type information to the following if-branches */
     379             :         break;
     380             : 
     381             :         /****************************************/
     382             :         /* BRANCH INSTRUCTIONS                  */
     383             : 
     384             : case ICMD_GOTO:            /* {ALL} */
     385             : case ICMD_IFNULL:          /* {ALL} */
     386             : case ICMD_IFNONNULL:       /* {ALL} */
     387             : case ICMD_IFEQ:            /* {ALL} */
     388             : case ICMD_IFNE:            /* {ALL} */
     389       36379 : case ICMD_IFLT:            /* {ALL} */
     390           0 : case ICMD_IFGE:            /* {ALL} */
     391             : case ICMD_IFGT:            /* {ALL} */
     392           0 : case ICMD_IFLE:            /* {ALL} */
     393             : case ICMD_IF_ICMPEQ:       /* {ALL} */
     394             : case ICMD_IF_ICMPNE:       /* {ALL} */
     395             : case ICMD_IF_ICMPLT:       /* {ALL} */
     396             : case ICMD_IF_ICMPGE:       /* {ALL} */
     397             : case ICMD_IF_ICMPGT:       /* {ALL} */
     398           0 : case ICMD_IF_ICMPLE:       /* {ALL} */
     399             : case ICMD_IF_ACMPEQ:       /* {ALL} */
     400             : case ICMD_IF_ACMPNE:       /* {ALL} */
     401             : 
     402             : case ICMD_IF_LEQ:          /* {ALL} */
     403             : case ICMD_IF_LNE:          /* {ALL} */
     404           0 : case ICMD_IF_LLT:          /* {ALL} */
     405             : case ICMD_IF_LGE:          /* {ALL} */
     406             : case ICMD_IF_LGT:          /* {ALL} */
     407      110068 : case ICMD_IF_LLE:          /* {ALL} */
     408             : 
     409             : case ICMD_IF_LCMPEQ:       /* {ALL} */
     410             : case ICMD_IF_LCMPNE:       /* {ALL} */
     411             : case ICMD_IF_LCMPLT:       /* {ALL} */
     412             : case ICMD_IF_LCMPGE:       /* {ALL} */
     413             : case ICMD_IF_LCMPGT:       /* {ALL} */
     414             : case ICMD_IF_LCMPLE:       /* {ALL} */
     415             :         /* {RESULTNOW} */
     416             :         TYPECHECK_COUNT(stat_ins_branch);
     417             : 
     418             :         /* propagate stack and variables to the target block */
     419             :         REACH(IPTR->dst);
     420             :         break;
     421             : 
     422             :         /****************************************/
     423             :         /* SWITCHES                             */
     424             : 
     425             : case ICMD_TABLESWITCH:     /* {ALL} */
     426             :         /* {RESULTNOW} */
     427             :         TYPECHECK_COUNT(stat_ins_switch);
     428             : 
     429          80 :         table = IPTR->dst.table;
     430             :         i = IPTR->sx.s23.s3.tablehigh
     431          80 :         - IPTR->sx.s23.s2.tablelow + 1 + 1; /* plus default */
     432             : 
     433        1336 :         while (--i >= 0) {
     434        1176 :                 REACH(*table);
     435        1176 :                 table++;
     436             :         }
     437             : 
     438             :         OLD_LOG("switch done");
     439             :         break;
     440             : 
     441             : case ICMD_LOOKUPSWITCH:    /* {ALL} */
     442             :         /* {RESULTNOW} */
     443             :         TYPECHECK_COUNT(stat_ins_switch);
     444             : 
     445          78 :         lookup = IPTR->dst.lookup;
     446          78 :         i = IPTR->sx.s23.s2.lookupcount;
     447          78 :         REACH(IPTR->sx.s23.s3.lookupdefault);
     448             : 
     449         780 :         while (--i >= 0) {
     450         624 :                 REACH(lookup->target);
     451         624 :                 lookup++;
     452             :         }
     453             : 
     454             :         OLD_LOG("switch done");
     455             :         break;
     456             : 
     457             : 
     458             :         /****************************************/
     459             :         /* ADDRESS RETURNS AND THROW            */
     460             : 
     461             : case ICMD_ATHROW:
     462             :         TYPECHECK_COUNT(stat_ins_athrow);
     463       19130 :         r = OP1->typeinfo.is_assignable_to_class(to_classref_or_classinfo(class_java_lang_Throwable));
     464       19130 :         if (r == typecheck_FALSE)
     465           1 :                 VERIFY_ERROR("illegal instruction: ATHROW on non-Throwable");
     466       19129 :         if (r == typecheck_FAIL)
     467           0 :                 EXCEPTION;
     468       19129 :         if (r == typecheck_MAYBE) {
     469             :                 /* the check has to be postponed. we need a patcher */
     470             :                 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
     471             :                 IPTR->sx.s23.s2.uc = create_unresolved_class(
     472             :                                 METHOD,
     473             :                                 /* XXX make this more efficient, use class_java_lang_Throwable
     474             :                                  * directly */
     475             :                                 class_get_classref(METHOD->clazz,utf8::java_lang_Throwable),
     476       15328 :                                 &OP1->typeinfo);
     477       15328 :                 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
     478             :         }
     479             :         break;
     480             : 
     481             : case ICMD_ARETURN:
     482             :         TYPECHECK_COUNT(stat_ins_areturn);
     483       39056 :         if (!OP1->typeinfo.is_reference())
     484           0 :                 VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
     485             : 
     486       39056 :         if (STATE->returntype.type != TYPE_ADR
     487             :                         || (r = OP1->typeinfo.is_assignable_to(&(STATE->returntype.typeinfo)))
     488             :                         == typecheck_FALSE)
     489           0 :                 VERIFY_ERROR("Return type mismatch");
     490       39056 :         if (r == typecheck_FAIL)
     491           0 :                 EXCEPTION;
     492       39056 :         if (r == typecheck_MAYBE) {
     493             :                 /* the check has to be postponed, we need a patcher */
     494             :                 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
     495             :                 IPTR->sx.s23.s2.uc = create_unresolved_class(
     496             :                                 METHOD,
     497             :                                 METHOD->parseddesc->returntype.classref,
     498        3305 :                                 &OP1->typeinfo);
     499        3305 :                 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
     500             :         }
     501             :         goto return_tail;
     502             : 
     503             :         /****************************************/
     504             :         /* PRIMITIVE RETURNS                    */
     505             : 
     506             : case ICMD_IRETURN:
     507       19769 :         if (STATE->returntype.type != TYPE_INT)
     508           1 :                 VERIFY_ERROR("Return type mismatch");
     509             :         goto return_tail;
     510             : 
     511             : case ICMD_LRETURN:
     512         246 :         if (STATE->returntype.type != TYPE_LNG)
     513           0 :                 VERIFY_ERROR("Return type mismatch");
     514             :         goto return_tail;
     515             : 
     516             : case ICMD_FRETURN:
     517         154 :         if (STATE->returntype.type != TYPE_FLT)
     518           0 :                 VERIFY_ERROR("Return type mismatch");
     519             :         goto return_tail;
     520             : 
     521             : case ICMD_DRETURN:
     522           9 :         if (STATE->returntype.type != TYPE_DBL)
     523           0 :                 VERIFY_ERROR("Return type mismatch");
     524             :         goto return_tail;
     525             : 
     526             : case ICMD_RETURN:
     527       44351 :         if (STATE->returntype.type != TYPE_VOID)
     528           0 :                 VERIFY_ERROR("Return type mismatch");
     529             : 
     530             : return_tail:
     531             :         TYPECHECK_COUNT(stat_ins_primitive_return);
     532             : 
     533      103584 :         if (STATE->initmethod && METHOD->clazz != class_java_lang_Object) {
     534             :                 /* Check if the 'this' instance has been initialized. */
     535             :                 OLD_LOG("Checking <init> marker");
     536             : #if defined(TYPECHECK_VARIABLESBASED)
     537             :                 if (!typevector_checktype(jd->var,STATE->numlocals-1,TYPE_INT))
     538       25389 : #else
     539             :                 if (STATE->locals[STATE->numlocals-1].type != TYPE_INT)
     540             : #endif
     541           0 :                         VERIFY_ERROR("<init> method does not initialize 'this'");
     542             :         }
     543             :         break;
     544           0 : 
     545             :         /****************************************/
     546             :         /* SUBROUTINE INSTRUCTIONS              */
     547             : 
     548             : case ICMD_JSR: /* {VARIABLESBASED,TYPEINFERER} */
     549          18 :         DST->typeinfo.init_returnaddress(BPTR->next);
     550          18 :         REACH(IPTR->sx.s23.s3.jsrtarget);
     551             :         break;
     552             : 
     553             : case ICMD_JSR: /* {STACKBASED} */
     554             :         /* {RESULTNOW} */
     555           0 :         tbptr = IPTR->sx.s23.s3.jsrtarget.block;
     556             : 
     557           0 :         stack[0].typeinfo.init_returnaddress(tbptr);
     558           0 :         REACH_BLOCK(tbptr);
     559             : 
     560           0 :         stack = typecheck_stackbased_jsr(STATE, stack, stackfloor);
     561           0 :         if (stack == NULL)
     562           0 :                 EXCEPTION;
     563             :         break;
     564             : 
     565             : case ICMD_RET: /* {VARIABLESBASED,TYPEINFERER} */
     566             : #if !defined(TYPECHECK_TYPEINFERER)
     567             :         /* check returnAddress variable */
     568             :         if (!typevector_checkretaddr(jd->var,IPTR->s1.varindex))
     569          15 :                 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
     570           0 : #endif
     571             :         REACH(IPTR->dst);
     572             :         break;
     573          15 : 
     574             : case ICMD_RET: /* {STACKBASED} */
     575             :         /* {RESULTNOW} */
     576           0 :         CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_RET);
     577           0 :         if (!STATE->locals[IPTR->s1.varindex].typeinfo.is_primitive())
     578           0 :                 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
     579             : 
     580           0 :         if (!typecheck_stackbased_ret(STATE, stack, stackfloor))
     581           0 :                 EXCEPTION;
     582             :         break;
     583             : 
     584             :         /****************************************/
     585             :         /* INVOKATIONS                          */
     586             : 
     587             : case ICMD_INVOKEVIRTUAL:   /* {VARIABLESBASED,TYPEINFERER} */
     588             : case ICMD_INVOKESPECIAL:   /* {VARIABLESBASED,TYPEINFERER} */
     589      289993 : case ICMD_INVOKESTATIC:    /* {VARIABLESBASED,TYPEINFERER} */
     590           5 : case ICMD_INVOKEINTERFACE: /* {VARIABLESBASED,TYPEINFERER} */
     591             :         TYPECHECK_COUNT(stat_ins_invoke);
     592             :         if (!handle_invocation(state))
     593             :                 EXCEPTION;
     594             :         TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
     595             :         break;
     596             : 
     597             : case ICMD_INVOKEVIRTUAL:   /* {STACKBASED} */
     598             : case ICMD_INVOKESPECIAL:   /* {STACKBASED} */
     599             : case ICMD_INVOKESTATIC:    /* {STACKBASED} */
     600           0 : case ICMD_INVOKEINTERFACE: /* {STACKBASED} */
     601           0 :         TYPECHECK_COUNT(stat_ins_invoke);
     602             : 
     603           0 :         INSTRUCTION_GET_METHODDESC(IPTR, md);
     604           0 :         CHECK_STACK_DEPTH(md->paramslots);
     605             : 
     606           0 :         if (!typecheck_stackbased_verify_invocation(STATE, stack, stackfloor))
     607             :                 EXCEPTION;
     608           0 : 
     609           0 :         stack -= md->paramslots;
     610           0 : 
     611           0 :         if (md->returntype.type != TYPE_VOID) {
     612           0 :                 if (IS_2_WORD_TYPE(md->returntype.type)) {
     613           0 :                         CHECK_STACK_SPACE(2);
     614             :                         stack += 2;
     615             :                         stack[0].type = TYPE_VOID;
     616           0 :                         stack[-1].type = md->returntype.type;
     617           0 :                 }
     618           0 :                 else {
     619             :                         CHECK_STACK_SPACE(1);
     620             :                         stack += 1;
     621             :                         stack[0].type = md->returntype.type;
     622             :                 }
     623             :         }
     624             :         TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
     625             :         break;
     626             : 
     627             :         /****************************************/
     628             :         /* MULTIANEWARRAY                       */
     629             : 
     630             : case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED,TYPEINFERER} */
     631          15 :         if (!handle_multianewarray(STATE))
     632           0 :                 EXCEPTION;
     633             :         break;
     634             : 
     635             : case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
     636           0 :         if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
     637           0 :                 EXCEPTION;
     638           0 :         stack -= (IPTR->s1.argcount - 1);
     639           0 :         stack[0].type = TYPE_ADR;
     640             :         break;
     641             : 
     642             :         /****************************************/
     643             :         /* BUILTINS                             */
     644             : 
     645             : case ICMD_BUILTIN: /* {VARIABLESBASED,TYPEINFERER} */
     646             :         TYPECHECK_COUNT(stat_ins_builtin);
     647       79492 :         if (!handle_builtin(state))
     648           0 :                 EXCEPTION;
     649             :         break;
     650             : 
     651             : case ICMD_BUILTIN: /* {STACKBASED} */
     652             :         TYPECHECK_COUNT(stat_ins_builtin);
     653           0 :         if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
     654           0 :                 EXCEPTION;
     655             : 
     656             :         /* pop operands and push return value */
     657             :         {
     658           0 :                 u1 rtype = IPTR->sx.s23.s3.bte->md->returntype.type;
     659           0 :                 stack -=  IPTR->sx.s23.s3.bte->md->paramslots;
     660           0 :                 if (rtype != TYPE_VOID) {
     661           0 :                         if (IS_2_WORD_TYPE(rtype))
     662           0 :                                 stack += 2;
     663             :                         else
     664           0 :                                 stack += 1;
     665             :                 }
     666             :         }
     667             :         break;
     668             : 
     669             : /* the following code is only used by the stackbased verifier */
     670             : 
     671             : case ICMD_POP: /* {STACKBASED} */
     672             :         /* we pop 1 */
     673           0 :         CHECK_CAT1(stack[0]);
     674             :         break;
     675             : 
     676             : case ICMD_POP2: /* {STACKBASED} */
     677             :         /* we pop either 11 or 2 */
     678           0 :         if (IS_CAT1(stack[0]))
     679           0 :                 CHECK_CAT1(stack[-1]);
     680             :         break;
     681             : 
     682             : case ICMD_SWAP: /* {STACKBASED} */
     683           0 :         CHECK_CAT1(stack[0]);
     684           0 :         CHECK_CAT1(stack[-1]);
     685             : 
     686           0 :         COPY_SLOT(stack[ 0], temp     );
     687           0 :         COPY_SLOT(stack[-1], stack[ 0]);
     688           0 :         COPY_SLOT(temp     , stack[-1]);
     689             :         break;
     690             : 
     691             : case ICMD_DUP: /* {STACKBASED} */
     692             :         /* we dup 1 */
     693           0 :         CHECK_CAT1(stack[0]);
     694             : 
     695           0 :         COPY_SLOT(stack[ 0], stack[ 1]);
     696             :         break;
     697             : 
     698             : case ICMD_DUP_X1: /* {STACKBASED} */
     699             :         /* we dup 1 */
     700           0 :         CHECK_CAT1(stack[0]);
     701             :         /* we skip 1 */
     702           0 :         CHECK_CAT1(stack[-1]);
     703             : 
     704           0 :         COPY_SLOT(stack[ 0], stack[ 1]);
     705           0 :         COPY_SLOT(stack[-1], stack[ 0]);
     706           0 :         COPY_SLOT(stack[ 1], stack[-1]);
     707             :         break;
     708             : 
     709             : case ICMD_DUP_X2: /* {STACKBASED} */
     710             :         /* we dup 1 */
     711           0 :         CHECK_CAT1(stack[0]);
     712             :         /* we skip either 11 or 2 */
     713           0 :         if (IS_CAT1(stack[-1]))
     714           0 :                 CHECK_CAT1(stack[-2]);
     715             : 
     716           0 :         COPY_SLOT(stack[ 0], stack[ 1]);
     717           0 :         COPY_SLOT(stack[-1], stack[ 0]);
     718           0 :         COPY_SLOT(stack[-2], stack[-1]);
     719           0 :         COPY_SLOT(stack[ 1], stack[-2]);
     720             :         break;
     721             : 
     722             : case ICMD_DUP2: /* {STACKBASED} */
     723             :         /* we dup either 11 or 2 */
     724           0 :         if (IS_CAT1(stack[0]))
     725           0 :                 CHECK_CAT1(stack[-1]);
     726             : 
     727           0 :         COPY_SLOT(stack[ 0], stack[ 2]);
     728           0 :         COPY_SLOT(stack[-1], stack[ 1]);
     729             :         break;
     730             : 
     731             : case ICMD_DUP2_X1: /* {STACKBASED} */
     732             :         /* we dup either 11 or 2 */
     733           0 :         if (IS_CAT1(stack[0]))
     734           0 :                 CHECK_CAT1(stack[-1]);
     735             :         /* we skip 1 */
     736           0 :         CHECK_CAT1(stack[-2]);
     737             : 
     738           0 :         COPY_SLOT(stack[ 0], stack[ 2]);
     739           0 :         COPY_SLOT(stack[-1], stack[ 1]);
     740           0 :         COPY_SLOT(stack[-2], stack[ 0]);
     741           0 :         COPY_SLOT(stack[ 2], stack[-1]);
     742           0 :         COPY_SLOT(stack[ 1], stack[-2]);
     743             :         break;
     744             : 
     745             : case ICMD_DUP2_X2: /* {STACKBASED} */
     746             :         /* we dup either 11 or 2 */
     747           0 :         if (IS_CAT1(stack[0]))
     748           0 :                 CHECK_CAT1(stack[-1]);
     749             :         /* we skip either 11 or 2 */
     750           0 :         if (IS_CAT1(stack[-2]))
     751           0 :                 CHECK_CAT1(stack[-3]);
     752             : 
     753           0 :         COPY_SLOT(stack[ 0], stack[ 2]);
     754           0 :         COPY_SLOT(stack[-1], stack[ 1]);
     755           0 :         COPY_SLOT(stack[-2], stack[ 0]);
     756           0 :         COPY_SLOT(stack[-3], stack[-1]);
     757           0 :         COPY_SLOT(stack[ 2], stack[-2]);
     758           0 :         COPY_SLOT(stack[ 1], stack[-3]);
     759             :         break;
     760             : 
     761             : 
     762             : /* this marker is needed by generate.pl: */
     763             : /* {END_OF_CODE} */
     764             : 
     765             : /*
     766             :  * These are local overrides for various environment variables in Emacs.
     767             :  * Please do not remove this and leave it at the end of the file, where
     768             :  * Emacs will automagically detect them.
     769             :  * ---------------------------------------------------------------------
     770             :  * Local variables:
     771             :  * mode: c++
     772             :  * indent-tabs-mode: t
     773             :  * c-basic-offset: 4
     774             :  * tab-width: 4
     775             :  * End:
     776             :  * vim:noexpandtab:sw=4:ts=4:
     777             :  */

Generated by: LCOV version 1.11