1 /* src/vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Edwin Steiner
29 Changes: Christian Thalinger
31 $Id: typecheck.c 5515 2006-09-15 14:43:22Z edwin $
37 What's the purpose of the `typechecker`?
38 ----------------------------------------
40 The typechecker analyses (the intermediate repr. of) the bytecode of
41 each method and ensures that for each instruction the values on the
42 stack and in local variables are of the correct type whenever the
43 instruction is executed.
45 type checking is a mandatory part of bytecode verification.
48 How does the typechecker work?
49 ------------------------------
51 The JVM stack and the local variables are not statically typed, so the
52 typechecker has to *infer* the static types of stack slots and local
53 variables at each point of the method. The JVM spec imposes a lot of
54 restrictions on the bytecode in order to guarantee that this is always
57 Basically the typechecker solves the data flow equations of the method.
58 This is done in the usual way for a forward data flow analysis: Starting
59 from the entry point of the method the typechecker follows the CFG and
60 records the type of each stack slot and local variable at each point[1].
61 When two or more control flow paths merge at a point, the union of the
62 types for each slot/variable is taken. The algorithm continues to follow
63 all possible paths[2] until the recorded types do not change anymore (ie.
64 the equations have been solved).
66 If the solution has been reached and the resulting types are valid for
67 all instructions, then type checking terminates with success, otherwise
68 an exception is thrown.
71 Why is this code so damn complicated?
72 -------------------------------------
74 Short answer: The devil's in the details.
76 While the basic operation of the typechecker is no big deal, there are
77 many properties of Java bytecode which make type checking hard. Some of
78 them are not even addressed in the JVM spec. Some problems and their
81 *) Finding a good representation of the union of two reference types is
82 difficult because of multiple inheritance of interfaces.
84 Solution: The typeinfo system can represent such "merged" types by a
85 list of proper subclasses of a class. Example:
87 typeclass=java.lang.Object merged={ InterfaceA, InterfaceB }
89 represents the result of merging two interface types "InterfaceA"
92 *) When the code of a method is verified, there may still be unresolved
93 references to classes/methods/fields in the code, which we may not force
94 to be resolved eagerly. (A similar problem arises because of the special
95 checks for protected members.)
97 Solution: The typeinfo system knows how to deal with unresolved
98 class references. Whenever a check has to be performed for an
99 unresolved type, the type is annotated with constraints representing
100 the check. Later, when the type is resolved, the constraints are
101 checked. (See the constrain_unresolved_... and the resolve_...
104 *) Checks for uninitialized object instances are hard because after the
105 invocation of <init> on an uninitialized object *all* slots/variables
106 referring to this object (and exactly those slots/variables) must be
107 marked as initialized.
109 Solution: The JVM spec describes a solution, which has been
110 implemented in this typechecker.
112 Note that some checks mentioned in the JVM spec are unnecessary[4] and
113 not performed by either the reference implementation, or this implementation.
118 [1] Actually only the types of slots/variables at the start of each
119 basic block are remembered. Within a basic block the algorithm only keeps
120 the types of the slots/variables for the "current" instruction which is
123 [2] Actually the algorithm iterates through the basic block list until
124 there are no more changes. Theoretically it would be wise to sort the
125 basic blocks topologically beforehand, but the number of average/max
126 iterations observed is so low, that this was not deemed necessary.
128 [3] This is similar to a method proposed by: Alessandro Coglio et al., A
129 Formal Specification of Java Class Loading, Technical Report, Kestrel
130 Institute April 2000, revised July 2000
131 http://www.kestrel.edu/home/people/coglio/loading.pdf
132 An important difference is that Coglio's subtype constraints are checked
133 after loading, while our constraints are checked when the field/method
134 is accessed for the first time, so we can guarantee lexically correct
137 [4] Alessandro Coglio
138 Improving the official specification of Java bytecode verification
139 Proceedings of the 3rd ECOOP Workshop on Formal Techniques for Java Programs
141 citeseer.ist.psu.edu/article/coglio03improving.html
148 #include "vm/types.h"
149 #include "vm/global.h"
151 #ifdef ENABLE_VERIFIER
153 #include "mm/memory.h"
154 #include "toolbox/logging.h"
155 #include "native/native.h"
156 #include "vm/builtin.h"
157 #include "vm/jit/patcher.h"
158 #include "vm/loader.h"
159 #include "vm/options.h"
160 #include "vm/jit/jit.h"
161 #include "vm/jit/show.h"
162 #include "vm/access.h"
163 #include "vm/resolve.h"
164 #include "vm/exceptions.h"
166 /****************************************************************************/
168 /****************************************************************************/
170 #ifdef TYPECHECK_DEBUG
171 #define TYPECHECK_ASSERT(cond) assert(cond)
173 #define TYPECHECK_ASSERT(cond)
176 #ifdef TYPECHECK_VERBOSE_OPT
177 bool opt_typecheckverbose = false;
178 #define DOLOG(action) do { if (opt_typecheckverbose) {action;} } while(0)
180 #define DOLOG(action)
183 #ifdef TYPECHECK_VERBOSE
184 #define TYPECHECK_VERBOSE_IMPORTANT
185 #define LOGNL DOLOG(puts(""))
186 #define LOG(str) DOLOG(puts(str);)
187 #define LOG1(str,a) DOLOG(printf(str,a); LOGNL)
188 #define LOG2(str,a,b) DOLOG(printf(str,a,b); LOGNL)
189 #define LOG3(str,a,b,c) DOLOG(printf(str,a,b,c); LOGNL)
190 #define LOGIF(cond,str) DOLOG(do {if (cond) { puts(str); }} while(0))
191 #ifdef TYPEINFO_DEBUG
192 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(stdout,(info)); LOGNL;} while(0))
194 #define LOGINFO(info)
195 #define typevector_print(x,y,z)
197 #define LOGFLUSH DOLOG(fflush(stdout))
198 #define LOGSTR(str) DOLOG(printf("%s", str))
199 #define LOGSTR1(str,a) DOLOG(printf(str,a))
200 #define LOGSTR2(str,a,b) DOLOG(printf(str,a,b))
201 #define LOGSTR3(str,a,b,c) DOLOG(printf(str,a,b,c))
202 #define LOGNAME(c) DOLOG(class_classref_or_classinfo_print(c))
203 #define LOGMETHOD(str,m) DOLOG(printf("%s", str); method_println(m);)
207 #define LOG2(str,a,b)
208 #define LOG3(str,a,b,c)
209 #define LOGIF(cond,str)
210 #define LOGINFO(info)
214 #define LOGSTR1(str,a)
215 #define LOGSTR2(str,a,b)
216 #define LOGSTR3(str,a,b,c)
218 #define LOGMETHOD(str,m)
221 #ifdef TYPECHECK_VERBOSE_IMPORTANT
222 #define LOGimp(str) DOLOG(puts(str);LOGNL)
223 #define LOGimpSTR(str) DOLOG(puts(str))
226 #define LOGimpSTR(str)
229 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
233 static void typecheck_print_var(FILE *file, jitdata *jd, s4 index)
237 assert(index >= 0 && index < jd->varcount);
238 var = jd->var + index;
239 typeinfo_print_type(file, var->type, &(var->typeinfo));
242 static void typecheck_print_vararray(FILE *file, jitdata *jd, s4 *vars, int len)
246 for (i=0; i<len; ++i) {
249 typecheck_print_var(file, jd, *vars++);
256 /****************************************************************************/
258 /****************************************************************************/
260 #ifdef TYPECHECK_DEBUG
261 /*#define TYPECHECK_STATISTICS*/
264 #ifdef TYPECHECK_STATISTICS
265 #define STAT_ITERATIONS 10
266 #define STAT_BLOCKS 10
267 #define STAT_LOCALS 16
269 static int stat_typechecked = 0;
270 static int stat_methods_with_handlers = 0;
271 static int stat_methods_maythrow = 0;
272 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
273 static int stat_reached = 0;
274 static int stat_copied = 0;
275 static int stat_merged = 0;
276 static int stat_merging_changed = 0;
277 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
278 static int stat_locals[STAT_LOCALS+1] = { 0 };
279 static int stat_ins = 0;
280 static int stat_ins_maythrow = 0;
281 static int stat_ins_stack = 0;
282 static int stat_ins_field = 0;
283 static int stat_ins_field_unresolved = 0;
284 static int stat_ins_field_uninitialized = 0;
285 static int stat_ins_invoke = 0;
286 static int stat_ins_invoke_unresolved = 0;
287 static int stat_ins_primload = 0;
288 static int stat_ins_aload = 0;
289 static int stat_ins_builtin = 0;
290 static int stat_ins_builtin_gen = 0;
291 static int stat_ins_branch = 0;
292 static int stat_ins_switch = 0;
293 static int stat_ins_primitive_return = 0;
294 static int stat_ins_areturn = 0;
295 static int stat_ins_areturn_unresolved = 0;
296 static int stat_ins_athrow = 0;
297 static int stat_ins_athrow_unresolved = 0;
298 static int stat_ins_unchecked = 0;
299 static int stat_handlers_reached = 0;
300 static int stat_savedstack = 0;
302 #define TYPECHECK_MARK(var) ((var) = true)
303 #define TYPECHECK_COUNT(cnt) (cnt)++
304 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
305 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
307 if ((val) < (limit)) (array)[val]++; \
308 else (array)[limit]++; \
311 static void print_freq(FILE *file,int *array,int limit)
314 for (i=0; i<limit; ++i)
315 fprintf(file," %3d: %8d\n",i,array[i]);
316 fprintf(file," >=%3d: %8d\n",limit,array[limit]);
319 void typecheck_print_statistics(FILE *file) {
320 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
321 fprintf(file," with handler(s): %8d\n",stat_methods_with_handlers);
322 fprintf(file," with throw(s) : %8d\n",stat_methods_maythrow);
323 fprintf(file,"reached blocks : %8d\n",stat_reached);
324 fprintf(file,"copied states : %8d\n",stat_copied);
325 fprintf(file,"merged states : %8d\n",stat_merged);
326 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
327 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
328 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
329 fprintf(file,"instructions : %8d\n",stat_ins);
330 fprintf(file," stack : %8d\n",stat_ins_stack);
331 fprintf(file," field access : %8d\n",stat_ins_field);
332 fprintf(file," (unresolved) : %8d\n",stat_ins_field_unresolved);
333 fprintf(file," (uninit.) : %8d\n",stat_ins_field_uninitialized);
334 fprintf(file," invocations : %8d\n",stat_ins_invoke);
335 fprintf(file," (unresolved) : %8d\n",stat_ins_invoke_unresolved);
336 fprintf(file," load primitive : (currently not counted) %8d\n",stat_ins_primload);
337 fprintf(file," load address : %8d\n",stat_ins_aload);
338 fprintf(file," builtins : %8d\n",stat_ins_builtin);
339 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
340 fprintf(file," branches : %8d\n",stat_ins_branch);
341 fprintf(file," switches : %8d\n",stat_ins_switch);
342 fprintf(file," prim. return : %8d\n",stat_ins_primitive_return);
343 fprintf(file," areturn : %8d\n",stat_ins_areturn);
344 fprintf(file," (unresolved) : %8d\n",stat_ins_areturn_unresolved);
345 fprintf(file," athrow : %8d\n",stat_ins_athrow);
346 fprintf(file," (unresolved) : %8d\n",stat_ins_athrow_unresolved);
347 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
348 fprintf(file," maythrow : %8d\n",stat_ins_maythrow);
349 fprintf(file,"iterations used:\n");
350 print_freq(file,stat_iterations,STAT_ITERATIONS);
351 fprintf(file,"basic blocks per method / 10:\n");
352 print_freq(file,stat_blocks,STAT_BLOCKS);
353 fprintf(file,"locals:\n");
354 print_freq(file,stat_locals,STAT_LOCALS);
359 #define TYPECHECK_COUNT(cnt)
360 #define TYPECHECK_MARK(var)
361 #define TYPECHECK_COUNTIF(cond,cnt)
362 #define TYPECHECK_COUNT_FREQ(array,val,limit)
366 /****************************************************************************/
367 /* MACROS FOR THROWING EXCEPTIONS */
368 /****************************************************************************/
370 #define TYPECHECK_VERIFYERROR_ret(m,msg,retval) \
372 exceptions_throw_verifyerror((m), (msg)); \
376 #define TYPECHECK_VERIFYERROR_main(msg) TYPECHECK_VERIFYERROR_ret(state.m,(msg),NULL)
377 #define TYPECHECK_VERIFYERROR_bool(msg) TYPECHECK_VERIFYERROR_ret(state->m,(msg),false)
380 /****************************************************************************/
381 /* MACROS FOR VARIABLE TYPE CHECKING */
382 /****************************************************************************/
384 #define TYPECHECK_CHECK_TYPE(i,tp,msg) \
386 if (VAR(i)->type != (tp)) { \
387 exceptions_throw_verifyerror(state->m, (msg)); \
392 #define TYPECHECK_INT(i) \
393 TYPECHECK_CHECK_TYPE(i,TYPE_INT,"Expected to find integer value")
394 #define TYPECHECK_LNG(i) \
395 TYPECHECK_CHECK_TYPE(i,TYPE_LNG,"Expected to find long value")
396 #define TYPECHECK_FLT(i) \
397 TYPECHECK_CHECK_TYPE(i,TYPE_FLT,"Expected to find float value")
398 #define TYPECHECK_DBL(i) \
399 TYPECHECK_CHECK_TYPE(i,TYPE_DBL,"Expected to find double value")
400 #define TYPECHECK_ADR(i) \
401 TYPECHECK_CHECK_TYPE(i,TYPE_ADR,"Expected to find object value")
403 #define TYPECHECK_INT_OP(o) TYPECHECK_INT((o).varindex)
404 #define TYPECHECK_LNG_OP(o) TYPECHECK_LNG((o).varindex)
405 #define TYPECHECK_FLT_OP(o) TYPECHECK_FLT((o).varindex)
406 #define TYPECHECK_DBL_OP(o) TYPECHECK_DBL((o).varindex)
407 #define TYPECHECK_ADR_OP(o) TYPECHECK_ADR((o).varindex)
410 /****************************************************************************/
411 /* VERIFIER STATE STRUCT */
412 /****************************************************************************/
414 /* verifier_state - This structure keeps the current state of the */
415 /* bytecode verifier for passing it between verifier functions. */
417 typedef struct verifier_state {
418 instruction *iptr; /* pointer to current instruction */
419 basicblock *bptr; /* pointer to current basic block */
421 methodinfo *m; /* the current method */
422 jitdata *jd; /* jitdata for current method */
423 codegendata *cd; /* codegendata for current method */
425 basicblock *basicblocks;
428 s4 numlocals; /* number of local variables */
429 s4 validlocals; /* number of Java-accessible locals */
432 typedescriptor returntype; /* return type of the current method */
435 s4 *savedinvars; /* saved invar pointer */
439 exceptiontable **handlers; /* active exception handlers */
441 bool repeat; /* if true, blocks are iterated over again */
442 bool initmethod; /* true if this is an "<init>" method */
444 #ifdef TYPECHECK_STATISTICS
445 bool stat_maythrow; /* at least one instruction may throw */
450 /****************************************************************************/
451 /* TYPESTACK MACROS AND FUNCTIONS */
453 /* These macros and functions act on the 'type stack', which is a shorthand */
454 /* for the types of the stackslots of the current stack. The type of a */
455 /* stack slot is usually described by a TYPE_* constant and -- for TYPE_ADR */
456 /* -- by the typeinfo of the slot. The only thing that makes the type stack */
457 /* more complicated are returnAddresses of local subroutines, because a */
458 /* single stack slot may contain a set of more than one possible return */
459 /* address. This is handled by 'return address sets'. A return address set */
460 /* is kept as a linked list dangling off the typeinfo of the stack slot. */
461 /****************************************************************************/
463 /* typecheck_copy_types ********************************************************
465 Copy the types of the source variables to the destination variables.
468 state............current verifier state
469 srcvars..........array of variable indices to copy
470 dstvars..........array of the destination variables
471 n................number of variables to copy
474 true.............success
475 false............an exception has been thrown
477 *******************************************************************************/
480 typecheck_copy_types(verifier_state *state, s4 *srcvars, s4 *dstvars, s4 n)
485 jitdata *jd = state->jd;
487 for (i=0; i < n; ++i, ++srcvars, ++dstvars) {
492 if (dv->type == TYPE_ADR) {
493 TYPEINFO_CLONE(sv->typeinfo,dv->typeinfo);
500 /* typecheck_merge_types *******************************************************
502 Merge the types of the source variables into the destination variables.
505 state............current state of the verifier
506 srcvars..........source variable indices
507 dstvars..........destination variable indices
508 n................number of variables
511 typecheck_TRUE...the destination variables have been modified
512 typecheck_FALSE..the destination variables are unchanged
513 typecheck_FAIL...an exception has been thrown
515 *******************************************************************************/
517 static typecheck_result
518 typecheck_merge_types(verifier_state *state,s4 *srcvars, s4 *dstvars, s4 n)
523 jitdata *jd = state->jd;
525 bool changed = false;
527 for (i=0; i < n; ++i, ++srcvars, ++dstvars) {
531 if (dv->type != sv->type) {
532 exceptions_throw_verifyerror(state->m,"Stack type mismatch");
533 return typecheck_FAIL;
535 if (dv->type == TYPE_ADR) {
536 if (TYPEINFO_IS_PRIMITIVE(dv->typeinfo)) {
537 /* dv has returnAddress type */
538 if (!TYPEINFO_IS_PRIMITIVE(sv->typeinfo)) {
539 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
540 return typecheck_FAIL;
544 /* dv has reference type */
545 if (TYPEINFO_IS_PRIMITIVE(sv->typeinfo)) {
546 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
547 return typecheck_FAIL;
549 r = typeinfo_merge(state->m,&(dv->typeinfo),&(sv->typeinfo));
550 if (r == typecheck_FAIL)
560 /* typestate_merge *************************************************************
562 Merge the types of one state into the destination state.
565 state............current state of the verifier
566 dstvars..........indices of the destinations invars
567 dstlocals........the destinations inlocals
568 srcvars..........indices of the source's outvars
569 srclocals........the source locals
570 n................number of invars (== number of outvars)
573 typecheck_TRUE...destination state has been modified
574 typecheck_FALSE..destination state has not been modified
575 typecheck_FAIL...an exception has been thrown
577 *******************************************************************************/
579 static typecheck_result
580 typestate_merge(verifier_state *state,
581 s4 *srcvars, varinfo *srclocals,
582 s4 *dstvars, varinfo *dstlocals,
585 bool changed = false;
588 /* The stack is always merged. If there are returnAddresses on
589 * the stack they are ignored in this step. */
591 r = typecheck_merge_types(state, srcvars, dstvars, n);
592 if (r == typecheck_FAIL)
596 /* merge the locals */
598 r = typevector_merge(state->m, dstlocals, srclocals, state->numlocals);
599 if (r == typecheck_FAIL)
605 /* typestate_reach *************************************************************
607 Reach a destination block and propagate stack and local variable types
610 state............current state of the verifier
611 destblock........destination basic block
612 srcvars..........variable indices of the outvars to propagate
613 srclocals........local variables to propagate
614 n................number of srcvars
617 state->repeat....set to true if the verifier must iterate again
618 over the basic blocks
621 true.............success
622 false............an exception has been thrown
624 *******************************************************************************/
627 typestate_reach(verifier_state *state,
628 basicblock *destblock,
629 s4 *srcvars, varinfo *srclocals, s4 n)
632 bool changed = false;
635 LOG1("reaching block L%03d",destblock->nr);
636 TYPECHECK_COUNT(stat_reached);
638 destloc = destblock->inlocals;
640 if (destblock->flags == BBTYPECHECK_UNDEF) {
641 /* The destblock has never been reached before */
643 TYPECHECK_COUNT(stat_copied);
644 LOG1("block L%03d reached first time",destblock->nr);
646 if (!typecheck_copy_types(state, srcvars, destblock->invars, n))
648 typevector_copy_inplace(srclocals, destloc, state->numlocals);
652 /* The destblock has already been reached before */
654 TYPECHECK_COUNT(stat_merged);
655 LOG1("block L%03d reached before", destblock->nr);
657 r = typestate_merge(state, srcvars, srclocals,
658 destblock->invars, destblock->inlocals, n);
659 if (r == typecheck_FAIL)
662 TYPECHECK_COUNTIF(changed,stat_merging_changed);
667 destblock->flags = BBTYPECHECK_REACHED;
668 if (destblock <= state->bptr) {
670 state->repeat = true;
677 /* typestate_save_invars *******************************************************
679 Save the invars of the current basic block in the space reserved by
682 This function must be called before an instruction modifies a variable
683 that is an invar of the current block. In such cases the invars of the
684 block must be saved, and restored at the end of the analysis of this
685 basic block, so that the invars again reflect the *input* to this basic
686 block (and do not randomly contain types that appear within the block).
689 state............current state of the verifier
691 *******************************************************************************/
694 typestate_save_invars(verifier_state *state)
699 LOG("saving invars");
701 if (!state->savedindices) {
702 LOG("allocating savedindices buffer");
703 pindex = DMNEW(s4, state->m->maxstack);
704 state->savedindices = pindex;
705 index = state->numlocals + VERIFIER_EXTRA_VARS;
706 for (i=0; i<state->m->maxstack; ++i)
712 typecheck_copy_types(state, state->bptr->invars, state->savedindices,
713 state->bptr->indepth);
715 /* set the invars of the block to the saved variables */
716 /* and remember the original invars */
718 state->savedinvars = state->bptr->invars;
719 state->bptr->invars = state->savedindices;
723 /* typestate_restore_invars ***************************************************
725 Restore the invars of the current basic block that have been previously
726 saved by `typestate_save_invars`.
729 state............current state of the verifier
731 *******************************************************************************/
734 typestate_restore_invars(verifier_state *state)
736 TYPECHECK_COUNT(stat_savedstack);
737 LOG("restoring saved invars");
739 /* restore the invars pointer */
741 state->bptr->invars = state->savedinvars;
743 /* copy the types back */
745 typecheck_copy_types(state, state->savedindices, state->bptr->invars,
746 state->bptr->indepth);
748 /* mark that there are no saved invars currently */
750 state->savedinvars = NULL;
754 /****************************************************************************/
756 /****************************************************************************/
758 #define COPYTYPE(source,dest) \
759 {if (VAROP(source)->type == TYPE_ADR) \
760 TYPEINFO_COPY(VAROP(source)->typeinfo,VAROP(dest)->typeinfo);}
762 #define ISBUILTIN(v) (bte->fp == (functionptr) (v))
765 /* verify_invocation ***********************************************************
767 Verify an ICMD_INVOKE* instruction.
770 state............the current state of the verifier
773 true.............successful verification,
774 false............an exception has been thrown.
776 *******************************************************************************/
779 verify_invocation(verifier_state *state)
781 unresolved_method *um; /* struct describing the called method */
782 constant_FMIref *mref; /* reference to the called method */
783 methodinfo *mi; /* resolved method (if any) */
784 methoddesc *md; /* descriptor of the called method */
785 utf *mname; /* method name */
786 utf *mclassname; /* name of the method's class */
787 bool specialmethod; /* true if a <...> method is called */
788 int opcode; /* invocation opcode */
789 bool callinginit; /* true if <init> is called */
791 classref_or_classinfo initclass;
793 s4 argindex; /* argument variable index */
794 varinfo *av; /* argument variable */
795 varinfo *dv; /* result variable of the invocation */
797 u1 rtype; /* return type of called method */
798 resolve_result_t result;
803 /* get the FMIref and the unresolved_method struct (if any) */
804 /* from the instruction */
806 if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
807 /* unresolved method */
808 um = state->iptr->sx.s23.s3.um;
809 mref = um->methodref;
812 /* resolved method */
814 mref = state->iptr->sx.s23.s3.fmiref;
817 /* get method descriptor and name */
819 md = mref->parseddesc.md;
822 /* get method info (if resolved) and classname */
824 if (IS_FMIREF_RESOLVED(mref)) {
826 mclassname = mi->class->name;
830 mclassname = mref->p.classref->name;
833 specialmethod = (mname->text[0] == '<');
834 opcode = state->iptr[0].opc;
835 dv = VAROP(state->iptr->dst);
837 /* prevent compiler warnings */
841 /* check whether we are calling <init> */
843 callinginit = (opcode == ICMD_INVOKESPECIAL && mname == utf_init);
844 if (specialmethod && !callinginit)
845 TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
847 /* allocate parameters if necessary */
850 if (!descriptor_params_from_paramtypes(md,
851 (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
854 /* check parameter types */
856 i = md->paramcount; /* number of parameters including 'this'*/
859 argindex = state->iptr->sx.s23.s2.args[i];
861 td = md->paramtypes + i;
863 if (av->type != td->type)
864 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
866 if (av->type == TYPE_ADR) {
867 LOGINFO(&(av->typeinfo));
868 if (i==0 && callinginit)
870 /* first argument to <init> method */
871 if (!TYPEINFO_IS_NEWOBJECT(av->typeinfo))
872 TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
874 /* get the address of the NEW instruction */
875 LOGINFO(&(av->typeinfo));
876 ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo);
878 initclass = ins[-1].sx.val.c;
880 initclass.cls = state->m->class;
881 LOGSTR("class: "); LOGNAME(initclass); LOGNL;
885 /* non-adress argument. if this is the first argument and we are */
886 /* invoking an instance method, this is an error. */
887 if (i==0 && opcode != ICMD_INVOKESTATIC) {
888 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch for 'this' argument");
895 LOG("replacing uninitialized object");
896 /* replace uninitialized object type on stack */
898 /* for all live-in and live-through variables */
899 for (i=0; i<state->iptr->s1.argcount; ++i) {
900 argindex = state->iptr->sx.s23.s2.args[i];
902 if (av->type == TYPE_ADR
903 && TYPEINFO_IS_NEWOBJECT(av->typeinfo)
904 && TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo) == ins)
906 LOG("replacing uninitialized type");
908 /* If this stackslot is in the instack of
909 * this basic block we must save the type(s)
910 * we are going to replace.
912 /* XXX this needs a new check */
913 if (state->bptr->invars
914 && argindex >= state->bptr->invars[0]
915 && argindex < state->bptr->varstart
916 && !state->savedinvars)
918 typestate_save_invars(state);
921 if (!typeinfo_init_class(&(av->typeinfo),initclass))
926 /* replace uninitialized object type in locals */
927 if (!typevector_init_object(state->jd->var, ins, initclass,
931 /* initializing the 'this' reference? */
934 TYPECHECK_ASSERT(state->initmethod);
935 /* { we are initializing the 'this' reference } */
936 /* must be <init> of current class or direct superclass */
937 /* the current class is linked, so must be its superclass. thus we can be */
938 /* sure that resolving will be trivial. */
943 if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
944 return false; /* exception */
947 /* if lazy resolving did not succeed, it's not one of the allowed classes */
948 /* otherwise we check it directly */
949 if (cls == NULL || (cls != state->m->class && cls != state->m->class->super.cls)) {
950 TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
953 /* set our marker variable to type int */
954 LOG("setting <init> marker");
955 typevector_store(jd->var, state->numlocals-1, TYPE_INT, NULL);
958 /* { we are initializing an instance created with NEW } */
959 if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mclassname) {
960 TYPECHECK_VERIFYERROR_bool("wrong <init> called for uninitialized reference");
965 /* try to resolve the method lazily */
967 result = new_resolve_method_lazy(jd, state->iptr, state->m);
968 if (result == resolveFailed)
971 if (result != resolveSucceeded) {
973 um = new_create_unresolved_method(state->m->class,
974 state->m, state->iptr);
980 /* record subtype constraints for parameters */
982 if (!new_constrain_unresolved_method(jd, um, state->m->class,
983 state->m, state->iptr))
984 return false; /* XXX maybe wrap exception */
986 /* store the unresolved_method pointer */
988 state->iptr->sx.s23.s3.um = um;
989 state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
992 assert(IS_FMIREF_RESOLVED(state->iptr->sx.s23.s3.fmiref));
995 rtype = md->returntype.type;
996 if (rtype != TYPE_VOID) {
998 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
1006 /* verify_generic_builtin ******************************************************
1008 Verify the call of a generic builtin method.
1011 state............the current state of the verifier
1014 true.............successful verification,
1015 false............an exception has been thrown.
1017 *******************************************************************************/
1020 verify_generic_builtin(verifier_state *state)
1022 builtintable_entry *bte;
1027 jitdata *jd = state->jd;
1029 TYPECHECK_COUNT(stat_ins_builtin_gen);
1031 bte = state->iptr->sx.s23.s3.bte;
1035 /* check the types of the arguments on the stack */
1037 for (i--; i >= 0; i--) {
1038 av = VAR(state->iptr->sx.s23.s2.args[i]);
1040 if (av->type != md->paramtypes[i].type) {
1041 TYPECHECK_VERIFYERROR_bool("parameter type mismatch for builtin method");
1044 #ifdef TYPECHECK_DEBUG
1045 /* generic builtins may only take primitive types and java.lang.Object references */
1046 if (av->type == TYPE_ADR && md->paramtypes[i].classref->name != utf_java_lang_Object) {
1047 *exceptionptr = new_internalerror("generic builtin method with non-generic reference parameter");
1053 /* set the return type */
1055 rtype = md->returntype.type;
1056 if (rtype != TYPE_VOID) {
1059 dv = VAROP(state->iptr->dst);
1061 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
1069 /* verify_builtin **************************************************************
1071 Verify the call of a builtin method.
1074 state............the current state of the verifier
1077 true.............successful verification,
1078 false............an exception has been thrown.
1080 *******************************************************************************/
1083 verify_builtin(verifier_state *state)
1085 builtintable_entry *bte;
1086 classref_or_classinfo cls;
1087 varinfo *dv; /* output variable of current instruction */
1088 jitdata *jd = state->jd;
1090 bte = state->iptr->sx.s23.s3.bte;
1091 dv = VAROP(state->iptr->dst);
1093 /* XXX this is an ugly if-chain but twisti did not want a function */
1094 /* pointer in builtintable_entry for this, so here you go.. ;) */
1096 if (ISBUILTIN(BUILTIN_new)) {
1097 if (state->iptr[-1].opc != ICMD_ACONST)
1098 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without class");
1099 cls = state->iptr[-1].sx.val.c;
1100 dv->type = TYPE_ADR;
1101 TYPEINFO_INIT_NEWOBJECT(dv->typeinfo,state->iptr);
1103 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1104 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1105 dv->type = TYPE_ADR;
1106 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BOOLEAN);
1108 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1109 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1110 dv->type = TYPE_ADR;
1111 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_CHAR);
1113 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1114 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1115 dv->type = TYPE_ADR;
1116 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_FLOAT);
1118 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1119 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1120 dv->type = TYPE_ADR;
1121 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_DOUBLE);
1123 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1124 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1125 dv->type = TYPE_ADR;
1126 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BYTE);
1128 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1129 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1130 dv->type = TYPE_ADR;
1131 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_SHORT);
1133 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1134 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1135 dv->type = TYPE_ADR;
1136 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_INT);
1138 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1139 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1140 dv->type = TYPE_ADR;
1141 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_LONG);
1143 else if (ISBUILTIN(BUILTIN_newarray))
1145 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1146 if (state->iptr[-1].opc != ICMD_ACONST)
1147 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without class");
1148 /* XXX check that it is an array class(ref) */
1149 dv->type = TYPE_ADR;
1150 typeinfo_init_class(&(dv->typeinfo),state->iptr[-1].sx.val.c);
1152 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1154 TYPECHECK_ADR(state->iptr->sx.s23.s2.args[0]);
1155 if (state->iptr[-1].opc != ICMD_ACONST)
1156 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without class");
1157 dv->type = TYPE_INT;
1158 /* XXX check that it is an array class(ref) */
1161 return verify_generic_builtin(state);
1167 /* verify_multianewarray *******************************************************
1169 Verify a MULTIANEWARRAY instruction.
1172 state............the current state of the verifier
1175 true.............successful verification,
1176 false............an exception has been thrown.
1178 *******************************************************************************/
1181 verify_multianewarray(verifier_state *state)
1183 classinfo *arrayclass;
1184 arraydescriptor *desc;
1186 jitdata *jd = state->jd;
1188 /* check the array lengths on the stack */
1189 i = state->iptr->s1.argcount;
1191 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
1194 TYPECHECK_INT(state->iptr->sx.s23.s2.args[i]);
1197 /* check array descriptor */
1198 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
1199 /* the array class reference has already been resolved */
1200 arrayclass = state->iptr->sx.s23.s3.c.cls;
1202 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
1203 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
1204 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1205 if (desc->dimension < state->iptr->s1.argcount)
1206 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1208 /* set the array type of the result */
1209 typeinfo_init_classinfo(&(VAROP(state->iptr->dst)->typeinfo), arrayclass);
1213 constant_classref *cr;
1215 /* the array class reference is still unresolved */
1216 /* check that the reference indicates an array class of correct dimension */
1217 cr = state->iptr->sx.s23.s3.c.ref;
1222 /* { the dimension of the array class == i } */
1224 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1225 if (i < state->iptr->s1.argcount)
1226 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1228 /* set the array type of the result */
1229 if (!typeinfo_init_class(&(VAROP(state->iptr->dst)->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
1233 /* set return type */
1235 VAROP(state->iptr->dst)->type = TYPE_ADR;
1242 /* typecheck_invalidate_locals *************************************************
1244 Invalidate locals that are overwritten by writing to the given local.
1247 state............the current state of the verifier
1248 index............the index of the local that is written
1249 twoword..........true, if a two-word type is written
1251 *******************************************************************************/
1253 static void typecheck_invalidate_locals(verifier_state *state, s4 index, bool twoword)
1258 jitdata *jd = state->jd;
1259 s4 *localmap = jd->local_map;
1260 varinfo *vars = jd->var;
1262 i = state->reverselocalmap[index];
1264 /* invalidate locals of two-word type at index i-1 */
1267 localmap += 5 * (i-1);
1268 for (t=0; t<5; ++t) {
1269 mapped = *localmap++;
1270 if (mapped >= 0 && IS_2_WORD_TYPE(vars[mapped].type)) {
1271 LOG1("invalidate local %d", mapped);
1272 vars[mapped].type = TYPE_VOID;
1280 /* invalidate locals at index i */
1282 for (t=0; t<5; ++t) {
1283 mapped = *localmap++;
1285 LOG1("invalidate local %d", mapped);
1286 vars[mapped].type = TYPE_VOID;
1290 /* if a two-word type is written, invalidate locals at index i+1 */
1293 for (t=0; t<5; ++t) {
1294 mapped = *localmap++;
1296 LOG1("invalidate local %d", mapped);
1297 vars[mapped].type = TYPE_VOID;
1304 /* verify_basic_block **********************************************************
1306 Perform bytecode verification of a basic block.
1309 state............the current state of the verifier
1312 true.............successful verification,
1313 false............an exception has been thrown.
1315 *******************************************************************************/
1318 verify_basic_block(verifier_state *state)
1320 int opcode; /* current opcode */
1321 int len; /* for counting instructions, etc. */
1322 bool superblockend; /* true if no fallthrough to next block */
1323 instruction *iptr; /* the current instruction */
1324 basicblock *tbptr; /* temporary for target block */
1325 bool maythrow; /* true if this instruction may throw */
1326 unresolved_field *uf; /* for field accesses */
1327 constant_FMIref *fieldref; /* for field accesses */
1330 resolve_result_t result;
1331 branch_target_t *table;
1332 lookup_target_t *lookup;
1333 jitdata *jd = state->jd;
1337 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
1339 DOLOG(new_show_basicblock(jd, state->bptr, SHOW_STACK));
1341 superblockend = false;
1342 state->bptr->flags = BBFINISHED;
1344 /* prevent compiler warnings */
1348 /* determine the active exception handlers for this block */
1349 /* XXX could use a faster algorithm with sorted lists or */
1352 for (ex = state->cd->exceptiontable; ex ; ex = ex->down) {
1353 if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
1354 LOG1("active handler L%03d", ex->handler->nr);
1355 state->handlers[len++] = ex;
1358 state->handlers[len] = NULL;
1360 /* init variable types at the start of this block */
1361 typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
1363 DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars,
1364 state->bptr->indepth));
1365 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
1368 /* loop over the instructions */
1369 len = state->bptr->icount;
1370 state->iptr = state->bptr->iinstr;
1371 while (--len >= 0) {
1372 TYPECHECK_COUNT(stat_ins);
1376 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
1378 DOLOG(new_show_icmd(jd, state->iptr, false, SHOW_STACK)); LOGNL; LOGFLUSH;
1381 dv = VAROP(iptr->dst);
1386 /****************************************/
1387 /* STACK MANIPULATIONS */
1389 /* We just need to copy the typeinfo */
1390 /* for slots containing addresses. */
1394 TYPECHECK_COUNT(stat_ins_stack);
1395 COPYTYPE(iptr->s1, iptr->dst);
1396 dv->type = VAROP(iptr->s1)->type;
1399 /****************************************/
1400 /* PRIMITIVE VARIABLE ACCESS */
1402 case ICMD_ILOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_INT))
1403 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1404 dv->type = TYPE_INT;
1406 case ICMD_IINC: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_INT))
1407 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1408 dv->type = TYPE_INT;
1410 case ICMD_FLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_FLT))
1411 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1412 dv->type = TYPE_FLT;
1414 case ICMD_LLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_LNG))
1415 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1416 dv->type = TYPE_LNG;
1418 case ICMD_DLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_DBL))
1419 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1420 dv->type = TYPE_DBL;
1424 typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
1425 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_INT,NULL);
1428 typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
1429 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_FLT,NULL);
1432 typecheck_invalidate_locals(state, state->iptr->dst.varindex, true);
1433 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_LNG,NULL);
1436 typecheck_invalidate_locals(state, state->iptr->dst.varindex, true);
1437 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_DBL,NULL);
1440 /****************************************/
1441 /* LOADING ADDRESS FROM VARIABLE */
1444 TYPECHECK_COUNT(stat_ins_aload);
1446 /* loading a returnAddress is not allowed */
1447 if (!TYPEDESC_IS_REFERENCE(jd->var[state->iptr->s1.varindex])) {
1448 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1450 TYPEINFO_COPY(jd->var[state->iptr->s1.varindex].typeinfo,dv->typeinfo);
1451 dv->type = TYPE_ADR;
1454 /****************************************/
1455 /* STORING ADDRESS TO VARIABLE */
1458 typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
1460 if (TYPEINFO_IS_PRIMITIVE(VAROP(state->iptr->s1)->typeinfo)) {
1461 typevector_store_retaddr(jd->var,state->iptr->dst.varindex,&(VAROP(state->iptr->s1)->typeinfo));
1464 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_ADR,
1465 &(VAROP(state->iptr->s1)->typeinfo));
1469 /****************************************/
1470 /* LOADING ADDRESS FROM ARRAY */
1473 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(VAROP(state->iptr->s1)->typeinfo))
1474 TYPECHECK_VERIFYERROR_bool("illegal instruction: AALOAD on non-reference array");
1476 if (!typeinfo_init_component(&VAROP(state->iptr->s1)->typeinfo,&dv->typeinfo))
1478 dv->type = TYPE_ADR;
1482 /****************************************/
1486 case ICMD_PUTSTATIC:
1487 case ICMD_PUTFIELDCONST:
1488 case ICMD_PUTSTATICCONST:
1490 case ICMD_GETSTATIC:
1491 TYPECHECK_COUNT(stat_ins_field);
1493 if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
1494 uf = state->iptr->sx.s23.s3.uf;
1495 fieldref = uf->fieldref;
1499 fieldref = state->iptr->sx.s23.s3.fmiref;
1502 /* try to resolve the field reference lazily */
1503 result = new_resolve_field_lazy(jd, state->iptr, state->m);
1504 if (result == resolveFailed)
1507 if (result != resolveSucceeded) {
1509 uf = new_create_unresolved_field(state->m->class, state->m, state->iptr);
1513 state->iptr->sx.s23.s3.uf = uf;
1514 state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
1517 /* record the subtype constraints for this field access */
1518 if (!new_constrain_unresolved_field(jd, uf,state->m->class,state->m,state->iptr))
1519 return false; /* XXX maybe wrap exception? */
1521 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(state->iptr),stat_ins_field_unresolved);
1522 TYPECHECK_COUNTIF(INSTRUCTION_IS_RESOLVED(state->iptr) && !state->iptr->sx.s23.s3.fmiref->p.field->class->initialized,stat_ins_field_uninitialized);
1525 if (iptr->opc == ICMD_GETFIELD || iptr->opc == ICMD_GETSTATIC) {
1526 /* write the result type */
1527 dv->type = fieldref->parseddesc.fd->type;
1528 if (dv->type == TYPE_ADR) {
1529 if (!typeinfo_init_from_typedesc(fieldref->parseddesc.fd,NULL,&(dv->typeinfo)))
1537 /****************************************/
1538 /* PRIMITIVE ARRAY ACCESS */
1540 case ICMD_ARRAYLENGTH:
1541 if (!TYPEINFO_MAYBE_ARRAY(VAROP(state->iptr->s1)->typeinfo)
1542 && VAROP(state->iptr->s1)->typeinfo.typeclass.cls != pseudo_class_Arraystub)
1543 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARRAYLENGTH on non-array");
1544 dv->type = TYPE_INT;
1549 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BOOLEAN)
1550 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BYTE))
1551 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1552 dv->type = TYPE_INT;
1556 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_CHAR))
1557 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1558 dv->type = TYPE_INT;
1562 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_DOUBLE))
1563 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1564 dv->type = TYPE_DBL;
1568 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_FLOAT))
1569 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1570 dv->type = TYPE_FLT;
1574 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_INT))
1575 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1576 dv->type = TYPE_INT;
1580 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_SHORT))
1581 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1582 dv->type = TYPE_INT;
1586 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_LONG))
1587 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1588 dv->type = TYPE_LNG;
1593 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BOOLEAN)
1594 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BYTE))
1595 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1599 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_CHAR))
1600 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1604 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_DOUBLE))
1605 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1609 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_FLOAT))
1610 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1614 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_INT))
1615 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1619 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_SHORT))
1620 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1624 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_LONG))
1625 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1630 /* we just check the basic input types and that the */
1631 /* destination is an array of references. Assignability to */
1632 /* the actual array must be checked at runtime, each time the */
1633 /* instruction is performed. (See builtin_canstore.) */
1634 TYPECHECK_ADR_OP(state->iptr->sx.s23.s3);
1635 TYPECHECK_INT_OP(state->iptr->sx.s23.s2);
1636 TYPECHECK_ADR_OP(state->iptr->s1);
1637 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(VAROP(state->iptr->s1)->typeinfo))
1638 TYPECHECK_VERIFYERROR_bool("illegal instruction: AASTORE to non-reference array");
1642 case ICMD_IASTORECONST:
1643 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_INT))
1644 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1648 case ICMD_LASTORECONST:
1649 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_LONG))
1650 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1654 case ICMD_BASTORECONST:
1655 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_BOOLEAN)
1656 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_BYTE))
1657 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1661 case ICMD_CASTORECONST:
1662 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_CHAR))
1663 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1667 case ICMD_SASTORECONST:
1668 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_SHORT))
1669 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1673 /****************************************/
1674 /* ADDRESS CONSTANTS */
1677 if (state->iptr->flags.bits & INS_FLAG_CLASS) {
1678 /* a java.lang.Class reference */
1679 TYPEINFO_INIT_JAVA_LANG_CLASS(dv->typeinfo,state->iptr->sx.val.c);
1682 if (state->iptr->sx.val.anyptr == NULL)
1683 TYPEINFO_INIT_NULLTYPE(dv->typeinfo);
1685 /* string constant (or constant for builtin function) */
1686 typeinfo_init_classinfo(&(dv->typeinfo),class_java_lang_String);
1689 dv->type = TYPE_ADR;
1692 /****************************************/
1693 /* CHECKCAST AND INSTANCEOF */
1695 case ICMD_CHECKCAST:
1696 TYPECHECK_ADR_OP(state->iptr->s1);
1697 /* returnAddress is not allowed */
1698 if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
1699 TYPECHECK_VERIFYERROR_bool("Illegal instruction: CHECKCAST on non-reference");
1701 if (!typeinfo_init_class(&(dv->typeinfo),state->iptr->sx.s23.s3.c))
1703 dv->type = TYPE_ADR;
1707 case ICMD_INSTANCEOF:
1708 TYPECHECK_ADR_OP(state->iptr->s1);
1709 /* returnAddress is not allowed */
1710 if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
1711 TYPECHECK_VERIFYERROR_bool("Illegal instruction: INSTANCEOF on non-reference");
1712 dv->type = TYPE_INT;
1715 /****************************************/
1716 /* BRANCH INSTRUCTIONS */
1718 case ICMD_INLINE_GOTO:
1719 COPYTYPE(state->iptr->s1,state->iptr->dst);
1722 superblockend = true;
1725 case ICMD_IFNONNULL:
1732 case ICMD_IF_ICMPEQ:
1733 case ICMD_IF_ICMPNE:
1734 case ICMD_IF_ICMPLT:
1735 case ICMD_IF_ICMPGE:
1736 case ICMD_IF_ICMPGT:
1737 case ICMD_IF_ICMPLE:
1738 case ICMD_IF_ACMPEQ:
1739 case ICMD_IF_ACMPNE:
1748 case ICMD_IF_LCMPEQ:
1749 case ICMD_IF_LCMPNE:
1750 case ICMD_IF_LCMPLT:
1751 case ICMD_IF_LCMPGE:
1752 case ICMD_IF_LCMPGT:
1753 case ICMD_IF_LCMPLE:
1755 case ICMD_IF_FCMPEQ:
1756 case ICMD_IF_FCMPNE:
1758 case ICMD_IF_FCMPL_LT:
1759 case ICMD_IF_FCMPL_GE:
1760 case ICMD_IF_FCMPL_GT:
1761 case ICMD_IF_FCMPL_LE:
1763 case ICMD_IF_FCMPG_LT:
1764 case ICMD_IF_FCMPG_GE:
1765 case ICMD_IF_FCMPG_GT:
1766 case ICMD_IF_FCMPG_LE:
1768 case ICMD_IF_DCMPEQ:
1769 case ICMD_IF_DCMPNE:
1771 case ICMD_IF_DCMPL_LT:
1772 case ICMD_IF_DCMPL_GE:
1773 case ICMD_IF_DCMPL_GT:
1774 case ICMD_IF_DCMPL_LE:
1776 case ICMD_IF_DCMPG_LT:
1777 case ICMD_IF_DCMPG_GE:
1778 case ICMD_IF_DCMPG_GT:
1779 case ICMD_IF_DCMPG_LE:
1780 TYPECHECK_COUNT(stat_ins_branch);
1782 /* propagate stack and variables to the target block */
1783 if (!typestate_reach(state, state->iptr->dst.block,
1784 state->bptr->outvars, jd->var,
1785 state->bptr->outdepth))
1789 /****************************************/
1792 case ICMD_TABLESWITCH:
1793 TYPECHECK_COUNT(stat_ins_switch);
1795 table = iptr->dst.table;
1796 i = iptr->sx.s23.s3.tablehigh
1797 - iptr->sx.s23.s2.tablelow + 1 + 1; /* plus default */
1800 tbptr = (table++)->block;
1801 LOG2("target %d is block %04d",i,tbptr->nr);
1802 if (!typestate_reach(state, tbptr, state->bptr->outvars,
1803 jd->var, state->bptr->outdepth))
1808 superblockend = true;
1811 case ICMD_LOOKUPSWITCH:
1812 TYPECHECK_COUNT(stat_ins_switch);
1814 lookup = iptr->dst.lookup;
1815 i = iptr->sx.s23.s2.lookupcount;
1817 if (!typestate_reach(state,iptr->sx.s23.s3.lookupdefault.block,
1818 state->bptr->outvars, jd->var,
1819 state->bptr->outdepth))
1823 tbptr = (lookup++)->target.block;
1824 LOG2("target %d is block %04d",i,tbptr->nr);
1825 if (!typestate_reach(state, tbptr, state->bptr->outvars,
1826 jd->var, state->bptr->outdepth))
1831 superblockend = true;
1835 /****************************************/
1836 /* ADDRESS RETURNS AND THROW */
1839 TYPECHECK_COUNT(stat_ins_athrow);
1840 r = typeinfo_is_assignable_to_class(&VAROP(state->iptr->s1)->typeinfo,
1841 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
1842 if (r == typecheck_FALSE)
1843 TYPECHECK_VERIFYERROR_bool("illegal instruction: ATHROW on non-Throwable");
1844 if (r == typecheck_FAIL)
1846 if (r == typecheck_MAYBE) {
1847 /* the check has to be postponed. we need a patcher */
1848 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
1849 iptr->sx.s23.s2.uc = create_unresolved_class(
1851 /* XXX make this more efficient, use class_java_lang_Throwable
1853 class_get_classref(state->m->class,utf_java_lang_Throwable),
1854 &VAROP(state->iptr->s1)->typeinfo);
1855 iptr->flags.bits |= INS_FLAG_UNRESOLVED;
1857 superblockend = true;
1862 TYPECHECK_COUNT(stat_ins_areturn);
1863 if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
1864 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARETURN on non-reference");
1866 if (state->returntype.type != TYPE_ADR
1867 || (r = typeinfo_is_assignable(&VAROP(state->iptr->s1)->typeinfo,&(state->returntype.typeinfo)))
1869 TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1870 if (r == typecheck_FAIL)
1872 if (r == typecheck_MAYBE) {
1873 /* the check has to be postponed, we need a patcher */
1874 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
1875 iptr->sx.s23.s2.uc = create_unresolved_class(
1877 state->m->parseddesc->returntype.classref,
1878 &VAROP(state->iptr->s1)->typeinfo);
1879 iptr->flags.bits |= INS_FLAG_UNRESOLVED;
1883 /****************************************/
1884 /* PRIMITIVE RETURNS */
1887 if (state->returntype.type != TYPE_INT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1891 if (state->returntype.type != TYPE_LNG) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1895 if (state->returntype.type != TYPE_FLT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1899 if (state->returntype.type != TYPE_DBL) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1903 if (state->returntype.type != TYPE_VOID) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
1905 TYPECHECK_COUNT(stat_ins_primitive_return);
1907 if (state->initmethod && state->m->class != class_java_lang_Object) {
1908 /* Check if the 'this' instance has been initialized. */
1909 LOG("Checking <init> marker");
1910 if (!typevector_checktype(jd->var,state->numlocals-1,TYPE_INT))
1911 TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'");
1914 superblockend = true;
1918 /****************************************/
1919 /* SUBROUTINE INSTRUCTIONS */
1924 tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
1925 TYPEINFO_INIT_RETURNADDRESS(dv->typeinfo, state->bptr->next);
1926 if (!typestate_reach(state, tbptr, state->bptr->outvars, jd->var,
1927 state->bptr->outdepth))
1930 superblockend = true;
1934 /* check returnAddress variable */
1935 if (!typevector_checkretaddr(jd->var,state->iptr->s1.varindex))
1936 TYPECHECK_VERIFYERROR_bool("illegal instruction: RET using non-returnAddress variable");
1938 if (!typestate_reach(state, iptr->dst.block, state->bptr->outvars, jd->var,
1939 state->bptr->outdepth))
1942 superblockend = true;
1945 /****************************************/
1948 case ICMD_INVOKEVIRTUAL:
1949 case ICMD_INVOKESPECIAL:
1950 case ICMD_INVOKESTATIC:
1951 case ICMD_INVOKEINTERFACE:
1952 TYPECHECK_COUNT(stat_ins_invoke);
1953 if (!verify_invocation(state))
1955 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(iptr), stat_ins_invoke_unresolved);
1959 /****************************************/
1960 /* MULTIANEWARRAY */
1962 case ICMD_MULTIANEWARRAY:
1963 if (!verify_multianewarray(state))
1968 /****************************************/
1972 TYPECHECK_COUNT(stat_ins_builtin);
1973 if (!verify_builtin(state))
1978 /****************************************/
1979 /* SIMPLE EXCEPTION THROWING TESTS */
1981 case ICMD_CHECKNULL:
1982 /* CHECKNULL just requires that the stack top
1983 * is an address. This is checked in stack.c */
1987 /****************************************/
1988 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
1989 /* REPLACED BY OTHER OPCODES */
1991 #ifdef TYPECHECK_DEBUG
1994 case ICMD_ANEWARRAY:
1995 case ICMD_MONITORENTER:
1996 case ICMD_MONITOREXIT:
1997 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
1998 LOG("Should have been converted to builtin function call.");
1999 TYPECHECK_ASSERT(false);
2003 /****************************************/
2004 /* UNCHECKED OPERATIONS */
2006 /*********************************************
2007 * Instructions below...
2008 * *) don't operate on local variables,
2009 * *) don't operate on references,
2010 * *) don't operate on returnAddresses,
2011 * *) don't affect control flow (except
2012 * by throwing exceptions).
2014 * (These instructions are typechecked in
2016 ********************************************/
2018 /* Instructions which may throw a runtime exception: */
2022 dv->type = TYPE_INT;
2028 dv->type = TYPE_LNG;
2032 /* Instructions which never throw a runtime exception: */
2051 case ICMD_IADDCONST:
2052 case ICMD_ISUBCONST:
2053 case ICMD_IMULCONST:
2054 case ICMD_IANDCONST:
2056 case ICMD_IXORCONST:
2057 case ICMD_ISHLCONST:
2058 case ICMD_ISHRCONST:
2059 case ICMD_IUSHRCONST:
2063 case ICMD_INT2SHORT:
2068 case ICMD_LCMPCONST:
2073 dv->type = TYPE_INT;
2089 case ICMD_LADDCONST:
2090 case ICMD_LSUBCONST:
2091 case ICMD_LMULCONST:
2092 case ICMD_LANDCONST:
2094 case ICMD_LXORCONST:
2095 case ICMD_LSHLCONST:
2096 case ICMD_LSHRCONST:
2097 case ICMD_LUSHRCONST:
2102 dv->type = TYPE_LNG;
2115 dv->type = TYPE_FLT;
2128 dv->type = TYPE_DBL;
2131 case ICMD_INLINE_START:
2132 case ICMD_INLINE_END:
2135 /* XXX What shall we do with the following ?*/
2136 case ICMD_AASTORECONST:
2137 TYPECHECK_COUNT(stat_ins_unchecked);
2140 /****************************************/
2143 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2144 TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
2147 /* reach exception handlers for this instruction */
2150 TYPECHECK_COUNT(stat_ins_maythrow);
2151 TYPECHECK_MARK(state->stat_maythrow);
2152 LOG("reaching exception handlers");
2154 while (state->handlers[i]) {
2155 TYPECHECK_COUNT(stat_handlers_reached);
2156 if (state->handlers[i]->catchtype.any)
2157 VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
2159 VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
2160 if (!typestate_reach(state,
2161 state->handlers[i]->handler,
2162 &(state->exinvars), jd->var, 1))
2168 LOG("\t\tnext instruction");
2170 } /* while instructions */
2172 LOG("instructions done");
2173 LOGSTR("RESULT=> ");
2174 DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
2175 state->bptr->outdepth));
2176 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
2179 /* propagate stack and variables to the following block */
2180 if (!superblockend) {
2181 LOG("reaching following block");
2182 tbptr = state->bptr->next;
2183 while (tbptr->flags == BBDELETED) {
2184 tbptr = tbptr->next;
2185 #ifdef TYPECHECK_DEBUG
2186 /* this must be checked in parse.c */
2187 if ((tbptr->nr) >= state->basicblockcount)
2188 TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
2191 if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
2192 state->bptr->outdepth))
2196 /* We may have to restore the types of the instack slots. They
2197 * have been saved if an <init> call inside the block has
2198 * modified the instack types. (see INVOKESPECIAL) */
2200 if (state->savedinvars)
2201 typestate_restore_invars(state);
2207 /* verify_init_locals **********************************************************
2209 Initialize the local variables in the verifier state.
2212 state............the current state of the verifier
2215 true.............success,
2216 false............an exception has been thrown.
2218 *******************************************************************************/
2221 verify_init_locals(verifier_state *state)
2227 jitdata *jd = state->jd;
2230 locals = state->basicblocks[0].inlocals;
2232 /* allocate parameter descriptors if necessary */
2234 if (!state->m->parseddesc->params)
2235 if (!descriptor_params_from_paramtypes(state->m->parseddesc,state->m->flags))
2238 /* pre-initialize variables as TYPE_VOID */
2240 i = state->numlocals;
2243 v->type = TYPE_VOID;
2247 /* if this is an instance method initialize the "this" ref type */
2249 if (!(state->m->flags & ACC_STATIC)) {
2250 index = jd->local_map[5*0 + TYPE_ADR];
2251 if (index != UNUSED) {
2252 if (state->validlocals < 1)
2253 TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
2256 if (state->initmethod)
2257 TYPEINFO_INIT_NEWOBJECT(v->typeinfo, NULL);
2259 typeinfo_init_classinfo(&(v->typeinfo), state->m->class);
2265 LOG("'this' argument set.\n");
2267 /* the rest of the arguments and the return type */
2269 if (!typeinfo_init_varinfos_from_methoddesc(locals, state->m->parseddesc,
2271 skip, /* skip 'this' pointer */
2273 &state->returntype))
2276 LOG("Arguments set.\n");
2281 /* typecheck_init_flags ********************************************************
2283 Initialize the basic block flags for the following CFG traversal.
2286 state............the current state of the verifier
2288 *******************************************************************************/
2291 typecheck_init_flags(verifier_state *state)
2296 /* set all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
2298 i = state->basicblockcount;
2299 for (block = state->basicblocks; block; block = block->next) {
2301 #ifdef TYPECHECK_DEBUG
2302 /* check for invalid flags */
2303 if (block->flags != BBFINISHED && block->flags != BBDELETED && block->flags != BBUNDEF)
2305 LOGSTR1("block flags: %d\n",block->flags); LOGFLUSH;
2306 TYPECHECK_ASSERT(false);
2310 if (block->flags >= BBFINISHED) {
2311 block->flags = BBTYPECHECK_UNDEF;
2315 /* the first block is always reached */
2317 if (state->basicblockcount && state->basicblocks[0].flags == BBTYPECHECK_UNDEF)
2318 state->basicblocks[0].flags = BBTYPECHECK_REACHED;
2322 /* typecheck_reset_flags *******************************************************
2324 Reset the flags of basic blocks we have not reached.
2327 state............the current state of the verifier
2329 *******************************************************************************/
2332 typecheck_reset_flags(verifier_state *state)
2336 /* check for invalid flags at exit */
2338 #ifdef TYPECHECK_DEBUG
2339 for (block = state->basicblocks; block; block = block->next) {
2340 if (block->flags != BBDELETED
2341 && block->flags != BBUNDEF
2342 && block->flags != BBFINISHED
2343 && block->flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2344 * some exception handlers,
2347 LOG2("block L%03d has invalid flags after typecheck: %d",
2348 block->nr,block->flags);
2349 TYPECHECK_ASSERT(false);
2354 /* Delete blocks we never reached */
2356 for (block = state->basicblocks; block; block = block->next) {
2357 if (block->flags == BBTYPECHECK_UNDEF)
2358 block->flags = BBDELETED;
2363 /****************************************************************************/
2365 /* This is the main function of the bytecode verifier. It is called */
2366 /* directly after analyse_stack. */
2369 /* meth.............the method to verify */
2370 /* cdata............codegendata for the method */
2371 /* rdata............registerdata for the method */
2374 /* true.............successful verification */
2375 /* false............an exception has been thrown */
2377 /****************************************************************************/
2379 #define MAXPARAMS 255
2381 bool typecheck(jitdata *jd)
2385 varinfo *savedlocals;
2386 verifier_state state; /* current state of the verifier */
2390 /* collect statistics */
2392 #ifdef TYPECHECK_STATISTICS
2393 int count_iterations = 0;
2394 TYPECHECK_COUNT(stat_typechecked);
2395 TYPECHECK_COUNT_FREQ(stat_locals,cdata->maxlocals,STAT_LOCALS);
2396 TYPECHECK_COUNT_FREQ(stat_blocks,cdata->method->basicblockcount/10,STAT_BLOCKS);
2397 TYPECHECK_COUNTIF(cdata->method->exceptiontablelength != 0,stat_methods_with_handlers);
2398 state.stat_maythrow = false;
2401 /* get required compiler data */
2406 /* some logging on entry */
2409 LOGSTR("\n==============================================================================\n");
2410 DOLOG( new_show_method(jd, SHOW_STACK) );
2411 LOGSTR("\n==============================================================================\n");
2412 LOGMETHOD("Entering typecheck: ",cd->method);
2414 /* initialize the verifier state */
2419 state.basicblockcount = jd->new_basicblockcount;
2420 state.basicblocks = jd->new_basicblocks;
2421 state.savedindices = NULL;
2422 state.savedinvars = NULL;
2424 /* check if this method is an instance initializer method */
2426 state.initmethod = (state.m->name == utf_init);
2428 /* initialize the basic block flags for the following CFG traversal */
2430 typecheck_init_flags(&state);
2432 /* number of local variables */
2434 /* In <init> methods we use an extra local variable to indicate whether */
2435 /* the 'this' reference has been initialized. */
2436 /* TYPE_VOID...means 'this' has not been initialized, */
2437 /* TYPE_INT....means 'this' has been initialized. */
2439 state.numlocals = state.jd->localcount;
2440 state.validlocals = state.numlocals;
2441 if (state.initmethod)
2442 state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
2444 state.reverselocalmap = DMNEW(s4, state.validlocals);
2445 for (i=0; i<jd->m->maxlocals; ++i)
2446 for (t=0; t<5; ++t) {
2447 s4 mapped = jd->local_map[5*i + t];
2449 state.reverselocalmap[mapped] = i;
2452 /* allocate the buffer of active exception handlers */
2454 state.handlers = DMNEW(exceptiontable*, state.cd->exceptiontablelength + 1);
2456 /* save local variables */
2458 savedlocals = DMNEW(varinfo, state.numlocals);
2459 MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
2461 /* initialized local variables of first block */
2463 if (!verify_init_locals(&state))
2466 /* initialize invars of exception handlers */
2468 state.exinvars = state.numlocals;
2469 VAR(state.exinvars)->type = TYPE_ADR;
2470 typeinfo_init_classinfo(&(VAR(state.exinvars)->typeinfo),
2471 class_java_lang_Throwable); /* changed later */
2473 LOG("Exception handler stacks set.\n");
2475 /* loop while there are still blocks to be checked */
2477 TYPECHECK_COUNT(count_iterations);
2479 state.repeat = false;
2481 state.bptr = state.basicblocks;
2483 for (; state.bptr; state.bptr = state.bptr->next) {
2484 LOGSTR1("---- BLOCK %04d, ",state.bptr->nr);
2485 LOGSTR1("blockflags: %d\n",state.bptr->flags);
2488 /* verify reached block */
2489 if (state.bptr->flags == BBTYPECHECK_REACHED) {
2490 if (!verify_basic_block(&state))
2495 LOGIF(state.repeat,"state.repeat == true");
2496 } while (state.repeat);
2500 #ifdef TYPECHECK_STATISTICS
2501 LOG1("Typechecker did %4d iterations",count_iterations);
2502 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2503 TYPECHECK_COUNTIF(state.jsrencountered,stat_typechecked_jsr);
2504 TYPECHECK_COUNTIF(state.stat_maythrow,stat_methods_maythrow);
2507 /* reset the flags of blocks we haven't reached */
2509 typecheck_reset_flags(&state);
2511 /* restore locals */
2513 MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
2515 /* everything's ok */
2517 LOGimp("exiting typecheck");
2520 #endif /* ENABLE_VERIFIER */
2523 * These are local overrides for various environment variables in Emacs.
2524 * Please do not remove this and leave it at the end of the file, where
2525 * Emacs will automagically detect them.
2526 * ---------------------------------------------------------------------
2529 * indent-tabs-mode: t
2533 * vim:noexpandtab:sw=4:ts=4: