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 5729 2006-10-09 23:53:42Z 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);
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;
805 /* get the FMIref and the unresolved_method struct (if any) */
806 /* from the instruction */
808 if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
809 /* unresolved method */
810 um = state->iptr->sx.s23.s3.um;
811 mref = um->methodref;
814 /* resolved method */
816 mref = state->iptr->sx.s23.s3.fmiref;
819 /* get method descriptor and name */
821 md = mref->parseddesc.md;
824 /* get method info (if resolved) and classname */
826 if (IS_FMIREF_RESOLVED(mref)) {
828 mclassname = mi->class->name;
832 mclassname = mref->p.classref->name;
835 opcode = state->iptr[0].opc;
836 invokestatic = (opcode == ICMD_INVOKESTATIC);
837 invokespecial = (opcode == ICMD_INVOKESPECIAL);
838 specialmethod = (mname->text[0] == '<');
839 dv = VAROP(state->iptr->dst);
841 /* prevent compiler warnings */
845 /* check whether we are calling <init> */
847 callinginit = (invokespecial && mname == utf_init);
848 if (specialmethod && !callinginit)
849 TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
851 /* allocate parameters if necessary */
854 if (!descriptor_params_from_paramtypes(md,
855 (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
858 /* check parameter types */
860 i = md->paramcount; /* number of parameters including 'this'*/
863 argindex = state->iptr->sx.s23.s2.args[i];
865 td = md->paramtypes + i;
867 if (av->type != td->type)
868 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
870 if (av->type == TYPE_ADR) {
871 LOGINFO(&(av->typeinfo));
872 if (i==0 && callinginit)
874 /* first argument to <init> method */
875 if (!TYPEINFO_IS_NEWOBJECT(av->typeinfo))
876 TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
878 /* get the address of the NEW instruction */
879 LOGINFO(&(av->typeinfo));
880 ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo);
882 initclass = ins[-1].sx.val.c;
884 initclass.cls = state->m->class;
885 LOGSTR("class: "); LOGNAME(initclass); LOGNL;
889 /* non-adress argument. if this is the first argument and we are */
890 /* invoking an instance method, this is an error. */
891 if (i==0 && opcode != ICMD_INVOKESTATIC) {
892 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch for 'this' argument");
899 LOG("replacing uninitialized object");
900 /* replace uninitialized object type on stack */
902 /* for all live-in and live-through variables */
903 for (i=0; i<state->iptr->s1.argcount; ++i) {
904 argindex = state->iptr->sx.s23.s2.args[i];
906 if (av->type == TYPE_ADR
907 && TYPEINFO_IS_NEWOBJECT(av->typeinfo)
908 && TYPEINFO_NEWOBJECT_INSTRUCTION(av->typeinfo) == ins)
910 LOG("replacing uninitialized type");
912 /* If this stackslot is in the instack of
913 * this basic block we must save the type(s)
914 * we are going to replace.
916 /* XXX this needs a new check */
917 if (state->bptr->invars
918 && argindex >= state->bptr->invars[0]
919 && argindex < state->bptr->varstart
920 && !state->savedinvars)
922 typestate_save_invars(state);
925 if (!typeinfo_init_class(&(av->typeinfo),initclass))
930 /* replace uninitialized object type in locals */
931 if (!typevector_init_object(state->jd->var, ins, initclass,
935 /* initializing the 'this' reference? */
938 TYPECHECK_ASSERT(state->initmethod);
939 /* { we are initializing the 'this' reference } */
940 /* must be <init> of current class or direct superclass */
941 /* the current class is linked, so must be its superclass. thus we can be */
942 /* sure that resolving will be trivial. */
947 if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
948 return false; /* exception */
951 /* if lazy resolving did not succeed, it's not one of the allowed classes */
952 /* otherwise we check it directly */
953 if (cls == NULL || (cls != state->m->class && cls != state->m->class->super.cls)) {
954 TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
957 /* set our marker variable to type int */
958 LOG("setting <init> marker");
959 typevector_store(jd->var, state->numlocals-1, TYPE_INT, NULL);
962 /* { we are initializing an instance created with NEW } */
963 if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mclassname) {
964 TYPECHECK_VERIFYERROR_bool("wrong <init> called for uninitialized reference");
969 /* try to resolve the method lazily */
971 result = resolve_method_lazy(state->m, mref, invokespecial);
973 /* perform verification checks */
975 if (result == resolveSucceeded) {
977 assert(IS_FMIREF_RESOLVED(mref));
981 result = resolve_method_verifier_checks(state->m,
987 /* check types of parameters */
989 if (result == resolveSucceeded && !invokestatic)
990 result = resolve_method_instance_type_checks(
992 &(VAR(state->iptr->sx.s23.s2.args[0])->typeinfo),
995 if (result == resolveSucceeded)
996 result = resolve_method_param_type_checks(
997 jd, state->m, state->iptr,
1000 /* impose loading constraints */
1002 if (result == resolveSucceeded) {
1003 /* XXX state->m->class may have to be wrong when inlining */
1004 if (!resolve_method_loading_constraints(state->m->class, mi))
1008 if (result == resolveFailed)
1011 if (result == resolveSucceeded) {
1012 /* if this call is monomorphic, turn it into an INVOKESPECIAL */
1014 if ((state->iptr->opc == ICMD_INVOKEVIRTUAL)
1015 && (mi->flags & (ACC_FINAL | ACC_PRIVATE)))
1017 state->iptr->opc = ICMD_INVOKESPECIAL;
1021 /* resolution must be deferred */
1024 um = resolve_create_unresolved_method(state->m->class, state->m,
1026 state->iptr->opc == ICMD_INVOKESTATIC,
1033 /* record subtype constraints for parameters */
1035 if (!constrain_unresolved_method(jd, um, state->m->class,
1036 state->m, state->iptr))
1037 return false; /* XXX maybe wrap exception */
1039 /* store the unresolved_method pointer */
1041 state->iptr->sx.s23.s3.um = um;
1042 state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
1045 rtype = md->returntype.type;
1046 if (rtype != TYPE_VOID) {
1048 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
1056 /* verify_generic_builtin ******************************************************
1058 Verify the call of a generic builtin method.
1061 state............the current state of the verifier
1064 true.............successful verification,
1065 false............an exception has been thrown.
1067 *******************************************************************************/
1070 verify_generic_builtin(verifier_state *state)
1072 builtintable_entry *bte;
1077 jitdata *jd = state->jd;
1079 TYPECHECK_COUNT(stat_ins_builtin_gen);
1081 bte = state->iptr->sx.s23.s3.bte;
1085 /* check the types of the arguments on the stack */
1087 for (i--; i >= 0; i--) {
1088 av = VAR(state->iptr->sx.s23.s2.args[i]);
1090 if (av->type != md->paramtypes[i].type) {
1091 TYPECHECK_VERIFYERROR_bool("parameter type mismatch for builtin method");
1094 #ifdef TYPECHECK_DEBUG
1095 /* generic builtins may only take primitive types and java.lang.Object references */
1096 if (av->type == TYPE_ADR && md->paramtypes[i].classref->name != utf_java_lang_Object) {
1097 *exceptionptr = new_internalerror("generic builtin method with non-generic reference parameter");
1103 /* set the return type */
1105 rtype = md->returntype.type;
1106 if (rtype != TYPE_VOID) {
1109 dv = VAROP(state->iptr->dst);
1111 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dv->typeinfo)))
1119 /* verify_builtin **************************************************************
1121 Verify the call of a builtin method.
1124 state............the current state of the verifier
1127 true.............successful verification,
1128 false............an exception has been thrown.
1130 *******************************************************************************/
1133 verify_builtin(verifier_state *state)
1135 builtintable_entry *bte;
1136 classref_or_classinfo cls;
1137 varinfo *dv; /* output variable of current instruction */
1138 jitdata *jd = state->jd;
1140 bte = state->iptr->sx.s23.s3.bte;
1141 dv = VAROP(state->iptr->dst);
1143 /* XXX this is an ugly if-chain but twisti did not want a function */
1144 /* pointer in builtintable_entry for this, so here you go.. ;) */
1146 if (ISBUILTIN(BUILTIN_new)) {
1147 if (state->iptr[-1].opc != ICMD_ACONST)
1148 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without class");
1149 cls = state->iptr[-1].sx.val.c;
1150 dv->type = TYPE_ADR;
1151 TYPEINFO_INIT_NEWOBJECT(dv->typeinfo,state->iptr);
1153 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1154 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1155 dv->type = TYPE_ADR;
1156 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BOOLEAN);
1158 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1159 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1160 dv->type = TYPE_ADR;
1161 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_CHAR);
1163 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1164 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1165 dv->type = TYPE_ADR;
1166 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_FLOAT);
1168 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1169 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1170 dv->type = TYPE_ADR;
1171 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_DOUBLE);
1173 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1174 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1175 dv->type = TYPE_ADR;
1176 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_BYTE);
1178 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1179 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1180 dv->type = TYPE_ADR;
1181 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_SHORT);
1183 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1184 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1185 dv->type = TYPE_ADR;
1186 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_INT);
1188 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1189 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1190 dv->type = TYPE_ADR;
1191 TYPEINFO_INIT_PRIMITIVE_ARRAY(dv->typeinfo,ARRAYTYPE_LONG);
1193 else if (ISBUILTIN(BUILTIN_newarray))
1195 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1196 if (state->iptr[-1].opc != ICMD_ACONST)
1197 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without class");
1198 /* XXX check that it is an array class(ref) */
1199 dv->type = TYPE_ADR;
1200 typeinfo_init_class(&(dv->typeinfo),state->iptr[-1].sx.val.c);
1202 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1204 TYPECHECK_ADR(state->iptr->sx.s23.s2.args[0]);
1205 if (state->iptr[-1].opc != ICMD_ACONST)
1206 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without class");
1207 dv->type = TYPE_INT;
1208 /* XXX check that it is an array class(ref) */
1211 return verify_generic_builtin(state);
1217 /* verify_multianewarray *******************************************************
1219 Verify a MULTIANEWARRAY instruction.
1222 state............the current state of the verifier
1225 true.............successful verification,
1226 false............an exception has been thrown.
1228 *******************************************************************************/
1231 verify_multianewarray(verifier_state *state)
1233 classinfo *arrayclass;
1234 arraydescriptor *desc;
1236 jitdata *jd = state->jd;
1238 /* check the array lengths on the stack */
1239 i = state->iptr->s1.argcount;
1241 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
1244 TYPECHECK_INT(state->iptr->sx.s23.s2.args[i]);
1247 /* check array descriptor */
1248 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
1249 /* the array class reference has already been resolved */
1250 arrayclass = state->iptr->sx.s23.s3.c.cls;
1252 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
1253 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
1254 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1255 if (desc->dimension < state->iptr->s1.argcount)
1256 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1258 /* set the array type of the result */
1259 typeinfo_init_classinfo(&(VAROP(state->iptr->dst)->typeinfo), arrayclass);
1263 constant_classref *cr;
1265 /* the array class reference is still unresolved */
1266 /* check that the reference indicates an array class of correct dimension */
1267 cr = state->iptr->sx.s23.s3.c.ref;
1272 /* { the dimension of the array class == i } */
1274 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1275 if (i < state->iptr->s1.argcount)
1276 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1278 /* set the array type of the result */
1279 if (!typeinfo_init_class(&(VAROP(state->iptr->dst)->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
1283 /* set return type */
1285 VAROP(state->iptr->dst)->type = TYPE_ADR;
1292 /* typecheck_invalidate_locals *************************************************
1294 Invalidate locals that are overwritten by writing to the given local.
1297 state............the current state of the verifier
1298 index............the index of the local that is written
1299 twoword..........true, if a two-word type is written
1301 *******************************************************************************/
1303 static void typecheck_invalidate_locals(verifier_state *state, s4 index, bool twoword)
1308 jitdata *jd = state->jd;
1309 s4 *localmap = jd->local_map;
1310 varinfo *vars = jd->var;
1312 i = state->reverselocalmap[index];
1314 /* invalidate locals of two-word type at index i-1 */
1317 localmap += 5 * (i-1);
1318 for (t=0; t<5; ++t) {
1319 mapped = *localmap++;
1320 if (mapped >= 0 && IS_2_WORD_TYPE(vars[mapped].type)) {
1321 LOG1("invalidate local %d", mapped);
1322 vars[mapped].type = TYPE_VOID;
1330 /* invalidate locals at index i */
1332 for (t=0; t<5; ++t) {
1333 mapped = *localmap++;
1335 LOG1("invalidate local %d", mapped);
1336 vars[mapped].type = TYPE_VOID;
1340 /* if a two-word type is written, invalidate locals at index i+1 */
1343 for (t=0; t<5; ++t) {
1344 mapped = *localmap++;
1346 LOG1("invalidate local %d", mapped);
1347 vars[mapped].type = TYPE_VOID;
1354 /* verify_basic_block **********************************************************
1356 Perform bytecode verification of a basic block.
1359 state............the current state of the verifier
1362 true.............successful verification,
1363 false............an exception has been thrown.
1365 *******************************************************************************/
1368 verify_basic_block(verifier_state *state)
1370 int opcode; /* current opcode */
1371 int len; /* for counting instructions, etc. */
1372 bool superblockend; /* true if no fallthrough to next block */
1373 instruction *iptr; /* the current instruction */
1374 basicblock *tbptr; /* temporary for target block */
1375 bool maythrow; /* true if this instruction may throw */
1376 unresolved_field *uf; /* for field accesses */
1377 constant_FMIref *fieldref; /* for field accesses */
1380 resolve_result_t result;
1381 branch_target_t *table;
1382 lookup_target_t *lookup;
1383 jitdata *jd = state->jd;
1387 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
1389 DOLOG(show_basicblock(jd, state->bptr, SHOW_STACK));
1391 superblockend = false;
1392 state->bptr->flags = BBFINISHED;
1394 /* prevent compiler warnings */
1398 /* determine the active exception handlers for this block */
1399 /* XXX could use a faster algorithm with sorted lists or */
1402 for (ex = state->cd->exceptiontable; ex ; ex = ex->down) {
1403 if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
1404 LOG1("active handler L%03d", ex->handler->nr);
1405 state->handlers[len++] = ex;
1408 state->handlers[len] = NULL;
1410 /* init variable types at the start of this block */
1411 typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
1413 DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars,
1414 state->bptr->indepth));
1415 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
1418 /* loop over the instructions */
1419 len = state->bptr->icount;
1420 state->iptr = state->bptr->iinstr;
1421 while (--len >= 0) {
1422 TYPECHECK_COUNT(stat_ins);
1426 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
1428 DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); LOGNL; LOGFLUSH;
1431 dv = VAROP(iptr->dst);
1436 /****************************************/
1437 /* STACK MANIPULATIONS */
1439 /* We just need to copy the typeinfo */
1440 /* for slots containing addresses. */
1444 TYPECHECK_COUNT(stat_ins_stack);
1445 COPYTYPE(iptr->s1, iptr->dst);
1446 dv->type = VAROP(iptr->s1)->type;
1449 /****************************************/
1450 /* PRIMITIVE VARIABLE ACCESS */
1452 case ICMD_ILOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_INT))
1453 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1454 dv->type = TYPE_INT;
1456 case ICMD_IINC: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_INT))
1457 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1458 dv->type = TYPE_INT;
1460 case ICMD_FLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_FLT))
1461 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1462 dv->type = TYPE_FLT;
1464 case ICMD_LLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_LNG))
1465 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1466 dv->type = TYPE_LNG;
1468 case ICMD_DLOAD: if (!typevector_checktype(jd->var,state->iptr->s1.varindex,TYPE_DBL))
1469 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1470 dv->type = TYPE_DBL;
1474 typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
1475 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_INT,NULL);
1478 typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
1479 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_FLT,NULL);
1482 typecheck_invalidate_locals(state, state->iptr->dst.varindex, true);
1483 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_LNG,NULL);
1486 typecheck_invalidate_locals(state, state->iptr->dst.varindex, true);
1487 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_DBL,NULL);
1490 /****************************************/
1491 /* LOADING ADDRESS FROM VARIABLE */
1494 TYPECHECK_COUNT(stat_ins_aload);
1496 /* loading a returnAddress is not allowed */
1497 if (!TYPEDESC_IS_REFERENCE(*VAROP(state->iptr->s1))) {
1498 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1500 TYPEINFO_COPY(VAROP(state->iptr->s1)->typeinfo,dv->typeinfo);
1501 dv->type = TYPE_ADR;
1504 /****************************************/
1505 /* STORING ADDRESS TO VARIABLE */
1508 typecheck_invalidate_locals(state, state->iptr->dst.varindex, false);
1510 if (TYPEINFO_IS_PRIMITIVE(VAROP(state->iptr->s1)->typeinfo)) {
1511 typevector_store_retaddr(jd->var,state->iptr->dst.varindex,&(VAROP(state->iptr->s1)->typeinfo));
1514 typevector_store(jd->var,state->iptr->dst.varindex,TYPE_ADR,
1515 &(VAROP(state->iptr->s1)->typeinfo));
1519 /****************************************/
1520 /* LOADING ADDRESS FROM ARRAY */
1523 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(VAROP(state->iptr->s1)->typeinfo))
1524 TYPECHECK_VERIFYERROR_bool("illegal instruction: AALOAD on non-reference array");
1526 if (!typeinfo_init_component(&VAROP(state->iptr->s1)->typeinfo,&dv->typeinfo))
1528 dv->type = TYPE_ADR;
1532 /****************************************/
1536 case ICMD_PUTSTATIC:
1537 case ICMD_PUTFIELDCONST:
1538 case ICMD_PUTSTATICCONST:
1540 case ICMD_GETSTATIC:
1542 varinfo *valueslot = NULL;
1543 typeinfo *instanceti = NULL;
1544 typeinfo *valueti = NULL;
1545 bool isstatic = false;
1549 TYPECHECK_COUNT(stat_ins_field);
1551 if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
1552 uf = state->iptr->sx.s23.s3.uf;
1553 fieldref = uf->fieldref;
1557 fieldref = state->iptr->sx.s23.s3.fmiref;
1560 /* get opcode dependent values */
1562 switch (state->iptr->opc) {
1565 valueslot = VAROP(state->iptr->sx.s23.s2);
1566 instanceti = &(VAROP(state->iptr->s1)->typeinfo);
1569 case ICMD_PUTFIELDCONST:
1571 instanceti = &(VAROP(state->iptr->s1)->typeinfo);
1572 putfield_const_tail:
1573 if (IS_ADR_TYPE(fieldref->parseddesc.fd->type)) {
1574 /* XXX check for java.lang.Class constant values? */
1575 if (state->iptr->sx.val.anyptr) {
1576 assert(class_java_lang_String);
1577 assert(class_java_lang_String->state & CLASS_LOADED);
1578 assert(class_java_lang_String->state & CLASS_LINKED);
1579 typeinfo_init_classinfo(&constti, class_java_lang_String);
1582 TYPEINFO_INIT_NULLTYPE(constti);
1588 case ICMD_PUTSTATIC:
1591 valueslot = VAROP(state->iptr->s1);
1594 case ICMD_PUTSTATICCONST:
1597 goto putfield_const_tail;
1600 instanceti = &(VAROP(state->iptr->s1)->typeinfo);
1603 case ICMD_GETSTATIC:
1611 if (valueslot && IS_ADR_TYPE(valueslot->type)) {
1612 valueti = &(valueslot->typeinfo);
1615 /* try to resolve the field reference lazily */
1617 result = resolve_field_lazy(state->m, fieldref);
1619 if (result == resolveSucceeded) {
1622 /* perform verification checks now */
1624 fi = fieldref->p.field;
1626 result = resolve_field_verifier_checks(
1627 state->m, fieldref, fi->class, fi,
1628 instanceti, valueti, isstatic, isput);
1631 if (result == resolveFailed)
1634 /* if not resolved, yet, create an unresolved field */
1636 if (result != resolveSucceeded) {
1638 uf = resolve_create_unresolved_field(state->m->class,
1639 state->m, state->iptr);
1643 state->iptr->sx.s23.s3.uf = uf;
1644 state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
1647 /* record the subtype constraints for this field access */
1649 if (!resolve_constrain_unresolved_field(
1650 uf, state->m->class, state->m,
1651 instanceti, valueti))
1652 return false; /* XXX maybe wrap exception? */
1654 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(state->iptr),stat_ins_field_unresolved);
1655 TYPECHECK_COUNTIF(INSTRUCTION_IS_RESOLVED(state->iptr) &&
1656 !state->iptr->sx.s23.s3.fmiref->p.field->class->initialized,
1657 stat_ins_field_uninitialized);
1660 /* write the result type */
1662 if (iptr->opc == ICMD_GETFIELD || iptr->opc == ICMD_GETSTATIC) {
1663 dv->type = fieldref->parseddesc.fd->type;
1664 if (dv->type == TYPE_ADR) {
1665 if (!typeinfo_init_from_typedesc(fieldref->parseddesc.fd,
1666 NULL, &(dv->typeinfo)))
1675 /****************************************/
1676 /* PRIMITIVE ARRAY ACCESS */
1678 case ICMD_ARRAYLENGTH:
1679 if (!TYPEINFO_MAYBE_ARRAY(VAROP(state->iptr->s1)->typeinfo)
1680 && VAROP(state->iptr->s1)->typeinfo.typeclass.cls != pseudo_class_Arraystub)
1681 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARRAYLENGTH on non-array");
1682 dv->type = TYPE_INT;
1687 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BOOLEAN)
1688 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BYTE))
1689 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1690 dv->type = TYPE_INT;
1694 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_CHAR))
1695 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1696 dv->type = TYPE_INT;
1700 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_DOUBLE))
1701 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1702 dv->type = TYPE_DBL;
1706 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_FLOAT))
1707 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1708 dv->type = TYPE_FLT;
1712 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_INT))
1713 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1714 dv->type = TYPE_INT;
1718 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_SHORT))
1719 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1720 dv->type = TYPE_INT;
1724 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_LONG))
1725 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1726 dv->type = TYPE_LNG;
1731 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BOOLEAN)
1732 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_BYTE))
1733 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1737 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_CHAR))
1738 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1742 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_DOUBLE))
1743 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1747 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_FLOAT))
1748 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1752 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_INT))
1753 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1757 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_SHORT))
1758 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1762 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo,ARRAYTYPE_LONG))
1763 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1768 /* we just check the basic input types and that the */
1769 /* destination is an array of references. Assignability to */
1770 /* the actual array must be checked at runtime, each time the */
1771 /* instruction is performed. (See builtin_canstore.) */
1772 TYPECHECK_ADR_OP(state->iptr->sx.s23.s3);
1773 TYPECHECK_INT_OP(state->iptr->sx.s23.s2);
1774 TYPECHECK_ADR_OP(state->iptr->s1);
1775 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(VAROP(state->iptr->s1)->typeinfo))
1776 TYPECHECK_VERIFYERROR_bool("illegal instruction: AASTORE to non-reference array");
1780 case ICMD_IASTORECONST:
1781 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_INT))
1782 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1786 case ICMD_LASTORECONST:
1787 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_LONG))
1788 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1792 case ICMD_BASTORECONST:
1793 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_BOOLEAN)
1794 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_BYTE))
1795 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1799 case ICMD_CASTORECONST:
1800 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_CHAR))
1801 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1805 case ICMD_SASTORECONST:
1806 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(VAROP(state->iptr->s1)->typeinfo, ARRAYTYPE_SHORT))
1807 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1811 /****************************************/
1812 /* ADDRESS CONSTANTS */
1815 if (state->iptr->flags.bits & INS_FLAG_CLASS) {
1816 /* a java.lang.Class reference */
1817 TYPEINFO_INIT_JAVA_LANG_CLASS(dv->typeinfo,state->iptr->sx.val.c);
1820 if (state->iptr->sx.val.anyptr == NULL)
1821 TYPEINFO_INIT_NULLTYPE(dv->typeinfo);
1823 /* string constant (or constant for builtin function) */
1824 typeinfo_init_classinfo(&(dv->typeinfo),class_java_lang_String);
1827 dv->type = TYPE_ADR;
1830 /****************************************/
1831 /* CHECKCAST AND INSTANCEOF */
1833 case ICMD_CHECKCAST:
1834 TYPECHECK_ADR_OP(state->iptr->s1);
1835 /* returnAddress is not allowed */
1836 if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
1837 TYPECHECK_VERIFYERROR_bool("Illegal instruction: CHECKCAST on non-reference");
1839 if (!typeinfo_init_class(&(dv->typeinfo),state->iptr->sx.s23.s3.c))
1841 dv->type = TYPE_ADR;
1845 case ICMD_INSTANCEOF:
1846 TYPECHECK_ADR_OP(state->iptr->s1);
1847 /* returnAddress is not allowed */
1848 if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
1849 TYPECHECK_VERIFYERROR_bool("Illegal instruction: INSTANCEOF on non-reference");
1850 dv->type = TYPE_INT;
1853 /****************************************/
1854 /* BRANCH INSTRUCTIONS */
1856 case ICMD_INLINE_GOTO:
1857 COPYTYPE(state->iptr->s1,state->iptr->dst);
1860 superblockend = true;
1863 case ICMD_IFNONNULL:
1870 case ICMD_IF_ICMPEQ:
1871 case ICMD_IF_ICMPNE:
1872 case ICMD_IF_ICMPLT:
1873 case ICMD_IF_ICMPGE:
1874 case ICMD_IF_ICMPGT:
1875 case ICMD_IF_ICMPLE:
1876 case ICMD_IF_ACMPEQ:
1877 case ICMD_IF_ACMPNE:
1886 case ICMD_IF_LCMPEQ:
1887 case ICMD_IF_LCMPNE:
1888 case ICMD_IF_LCMPLT:
1889 case ICMD_IF_LCMPGE:
1890 case ICMD_IF_LCMPGT:
1891 case ICMD_IF_LCMPLE:
1893 case ICMD_IF_FCMPEQ:
1894 case ICMD_IF_FCMPNE:
1896 case ICMD_IF_FCMPL_LT:
1897 case ICMD_IF_FCMPL_GE:
1898 case ICMD_IF_FCMPL_GT:
1899 case ICMD_IF_FCMPL_LE:
1901 case ICMD_IF_FCMPG_LT:
1902 case ICMD_IF_FCMPG_GE:
1903 case ICMD_IF_FCMPG_GT:
1904 case ICMD_IF_FCMPG_LE:
1906 case ICMD_IF_DCMPEQ:
1907 case ICMD_IF_DCMPNE:
1909 case ICMD_IF_DCMPL_LT:
1910 case ICMD_IF_DCMPL_GE:
1911 case ICMD_IF_DCMPL_GT:
1912 case ICMD_IF_DCMPL_LE:
1914 case ICMD_IF_DCMPG_LT:
1915 case ICMD_IF_DCMPG_GE:
1916 case ICMD_IF_DCMPG_GT:
1917 case ICMD_IF_DCMPG_LE:
1918 TYPECHECK_COUNT(stat_ins_branch);
1920 /* propagate stack and variables to the target block */
1921 if (!typestate_reach(state, state->iptr->dst.block,
1922 state->bptr->outvars, jd->var,
1923 state->bptr->outdepth))
1927 /****************************************/
1930 case ICMD_TABLESWITCH:
1931 TYPECHECK_COUNT(stat_ins_switch);
1933 table = iptr->dst.table;
1934 i = iptr->sx.s23.s3.tablehigh
1935 - iptr->sx.s23.s2.tablelow + 1 + 1; /* plus default */
1938 tbptr = (table++)->block;
1939 LOG2("target %d is block %04d",i,tbptr->nr);
1940 if (!typestate_reach(state, tbptr, state->bptr->outvars,
1941 jd->var, state->bptr->outdepth))
1946 superblockend = true;
1949 case ICMD_LOOKUPSWITCH:
1950 TYPECHECK_COUNT(stat_ins_switch);
1952 lookup = iptr->dst.lookup;
1953 i = iptr->sx.s23.s2.lookupcount;
1955 if (!typestate_reach(state,iptr->sx.s23.s3.lookupdefault.block,
1956 state->bptr->outvars, jd->var,
1957 state->bptr->outdepth))
1961 tbptr = (lookup++)->target.block;
1962 LOG2("target %d is block %04d",i,tbptr->nr);
1963 if (!typestate_reach(state, tbptr, state->bptr->outvars,
1964 jd->var, state->bptr->outdepth))
1969 superblockend = true;
1973 /****************************************/
1974 /* ADDRESS RETURNS AND THROW */
1977 TYPECHECK_COUNT(stat_ins_athrow);
1978 r = typeinfo_is_assignable_to_class(&VAROP(state->iptr->s1)->typeinfo,
1979 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
1980 if (r == typecheck_FALSE)
1981 TYPECHECK_VERIFYERROR_bool("illegal instruction: ATHROW on non-Throwable");
1982 if (r == typecheck_FAIL)
1984 if (r == typecheck_MAYBE) {
1985 /* the check has to be postponed. we need a patcher */
1986 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
1987 iptr->sx.s23.s2.uc = create_unresolved_class(
1989 /* XXX make this more efficient, use class_java_lang_Throwable
1991 class_get_classref(state->m->class,utf_java_lang_Throwable),
1992 &VAROP(state->iptr->s1)->typeinfo);
1993 iptr->flags.bits |= INS_FLAG_UNRESOLVED;
1995 superblockend = true;
2000 TYPECHECK_COUNT(stat_ins_areturn);
2001 if (!TYPEINFO_IS_REFERENCE(VAROP(state->iptr->s1)->typeinfo))
2002 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARETURN on non-reference");
2004 if (state->returntype.type != TYPE_ADR
2005 || (r = typeinfo_is_assignable(&VAROP(state->iptr->s1)->typeinfo,&(state->returntype.typeinfo)))
2007 TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2008 if (r == typecheck_FAIL)
2010 if (r == typecheck_MAYBE) {
2011 /* the check has to be postponed, we need a patcher */
2012 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
2013 iptr->sx.s23.s2.uc = create_unresolved_class(
2015 state->m->parseddesc->returntype.classref,
2016 &VAROP(state->iptr->s1)->typeinfo);
2017 iptr->flags.bits |= INS_FLAG_UNRESOLVED;
2021 /****************************************/
2022 /* PRIMITIVE RETURNS */
2025 if (state->returntype.type != TYPE_INT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2029 if (state->returntype.type != TYPE_LNG) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2033 if (state->returntype.type != TYPE_FLT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2037 if (state->returntype.type != TYPE_DBL) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2041 if (state->returntype.type != TYPE_VOID) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2043 TYPECHECK_COUNT(stat_ins_primitive_return);
2045 if (state->initmethod && state->m->class != class_java_lang_Object) {
2046 /* Check if the 'this' instance has been initialized. */
2047 LOG("Checking <init> marker");
2048 if (!typevector_checktype(jd->var,state->numlocals-1,TYPE_INT))
2049 TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'");
2052 superblockend = true;
2056 /****************************************/
2057 /* SUBROUTINE INSTRUCTIONS */
2062 tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
2063 TYPEINFO_INIT_RETURNADDRESS(dv->typeinfo, state->bptr->next);
2064 if (!typestate_reach(state, tbptr, state->bptr->outvars, jd->var,
2065 state->bptr->outdepth))
2068 superblockend = true;
2072 /* check returnAddress variable */
2073 if (!typevector_checkretaddr(jd->var,state->iptr->s1.varindex))
2074 TYPECHECK_VERIFYERROR_bool("illegal instruction: RET using non-returnAddress variable");
2076 if (!typestate_reach(state, iptr->dst.block, state->bptr->outvars, jd->var,
2077 state->bptr->outdepth))
2080 superblockend = true;
2083 /****************************************/
2086 case ICMD_INVOKEVIRTUAL:
2087 case ICMD_INVOKESPECIAL:
2088 case ICMD_INVOKESTATIC:
2089 case ICMD_INVOKEINTERFACE:
2090 TYPECHECK_COUNT(stat_ins_invoke);
2091 if (!verify_invocation(state))
2093 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(iptr), stat_ins_invoke_unresolved);
2097 /****************************************/
2098 /* MULTIANEWARRAY */
2100 case ICMD_MULTIANEWARRAY:
2101 if (!verify_multianewarray(state))
2106 /****************************************/
2110 TYPECHECK_COUNT(stat_ins_builtin);
2111 if (!verify_builtin(state))
2116 /****************************************/
2117 /* SIMPLE EXCEPTION THROWING TESTS */
2119 case ICMD_CHECKNULL:
2120 /* CHECKNULL just requires that the stack top
2121 * is an address. This is checked in stack.c */
2125 /****************************************/
2126 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
2127 /* REPLACED BY OTHER OPCODES */
2129 #ifdef TYPECHECK_DEBUG
2132 case ICMD_ANEWARRAY:
2133 case ICMD_MONITORENTER:
2134 case ICMD_MONITOREXIT:
2135 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2136 LOG("Should have been converted to builtin function call.");
2137 TYPECHECK_ASSERT(false);
2141 /****************************************/
2142 /* UNCHECKED OPERATIONS */
2144 /*********************************************
2145 * Instructions below...
2146 * *) don't operate on local variables,
2147 * *) don't operate on references,
2148 * *) don't operate on returnAddresses,
2149 * *) don't affect control flow (except
2150 * by throwing exceptions).
2152 * (These instructions are typechecked in
2154 ********************************************/
2156 /* Instructions which may throw a runtime exception: */
2160 dv->type = TYPE_INT;
2166 dv->type = TYPE_LNG;
2170 /* Instructions which never throw a runtime exception: */
2189 case ICMD_IADDCONST:
2190 case ICMD_ISUBCONST:
2191 case ICMD_IMULCONST:
2192 case ICMD_IANDCONST:
2194 case ICMD_IXORCONST:
2195 case ICMD_ISHLCONST:
2196 case ICMD_ISHRCONST:
2197 case ICMD_IUSHRCONST:
2201 case ICMD_INT2SHORT:
2206 case ICMD_LCMPCONST:
2211 dv->type = TYPE_INT;
2227 case ICMD_LADDCONST:
2228 case ICMD_LSUBCONST:
2229 case ICMD_LMULCONST:
2230 case ICMD_LANDCONST:
2232 case ICMD_LXORCONST:
2233 case ICMD_LSHLCONST:
2234 case ICMD_LSHRCONST:
2235 case ICMD_LUSHRCONST:
2240 dv->type = TYPE_LNG;
2253 dv->type = TYPE_FLT;
2266 dv->type = TYPE_DBL;
2269 case ICMD_INLINE_START:
2270 case ICMD_INLINE_END:
2273 /* XXX What shall we do with the following ?*/
2274 case ICMD_AASTORECONST:
2275 TYPECHECK_COUNT(stat_ins_unchecked);
2278 /****************************************/
2281 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2282 TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
2285 /* reach exception handlers for this instruction */
2288 TYPECHECK_COUNT(stat_ins_maythrow);
2289 TYPECHECK_MARK(state->stat_maythrow);
2290 LOG("reaching exception handlers");
2292 while (state->handlers[i]) {
2293 TYPECHECK_COUNT(stat_handlers_reached);
2294 if (state->handlers[i]->catchtype.any)
2295 VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
2297 VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
2298 if (!typestate_reach(state,
2299 state->handlers[i]->handler,
2300 &(state->exinvars), jd->var, 1))
2306 LOG("\t\tnext instruction");
2308 } /* while instructions */
2310 LOG("instructions done");
2311 LOGSTR("RESULT=> ");
2312 DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
2313 state->bptr->outdepth));
2314 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
2317 /* propagate stack and variables to the following block */
2318 if (!superblockend) {
2319 LOG("reaching following block");
2320 tbptr = state->bptr->next;
2321 while (tbptr->flags == BBDELETED) {
2322 tbptr = tbptr->next;
2323 #ifdef TYPECHECK_DEBUG
2324 /* this must be checked in parse.c */
2325 if ((tbptr->nr) >= state->basicblockcount)
2326 TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
2329 if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
2330 state->bptr->outdepth))
2334 /* We may have to restore the types of the instack slots. They
2335 * have been saved if an <init> call inside the block has
2336 * modified the instack types. (see INVOKESPECIAL) */
2338 if (state->savedinvars)
2339 typestate_restore_invars(state);
2345 /* verify_init_locals **********************************************************
2347 Initialize the local variables in the verifier state.
2350 state............the current state of the verifier
2353 true.............success,
2354 false............an exception has been thrown.
2356 *******************************************************************************/
2359 verify_init_locals(verifier_state *state)
2365 jitdata *jd = state->jd;
2368 locals = state->basicblocks[0].inlocals;
2370 /* allocate parameter descriptors if necessary */
2372 if (!state->m->parseddesc->params)
2373 if (!descriptor_params_from_paramtypes(state->m->parseddesc,state->m->flags))
2376 /* pre-initialize variables as TYPE_VOID */
2378 i = state->numlocals;
2381 v->type = TYPE_VOID;
2385 /* if this is an instance method initialize the "this" ref type */
2387 if (!(state->m->flags & ACC_STATIC)) {
2388 index = jd->local_map[5*0 + TYPE_ADR];
2389 if (index != UNUSED) {
2390 if (state->validlocals < 1)
2391 TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
2394 if (state->initmethod)
2395 TYPEINFO_INIT_NEWOBJECT(v->typeinfo, NULL);
2397 typeinfo_init_classinfo(&(v->typeinfo), state->m->class);
2403 LOG("'this' argument set.\n");
2405 /* the rest of the arguments and the return type */
2407 if (!typeinfo_init_varinfos_from_methoddesc(locals, state->m->parseddesc,
2409 skip, /* skip 'this' pointer */
2411 &state->returntype))
2414 LOG("Arguments set.\n");
2419 /* typecheck_init_flags ********************************************************
2421 Initialize the basic block flags for the following CFG traversal.
2424 state............the current state of the verifier
2426 *******************************************************************************/
2429 typecheck_init_flags(verifier_state *state)
2434 /* set all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
2436 i = state->basicblockcount;
2437 for (block = state->basicblocks; block; block = block->next) {
2439 #ifdef TYPECHECK_DEBUG
2440 /* check for invalid flags */
2441 if (block->flags != BBFINISHED && block->flags != BBDELETED && block->flags != BBUNDEF)
2443 LOGSTR1("block flags: %d\n",block->flags); LOGFLUSH;
2444 TYPECHECK_ASSERT(false);
2448 if (block->flags >= BBFINISHED) {
2449 block->flags = BBTYPECHECK_UNDEF;
2453 /* the first block is always reached */
2455 if (state->basicblockcount && state->basicblocks[0].flags == BBTYPECHECK_UNDEF)
2456 state->basicblocks[0].flags = BBTYPECHECK_REACHED;
2460 /* typecheck_reset_flags *******************************************************
2462 Reset the flags of basic blocks we have not reached.
2465 state............the current state of the verifier
2467 *******************************************************************************/
2470 typecheck_reset_flags(verifier_state *state)
2474 /* check for invalid flags at exit */
2476 #ifdef TYPECHECK_DEBUG
2477 for (block = state->basicblocks; block; block = block->next) {
2478 if (block->flags != BBDELETED
2479 && block->flags != BBUNDEF
2480 && block->flags != BBFINISHED
2481 && block->flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2482 * some exception handlers,
2485 LOG2("block L%03d has invalid flags after typecheck: %d",
2486 block->nr,block->flags);
2487 TYPECHECK_ASSERT(false);
2492 /* Delete blocks we never reached */
2494 for (block = state->basicblocks; block; block = block->next) {
2495 if (block->flags == BBTYPECHECK_UNDEF)
2496 block->flags = BBDELETED;
2501 /****************************************************************************/
2503 /* This is the main function of the bytecode verifier. It is called */
2504 /* directly after analyse_stack. */
2507 /* meth.............the method to verify */
2508 /* cdata............codegendata for the method */
2509 /* rdata............registerdata for the method */
2512 /* true.............successful verification */
2513 /* false............an exception has been thrown */
2515 /****************************************************************************/
2517 #define MAXPARAMS 255
2519 bool typecheck(jitdata *jd)
2523 varinfo *savedlocals;
2524 verifier_state state; /* current state of the verifier */
2528 /* collect statistics */
2530 #ifdef TYPECHECK_STATISTICS
2531 int count_iterations = 0;
2532 TYPECHECK_COUNT(stat_typechecked);
2533 TYPECHECK_COUNT_FREQ(stat_locals,cdata->maxlocals,STAT_LOCALS);
2534 TYPECHECK_COUNT_FREQ(stat_blocks,cdata->method->basicblockcount/10,STAT_BLOCKS);
2535 TYPECHECK_COUNTIF(cdata->method->exceptiontablelength != 0,stat_methods_with_handlers);
2536 state.stat_maythrow = false;
2539 /* get required compiler data */
2544 /* some logging on entry */
2547 LOGSTR("\n==============================================================================\n");
2548 DOLOG( show_method(jd, SHOW_STACK) );
2549 LOGSTR("\n==============================================================================\n");
2550 LOGMETHOD("Entering typecheck: ",cd->method);
2552 /* initialize the verifier state */
2557 state.basicblockcount = jd->basicblockcount;
2558 state.basicblocks = jd->basicblocks;
2559 state.savedindices = NULL;
2560 state.savedinvars = NULL;
2562 /* check if this method is an instance initializer method */
2564 state.initmethod = (state.m->name == utf_init);
2566 /* initialize the basic block flags for the following CFG traversal */
2568 typecheck_init_flags(&state);
2570 /* number of local variables */
2572 /* In <init> methods we use an extra local variable to indicate whether */
2573 /* the 'this' reference has been initialized. */
2574 /* TYPE_VOID...means 'this' has not been initialized, */
2575 /* TYPE_INT....means 'this' has been initialized. */
2577 state.numlocals = state.jd->localcount;
2578 state.validlocals = state.numlocals;
2579 if (state.initmethod)
2580 state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
2582 state.reverselocalmap = DMNEW(s4, state.validlocals);
2583 for (i=0; i<jd->m->maxlocals; ++i)
2584 for (t=0; t<5; ++t) {
2585 s4 mapped = jd->local_map[5*i + t];
2587 state.reverselocalmap[mapped] = i;
2591 LOG("reverselocalmap:");
2592 for (i=0; i<state.validlocals; ++i) {
2593 LOG2(" %i => javaindex %i", i, state.reverselocalmap[i]);
2596 /* allocate the buffer of active exception handlers */
2598 state.handlers = DMNEW(exceptiontable*, state.cd->exceptiontablelength + 1);
2600 /* save local variables */
2602 savedlocals = DMNEW(varinfo, state.numlocals);
2603 MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
2605 /* initialized local variables of first block */
2607 if (!verify_init_locals(&state))
2610 /* initialize invars of exception handlers */
2612 state.exinvars = state.numlocals;
2613 VAR(state.exinvars)->type = TYPE_ADR;
2614 typeinfo_init_classinfo(&(VAR(state.exinvars)->typeinfo),
2615 class_java_lang_Throwable); /* changed later */
2617 LOG("Exception handler stacks set.\n");
2619 /* loop while there are still blocks to be checked */
2621 TYPECHECK_COUNT(count_iterations);
2623 state.repeat = false;
2625 state.bptr = state.basicblocks;
2627 for (; state.bptr; state.bptr = state.bptr->next) {
2628 LOGSTR1("---- BLOCK %04d, ",state.bptr->nr);
2629 LOGSTR1("blockflags: %d\n",state.bptr->flags);
2632 /* verify reached block */
2633 if (state.bptr->flags == BBTYPECHECK_REACHED) {
2634 if (!verify_basic_block(&state))
2639 LOGIF(state.repeat,"state.repeat == true");
2640 } while (state.repeat);
2644 #ifdef TYPECHECK_STATISTICS
2645 LOG1("Typechecker did %4d iterations",count_iterations);
2646 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2647 TYPECHECK_COUNTIF(state.jsrencountered,stat_typechecked_jsr);
2648 TYPECHECK_COUNTIF(state.stat_maythrow,stat_methods_maythrow);
2651 /* reset the flags of blocks we haven't reached */
2653 typecheck_reset_flags(&state);
2655 /* restore locals */
2657 MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
2659 /* everything's ok */
2661 LOGimp("exiting typecheck");
2664 #endif /* ENABLE_VERIFIER */
2667 * These are local overrides for various environment variables in Emacs.
2668 * Please do not remove this and leave it at the end of the file, where
2669 * Emacs will automagically detect them.
2670 * ---------------------------------------------------------------------
2673 * indent-tabs-mode: t
2677 * vim:noexpandtab:sw=4:ts=4: