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 5309 2006-09-05 11:20:04Z 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 *) The boundaries of jsr subroutines are not well-defined. For a given
105 instruction it may be impossible to tell whether it is part of a
106 subroutine, or to which subroutine it belongs.
108 Solution: The typechecker implements a method developed by
109 Alessandro Coglio[4] which treats each returnAddress as a distinct
110 type that is not merged with other returnAddresses. This way, when a
111 RET instruction is reached, we know exactly which types to propagate
112 to which return target among the possible targets of the RET. The
113 downside of this method is, that for each slot/variable we must
114 store not just one type, but one type *for each possible use of the
115 returnAddresses* that currently are in a slot/variable.[5]
117 *) Checks for uninitialized object instances are hard because after the
118 invocation of <init> on an uninitialized object *all* slots/variables
119 referring to this object (and exactly those slots/variables) must be
120 marked as initialized.
122 Solution: The JVM spec describes a solution, which has been
123 implemented in this typechecker.
128 [1] Actually only the types of slots/variables at the start of each
129 basic block are remembered. Within a basic block the algorithm only keeps
130 the types of the slots/variables for the "current" instruction which is
133 [2] Actually the algorithm iterates through the basic block list until
134 there are no more changes. Theoretically it would be wise to sort the
135 basic blocks topologically beforehand, but the number of average/max
136 iterations observed is so low, that this was not deemed necessary.
138 [3] This is similar to a method proposed by: Alessandro Coglio et al., A
139 Formal Specification of Java Class Loading, Technical Report, Kestrel
140 Institute April 2000, revised July 2000
141 http://www.kestrel.edu/home/people/coglio/loading.pdf
142 An important difference is that Coglio's subtype constraints are checked
143 after loading, while our constraints are checked when the field/method
144 is accessed for the first time, so we can guarantee lexically correct
147 [4] Alessandro Coglio, Simple Verification Technique for Complex Java
148 Bytecode Subroutines, 4th ECOOP Workshop on Formal Techniques for
149 Java-like Programs, June 2002
150 http://www.kestrel.edu/home/people/coglio/ftjp02.pdf
152 [5] This is a major source of code complexity. The main data structures
153 dealing with this are the "typevector set" and the typestack. The
154 "typevector set" is a set of alternative typevectors, such that each
155 typevector specifies the types of the local variables for a single
156 combination of returnAddresses used. Thus we support full polymorphism
157 of subroutines over the types of local variables. The typestack,
158 however, does not support polymorphism, both for historical and JVM-spec
159 reasons. A slot of the typestack may, however, contain multiple
160 alternative returnAddresses, which is realized by a linked list hanging
161 of the typeinfo of the stack slot.
169 #include "vm/types.h"
170 #include "vm/global.h"
172 #ifdef ENABLE_VERIFIER
174 #include "mm/memory.h"
175 #include "toolbox/logging.h"
176 #include "native/native.h"
177 #include "vm/builtin.h"
178 #include "vm/jit/patcher.h"
179 #include "vm/loader.h"
180 #include "vm/options.h"
181 #include "vm/jit/jit.h"
182 #include "vm/jit/show.h"
183 #include "vm/access.h"
184 #include "vm/resolve.h"
185 #include "vm/exceptions.h"
188 /****************************************************************************/
190 /****************************************************************************/
192 #ifdef TYPECHECK_DEBUG
193 #define TYPECHECK_ASSERT(cond) assert(cond)
195 #define TYPECHECK_ASSERT(cond)
198 #ifdef TYPECHECK_VERBOSE_OPT
199 bool opt_typecheckverbose = false;
200 FILE *typecheck_logfile;
201 #define DOLOG(action) do { if (opt_typecheckverbose) {action;} } while(0)
203 #define DOLOG(action)
206 #ifdef TYPECHECK_VERBOSE
207 #define TYPECHECK_VERBOSE_IMPORTANT
208 #define LOG(str) DOLOG(log_text(str))
209 #define LOG1(str,a) DOLOG(dolog(str,a))
210 #define LOG2(str,a,b) DOLOG(dolog(str,a,b))
211 #define LOG3(str,a,b,c) DOLOG(dolog(str,a,b,c))
212 #define LOGIF(cond,str) DOLOG(do {if (cond) log_text(str);} while(0))
213 #ifdef TYPEINFO_DEBUG
214 #define LOGINFO(info) DOLOG(do {typeinfo_print_short(typecheck_logfile,(info));log_finish();} while(0))
216 #define LOGINFO(info)
217 #define typevectorset_print(x,y,z)
219 #define LOGFLUSH DOLOG(fflush(typecheck_logfile))
220 #define LOGNL DOLOG(log_finish())
221 #define LOGSTR(str) DOLOG(log_print(str))
222 #define LOGSTR1(str,a) DOLOG(log_print(str,a))
223 #define LOGSTR2(str,a,b) DOLOG(log_print(str,a,b))
224 #define LOGSTR3(str,a,b,c) DOLOG(log_print(str,a,b,c))
225 #define LOGNAME(c) DOLOG(log_message_utf("class: ",(IS_CLASSREF(c) ? c.ref->name : c.cls->name)))
226 #define LOGMETHOD(str,m) DOLOG(log_message_method(str,m))
230 #define LOG2(str,a,b)
231 #define LOG3(str,a,b,c)
232 #define LOGIF(cond,str)
233 #define LOGINFO(info)
237 #define LOGSTR1(str,a)
238 #define LOGSTR2(str,a,b)
239 #define LOGSTR3(str,a,b,c)
241 #define LOGMETHOD(str,m)
244 #ifdef TYPECHECK_VERBOSE_IMPORTANT
245 #define LOGimp(str) DOLOG(log_text(str))
246 #define LOGimpSTR(str) DOLOG(log_print(str))
249 #define LOGimpSTR(str)
252 #if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
258 typestack_print(FILE *file,stackptr stack)
260 #ifdef TYPEINFO_DEBUG
262 /*fprintf(file,"<%p>",stack);*/
263 typeinfo_print_stacktype(file,stack->type,&(stack->typeinfo));
265 if (stack) fprintf(file," ");
272 typestate_print(FILE *file,stackptr instack,typevector *localset,int size)
274 fprintf(file,"Stack: ");
275 typestack_print(file,instack);
276 fprintf(file," Locals:");
277 typevectorset_print(file,localset,size);
282 /****************************************************************************/
284 /****************************************************************************/
286 #ifdef TYPECHECK_DEBUG
287 /*#define TYPECHECK_STATISTICS*/
290 #ifdef TYPECHECK_STATISTICS
291 #define STAT_ITERATIONS 10
292 #define STAT_BLOCKS 10
293 #define STAT_LOCALS 16
295 static int stat_typechecked = 0;
296 static int stat_typechecked_jsr = 0;
297 static int stat_methods_with_handlers = 0;
298 static int stat_methods_maythrow = 0;
299 static int stat_iterations[STAT_ITERATIONS+1] = { 0 };
300 static int stat_reached = 0;
301 static int stat_copied = 0;
302 static int stat_merged = 0;
303 static int stat_merging_changed = 0;
304 static int stat_backwards = 0;
305 static int stat_blocks[STAT_BLOCKS+1] = { 0 };
306 static int stat_locals[STAT_LOCALS+1] = { 0 };
307 static int stat_ins = 0;
308 static int stat_ins_maythrow = 0;
309 static int stat_ins_stack = 0;
310 static int stat_ins_field = 0;
311 static int stat_ins_field_unresolved = 0;
312 static int stat_ins_field_uninitialized = 0;
313 static int stat_ins_invoke = 0;
314 static int stat_ins_invoke_unresolved = 0;
315 static int stat_ins_primload = 0;
316 static int stat_ins_aload = 0;
317 static int stat_ins_builtin = 0;
318 static int stat_ins_builtin_gen = 0;
319 static int stat_ins_branch = 0;
320 static int stat_ins_switch = 0;
321 static int stat_ins_primitive_return = 0;
322 static int stat_ins_areturn = 0;
323 static int stat_ins_areturn_unresolved = 0;
324 static int stat_ins_athrow = 0;
325 static int stat_ins_athrow_unresolved = 0;
326 static int stat_ins_unchecked = 0;
327 static int stat_handlers_reached = 0;
328 static int stat_savedstack = 0;
330 #define TYPECHECK_MARK(var) ((var) = true)
331 #define TYPECHECK_COUNT(cnt) (cnt)++
332 #define TYPECHECK_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
333 #define TYPECHECK_COUNT_FREQ(array,val,limit) \
335 if ((val) < (limit)) (array)[val]++; \
336 else (array)[limit]++; \
339 static void print_freq(FILE *file,int *array,int limit)
342 for (i=0; i<limit; ++i)
343 fprintf(file," %3d: %8d\n",i,array[i]);
344 fprintf(file," >=%3d: %8d\n",limit,array[limit]);
347 void typecheck_print_statistics(FILE *file) {
348 fprintf(file,"typechecked methods: %8d\n",stat_typechecked);
349 fprintf(file," with JSR : %8d\n",stat_typechecked_jsr);
350 fprintf(file," with handler(s): %8d\n",stat_methods_with_handlers);
351 fprintf(file," with throw(s) : %8d\n",stat_methods_maythrow);
352 fprintf(file,"reached blocks : %8d\n",stat_reached);
353 fprintf(file,"copied states : %8d\n",stat_copied);
354 fprintf(file,"merged states : %8d\n",stat_merged);
355 fprintf(file,"merging changed : %8d\n",stat_merging_changed);
356 fprintf(file,"backwards branches : %8d\n",stat_backwards);
357 fprintf(file,"handlers reached : %8d\n",stat_handlers_reached);
358 fprintf(file,"saved stack (times): %8d\n",stat_savedstack);
359 fprintf(file,"instructions : %8d\n",stat_ins);
360 fprintf(file," stack : %8d\n",stat_ins_stack);
361 fprintf(file," field access : %8d\n",stat_ins_field);
362 fprintf(file," (unresolved) : %8d\n",stat_ins_field_unresolved);
363 fprintf(file," (uninit.) : %8d\n",stat_ins_field_uninitialized);
364 fprintf(file," invocations : %8d\n",stat_ins_invoke);
365 fprintf(file," (unresolved) : %8d\n",stat_ins_invoke_unresolved);
366 fprintf(file," load primitive : (currently not counted) %8d\n",stat_ins_primload);
367 fprintf(file," load address : %8d\n",stat_ins_aload);
368 fprintf(file," builtins : %8d\n",stat_ins_builtin);
369 fprintf(file," generic : %8d\n",stat_ins_builtin_gen);
370 fprintf(file," branches : %8d\n",stat_ins_branch);
371 fprintf(file," switches : %8d\n",stat_ins_switch);
372 fprintf(file," prim. return : %8d\n",stat_ins_primitive_return);
373 fprintf(file," areturn : %8d\n",stat_ins_areturn);
374 fprintf(file," (unresolved) : %8d\n",stat_ins_areturn_unresolved);
375 fprintf(file," athrow : %8d\n",stat_ins_athrow);
376 fprintf(file," (unresolved) : %8d\n",stat_ins_athrow_unresolved);
377 fprintf(file," unchecked : %8d\n",stat_ins_unchecked);
378 fprintf(file," maythrow : %8d\n",stat_ins_maythrow);
379 fprintf(file,"iterations used:\n");
380 print_freq(file,stat_iterations,STAT_ITERATIONS);
381 fprintf(file,"basic blocks per method / 10:\n");
382 print_freq(file,stat_blocks,STAT_BLOCKS);
383 fprintf(file,"locals:\n");
384 print_freq(file,stat_locals,STAT_LOCALS);
389 #define TYPECHECK_COUNT(cnt)
390 #define TYPECHECK_MARK(var)
391 #define TYPECHECK_COUNTIF(cond,cnt)
392 #define TYPECHECK_COUNT_FREQ(array,val,limit)
395 /****************************************************************************/
396 /* MACROS FOR THROWING EXCEPTIONS */
397 /****************************************************************************/
399 #define TYPECHECK_VERIFYERROR_ret(m,msg,retval) \
401 exceptions_throw_verifyerror((m), (msg)); \
405 #define TYPECHECK_VERIFYERROR_main(msg) TYPECHECK_VERIFYERROR_ret(state.m,(msg),NULL)
406 #define TYPECHECK_VERIFYERROR_bool(msg) TYPECHECK_VERIFYERROR_ret(state->m,(msg),false)
408 /****************************************************************************/
409 /* MACROS FOR STACK SLOT TYPE CHECKING */
410 /****************************************************************************/
412 #define TYPECHECK_CHECK_TYPE(sp,tp,msg) \
414 if ((sp)->type != (tp)) { \
415 exceptions_throw_verifyerror(state->m, (msg)); \
420 #define TYPECHECK_INT(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_INT,"Expected to find integer on stack")
421 #define TYPECHECK_LNG(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_LNG,"Expected to find long on stack")
422 #define TYPECHECK_FLT(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_FLT,"Expected to find float on stack")
423 #define TYPECHECK_DBL(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_DBL,"Expected to find double on stack")
424 #define TYPECHECK_ADR(sp) TYPECHECK_CHECK_TYPE(sp,TYPE_ADR,"Expected to find object on stack")
426 /****************************************************************************/
427 /* VERIFIER STATE STRUCT */
428 /****************************************************************************/
430 /* verifier_state - This structure keeps the current state of the */
431 /* bytecode verifier for passing it between verifier functions. */
433 typedef struct verifier_state {
434 new_instruction *iptr; /* pointer to current instruction */
435 basicblock *bptr; /* pointer to current basic block */
437 methodinfo *m; /* the current method */
438 jitdata *jd; /* jitdata for current method */
439 codegendata *cd; /* codegendata for current method */
440 registerdata *rd; /* registerdata for current method */
442 basicblock *basicblocks;
445 s4 numlocals; /* number of local variables */
446 s4 validlocals; /* number of Java-accessible locals */
447 void *localbuf; /* local variable types for each block start */
448 typevector *localset; /* typevector set for local variables */
449 typedescriptor returntype; /* return type of the current method */
451 stackptr savedstackbuf; /* buffer for saving the stack */
452 stackptr savedstack; /* saved instack of current block */
454 exceptiontable **handlers; /* active exception handlers */
455 stackelement excstack; /* instack for exception handlers */
457 bool repeat; /* if true, blocks are iterated over again */
458 bool initmethod; /* true if this is an "<init>" method */
459 bool jsrencountered; /* true if we there was a JSR */
461 #ifdef TYPECHECK_STATISTICS
462 bool stat_maythrow; /* at least one instruction may throw */
466 /****************************************************************************/
467 /* TYPESTACK MACROS AND FUNCTIONS */
469 /* These macros and functions act on the 'type stack', which is a shorthand */
470 /* for the types of the stackslots of the current stack. The type of a */
471 /* stack slot is usually described by a TYPE_* constant and -- for TYPE_ADR */
472 /* -- by the typeinfo of the slot. The only thing that makes the type stack */
473 /* more complicated are returnAddresses of local subroutines, because a */
474 /* single stack slot may contain a set of more than one possible return */
475 /* address. This is handled by 'return address sets'. A return address set */
476 /* is kept as a linked list dangling off the typeinfo of the stack slot. */
477 /****************************************************************************/
479 #define TYPESTACK_IS_RETURNADDRESS(sptr) \
480 TYPE_IS_RETURNADDRESS((sptr)->type,(sptr)->typeinfo)
482 #define TYPESTACK_RETURNADDRESSSET(sptr) \
483 ((typeinfo_retaddr_set*)TYPEINFO_RETURNADDRESS((sptr)->typeinfo))
485 #define RETURNADDRESSSET_SEEK(set,pos) \
486 do {int i; for (i=pos;i--;) set=set->alt;} while(0)
488 /* typestack_copy **************************************************************
490 Copy the types on the given stack to the destination stack.
492 This function does a straight forward copy except for returnAddress types.
493 For returnAddress slots only the return addresses corresponding to
494 typevectors in the SELECTED set are copied.
497 state............current verifier state
498 y................stack with types to copy
499 selected.........set of selected typevectors
502 *dst.............the destination stack
505 true.............success
506 false............an exception has been thrown
508 *******************************************************************************/
511 typestack_copy(verifier_state *state,stackptr dst,stackptr y,typevector *selected)
514 typeinfo_retaddr_set *sety;
515 typeinfo_retaddr_set *new;
516 typeinfo_retaddr_set **next;
519 for (;dst; dst=dst->prev, y=y->prev) {
520 /* XXX only check the following two in debug mode? */
522 exceptions_throw_verifyerror(state->m,"Stack depth mismatch");
525 if (dst->type != y->type) {
526 exceptions_throw_verifyerror(state->m,"Stack type mismatch");
529 LOG3("copy %p -> %p (type %d)",y,dst,dst->type);
530 if (dst->type == TYPE_ADR) {
531 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
532 /* We copy the returnAddresses from the selected
535 LOG("copying returnAddress");
536 sety = TYPESTACK_RETURNADDRESSSET(y);
538 for (k=0,sel=selected; sel; sel=sel->alt) {
539 LOG1("selected k=%d",sel->k);
544 *next = DNEW(typeinfo_retaddr_set);
545 (*next)->addr = sety->addr;
546 next = &((*next)->alt);
549 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,new);
552 TYPEINFO_CLONE(y->typeinfo,dst->typeinfo);
557 exceptions_throw_verifyerror(state->m,"Stack depth mismatch");
563 /* typestack_put_retaddr *******************************************************
565 Put a returnAddress into a stack slot.
567 The stack slot receives a set of return addresses with as many members as
568 there are typevectors in the local variable set.
571 retaddr..........the returnAddress to set (a basicblock *)
572 loc..............the local variable typevector set
575 *dst.............the destination stack slot
577 *******************************************************************************/
580 typestack_put_retaddr(stackptr dst,void *retaddr,typevector *loc)
582 TYPECHECK_ASSERT(dst->type == TYPE_ADR);
584 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,NULL);
585 for (;loc; loc=loc->alt) {
586 typeinfo_retaddr_set *set = DNEW(typeinfo_retaddr_set);
588 set->alt = TYPESTACK_RETURNADDRESSSET(dst);
589 TYPEINFO_INIT_RETURNADDRESS(dst->typeinfo,set);
593 /* typestack_collapse **********************************************************
595 Collapse the given stack by shortening all return address sets to a single
599 *dst.............the destination stack to collapse
601 *******************************************************************************/
604 typestack_collapse(stackptr dst)
606 for (; dst; dst = dst->prev) {
607 if (TYPESTACK_IS_RETURNADDRESS(dst))
608 TYPESTACK_RETURNADDRESSSET(dst)->alt = NULL;
612 /* typestack_merge *************************************************************
614 Merge the types on one stack into the destination stack.
617 state............current state of the verifier
618 dst..............the destination stack
619 y................the second stack
622 *dst.............receives the result of the stack merge
625 typecheck_TRUE...*dst has been modified
626 typecheck_FALSE..*dst has not been modified
627 typecheck_FAIL...an exception has been thrown
629 *******************************************************************************/
631 static typecheck_result
632 typestack_merge(verifier_state *state,stackptr dst,stackptr y)
635 bool changed = false;
637 for (; dst; dst = dst->prev, y=y->prev) {
639 exceptions_throw_verifyerror(state->m,"Stack depth mismatch");
640 return typecheck_FAIL;
642 if (dst->type != y->type) {
643 exceptions_throw_verifyerror(state->m,"Stack type mismatch");
644 return typecheck_FAIL;
646 if (dst->type == TYPE_ADR) {
647 if (TYPEINFO_IS_PRIMITIVE(dst->typeinfo)) {
648 /* dst has returnAddress type */
649 if (!TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
650 exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
651 return typecheck_FAIL;
655 /* dst has reference type */
656 if (TYPEINFO_IS_PRIMITIVE(y->typeinfo)) {
657 exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
658 return typecheck_FAIL;
660 r = typeinfo_merge(state->m,&(dst->typeinfo),&(y->typeinfo));
661 if (r == typecheck_FAIL)
668 exceptions_throw_verifyerror(state->m,"Stack depth mismatch");
669 return typecheck_FAIL;
674 /* typestack_add ***************************************************************
676 Add the return addresses in the given stack at a given k-index to the
677 corresponding return address sets in the destination stack.
680 dst..............the destination stack
681 y................the second stack
682 ky...............the k-index which should be selected from the Y stack
685 *dst.............receives the result of adding the addresses
687 *******************************************************************************/
690 typestack_add(stackptr dst,stackptr y,int ky)
692 typeinfo_retaddr_set *setd;
693 typeinfo_retaddr_set *sety;
695 for (; dst; dst = dst->prev, y=y->prev) {
696 if (TYPESTACK_IS_RETURNADDRESS(dst)) {
697 setd = TYPESTACK_RETURNADDRESSSET(dst);
698 sety = TYPESTACK_RETURNADDRESSSET(y);
699 RETURNADDRESSSET_SEEK(sety,ky);
702 setd->alt = DNEW(typeinfo_retaddr_set);
703 setd->alt->addr = sety->addr;
704 setd->alt->alt = NULL;
709 /* typestack_separable_with ****************************************************
711 This function answers the question: If variant 'kb' of typestack 'b' is
712 added to typestack 'a', will the result be separable?
714 A typestack is called 'separable' if it has at least one slot of type
715 returnAddress that contains at least two different return addresses.
716 (ie. a RET using the value in this slot could go to more than one target)
719 a................the first typestack
720 b................the second typestack
721 kb...............the k-index of the variant that should be selected
725 true.............the result would be separable
726 false............the result would not be separable
729 'a' and 'b' are assumed to have passed typestack_canmerge!
731 *******************************************************************************/
734 typestack_separable_with(stackptr a,stackptr b,int kb)
736 typeinfo_retaddr_set *seta;
737 typeinfo_retaddr_set *setb;
739 for (; a; a = a->prev, b = b->prev) {
741 if (TYPESTACK_IS_RETURNADDRESS(a)) {
742 TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
743 seta = TYPESTACK_RETURNADDRESSSET(a);
744 setb = TYPESTACK_RETURNADDRESSSET(b);
745 RETURNADDRESSSET_SEEK(setb,kb);
747 for (;seta;seta=seta->alt)
748 if (seta->addr != setb->addr) return true;
751 TYPECHECK_ASSERT(!b);
755 /* typestack_separable_from ****************************************************
757 This function answers the question: Is variant 'ka' of typestack 'a'
758 separable from variant 'kb' of typestack 'b'?
760 Two variants of typestacks are called 'separable' from each other, if there
761 is at least one slot for which the variants contain different return addresses.
762 (ie. a RET using the value in this slot would go to one target in the first
763 variant and to another target in the second variant)
766 a................the first typestack
767 ka...............the k-index of the variant that should be selected
769 b................the second typestack
770 kb...............the k-index of the variant that should be selected
774 true.............the variants are separable
775 false............the variants are not separable
778 'a' and 'b' are assumed to have passed typestack_canmerge!
780 *******************************************************************************/
783 typestack_separable_from(stackptr a,int ka,stackptr b,int kb)
785 typeinfo_retaddr_set *seta;
786 typeinfo_retaddr_set *setb;
788 for (; a; a = a->prev, b = b->prev) {
790 if (TYPESTACK_IS_RETURNADDRESS(a)) {
791 TYPECHECK_ASSERT(TYPESTACK_IS_RETURNADDRESS(b));
792 seta = TYPESTACK_RETURNADDRESSSET(a);
793 setb = TYPESTACK_RETURNADDRESSSET(b);
794 RETURNADDRESSSET_SEEK(seta,ka);
795 RETURNADDRESSSET_SEEK(setb,kb);
797 if (seta->addr != setb->addr) return true;
800 TYPECHECK_ASSERT(!b);
804 /****************************************************************************/
805 /* TYPESTATE FUNCTIONS */
807 /* These functions act on the 'type state', which comprises: */
808 /* - the types of the stack slots of the current stack */
809 /* - the set of type vectors describing the local variables */
810 /****************************************************************************/
812 /* typestate_merge *************************************************************
814 Merge the types of one state into the destination state.
817 state............current state of the verifier
818 deststack........the destination stack
819 destloc..........the destination set of local variable typevectors
820 ystack...........the second stack
821 yloc.............the second set of local variable typevectors
824 *deststack.......receives the result of the stack merge
825 *destloc.........receives the result of the local variable merge
828 typecheck_TRUE...destination state has been modified
829 typecheck_FALSE..destination state has not been modified
830 typecheck_FAIL...an exception has been thrown
832 *******************************************************************************/
834 static typecheck_result
835 typestate_merge(verifier_state *state,
836 stackptr deststack,typevector *destloc,
837 stackptr ystack,typevector *yloc)
839 typevector *dvec,*yvec;
841 bool changed = false;
845 LOGSTR("dstack: "); DOLOG(typestack_print(typecheck_logfile,deststack)); LOGNL;
846 LOGSTR("ystack: "); DOLOG(typestack_print(typecheck_logfile,ystack)); LOGNL;
847 LOGSTR("dloc : "); DOLOG(typevectorset_print(typecheck_logfile,destloc,state->numlocals)); LOGNL;
848 LOGSTR("yloc : "); DOLOG(typevectorset_print(typecheck_logfile,yloc,state->numlocals)); LOGNL;
851 /* The stack is always merged. If there are returnAddresses on
852 * the stack they are ignored in this step. */
854 r = typestack_merge(state,deststack,ystack);
855 if (r == typecheck_FAIL)
859 /* If there have not been any JSRs we just have a single typevector merge */
860 if (!state->jsrencountered) {
861 r = typevector_merge(state->m,destloc,yloc,state->numlocals);
862 if (r == typecheck_FAIL)
867 for (yvec=yloc; yvec; yvec=yvec->alt) {
870 /* Check if the typestates (deststack,destloc) will be
871 * separable when (ystack,yvec) is added. */
873 if (!typestack_separable_with(deststack,ystack,ky)
874 && !typevectorset_separable_with(destloc,yvec,state->numlocals))
876 /* No, the resulting set won't be separable, thus we
877 * may merge all states in (deststack,destloc) and
880 typestack_collapse(deststack);
881 if (typevectorset_collapse(state->m,destloc,state->numlocals) == typecheck_FAIL)
882 return typecheck_FAIL;
883 if (typevector_merge(state->m,destloc,yvec,state->numlocals) == typecheck_FAIL)
884 return typecheck_FAIL;
887 /* Yes, the resulting set will be separable. Thus we check
888 * if we may merge (ystack,yvec) with a single state in
889 * (deststack,destloc). */
891 for (dvec=destloc,kd=0; dvec; dvec=dvec->alt, kd++) {
892 if (!typestack_separable_from(ystack,ky,deststack,kd)
893 && !typevector_separable_from(yvec,dvec,state->numlocals))
895 /* The typestate (ystack,yvec) is not separable from
896 * (deststack,dvec) by any returnAddress. Thus we may
897 * merge the states. */
899 r = typevector_merge(state->m,dvec,yvec,state->numlocals);
900 if (r == typecheck_FAIL)
908 /* The typestate (ystack,yvec) is separable from all typestates
909 * (deststack,destloc). Thus we must add this state to the
912 typestack_add(deststack,ystack,ky);
913 typevectorset_add(destloc,yvec,state->numlocals);
922 LOGSTR("dstack: "); DOLOG(typestack_print(typecheck_logfile,deststack)); LOGNL;
923 LOGSTR("dloc : "); DOLOG(typevectorset_print(typecheck_logfile,destloc,state->numlocals)); LOGNL;
929 /* typestate_reach *************************************************************
931 Reach a destination block and propagate stack and local variable types
934 state............current state of the verifier
935 destblock........destination basic block
936 ystack...........stack to propagate
937 yloc.............set of local variable typevectors to propagate
940 state->repeat....set to true if the verifier must iterate again
941 over the basic blocks
944 true.............success
945 false............an exception has been thrown
947 *******************************************************************************/
950 typestate_reach(verifier_state *state,
951 basicblock *destblock,
952 stackptr ystack,typevector *yloc)
956 bool changed = false;
959 LOG1("reaching block L%03d",destblock->nr);
960 TYPECHECK_COUNT(stat_reached);
962 destidx = destblock - state->basicblocks;
963 destloc = MGET_TYPEVECTOR(state->localbuf,destidx,state->numlocals);
965 /* When branching backwards we have to check for uninitialized objects */
967 if (destblock <= state->bptr) {
972 TYPECHECK_COUNT(stat_backwards);
974 for (sp = ystack; sp; sp=sp->prev)
975 if (sp->type == TYPE_ADR &&
976 TYPEINFO_IS_NEWOBJECT(sp->typeinfo)) {
977 /*printf("current: %d, dest: %d\n", state->bptr->nr, destblock->nr);*/
978 exceptions_throw_verifyerror(state->m,"Branching backwards with uninitialized object on stack");
982 for (i=0; i<state->numlocals; ++i)
983 if (yloc->td[i].type == TYPE_ADR &&
984 TYPEINFO_IS_NEWOBJECT(yloc->td[i].info)) {
985 exceptions_throw_verifyerror(state->m,"Branching backwards with uninitialized object in local variable");
991 if (destblock->flags == BBTYPECHECK_UNDEF) {
992 /* The destblock has never been reached before */
994 TYPECHECK_COUNT(stat_copied);
995 LOG1("block (index %04d) reached first time",destidx);
997 if (!typestack_copy(state,destblock->instack,ystack,yloc))
999 typevectorset_copy_inplace(yloc,destloc,state->numlocals);
1003 /* The destblock has already been reached before */
1005 TYPECHECK_COUNT(stat_merged);
1006 LOG1("block (index %04d) reached before",destidx);
1008 r = typestate_merge(state,destblock->instack,destloc,ystack,yloc);
1009 if (r == typecheck_FAIL)
1012 TYPECHECK_COUNTIF(changed,stat_merging_changed);
1017 destblock->flags = BBTYPECHECK_REACHED;
1018 if (destblock <= state->bptr) {
1020 state->repeat = true;
1026 /* typestate_ret ***************************************************************
1028 Reach the destinations of a RET instruction.
1031 state............current state of the verifier
1032 retindex.........index of local variable containing the returnAddress
1035 state->repeat....set to true if the verifier must iterate again
1036 over the basic blocks
1039 true.............success
1040 false............an exception has been thrown
1042 *******************************************************************************/
1045 typestate_ret(verifier_state *state,int retindex)
1048 typevector *selected;
1049 basicblock *destblock;
1051 for (yvec=state->localset; yvec; ) {
1052 if (!TYPEDESC_IS_RETURNADDRESS(yvec->td[retindex])) {
1053 exceptions_throw_verifyerror(state->m,"Illegal instruction: RET on non-returnAddress");
1057 destblock = (basicblock*) TYPEINFO_RETURNADDRESS(yvec->td[retindex].info);
1059 selected = typevectorset_select(&yvec,retindex,destblock);
1061 if (!typestate_reach(state,destblock,state->bptr->outstack,selected))
1067 /* typestate_save_instack ******************************************************
1069 Save the input stack of the current basic block in the "savedstackbuf"
1070 of the verifier state.
1072 This function must be called before an instruction modifies a stack slot
1073 that happens to be part of the instack of the current block. In such
1074 cases the instack of the block must be saved, and restored at the end
1075 of the analysis of this basic block, so that the instack again reflects
1076 the *input* to this basic block (and does not randomly contain types
1077 that appear within the block).
1080 state............current state of the verifier
1082 *******************************************************************************/
1085 typestate_save_instack(verifier_state *state)
1091 LOG("saving input stack types");
1092 if (!state->savedstackbuf) {
1093 LOG("allocating savedstack buffer");
1094 state->savedstackbuf = DMNEW(stackelement, state->cd->maxstack);
1095 state->savedstackbuf->prev = NULL;
1096 for (i = 1; i < state->cd->maxstack; ++i)
1097 state->savedstackbuf[i].prev = state->savedstackbuf+(i-1);
1099 sp = state->savedstack = state->bptr->instack;
1100 dest = state->bptr->instack = state->savedstackbuf + (state->bptr->indepth-1);
1102 for(; sp; sp=sp->prev, dest=dest->prev) {
1103 dest->type = sp->type;
1104 TYPEINFO_COPY(sp->typeinfo,dest->typeinfo);
1108 /* typestate_restore_instack ***************************************************
1110 Restore the input stack of the current basic block that has been previously
1111 saved by `typestate_save_instack`.
1114 state............current state of the verifier
1116 *******************************************************************************/
1119 typestate_restore_instack(verifier_state *state)
1124 TYPECHECK_COUNT(stat_savedstack);
1125 LOG("restoring saved instack");
1127 sp = state->bptr->instack;
1128 dest = state->savedstack;
1129 for(; sp; sp=sp->prev, dest=dest->prev) {
1130 dest->type = sp->type;
1131 TYPEINFO_COPY(sp->typeinfo,dest->typeinfo);
1134 state->bptr->instack = state->savedstack;
1135 state->savedstack = NULL;
1138 /****************************************************************************/
1140 /****************************************************************************/
1142 #define COPYTYPE(source,dest) \
1143 {if ((source)->type == TYPE_ADR) \
1144 TYPEINFO_COPY((source)->typeinfo,(dest)->typeinfo);}
1146 #define ISBUILTIN(v) (bte->fp == (functionptr) (v))
1148 /* verify_invocation ***********************************************************
1150 Verify an ICMD_INVOKE* instruction.
1153 state............the current state of the verifier
1156 true.............successful verification,
1157 false............an exception has been thrown.
1159 *******************************************************************************/
1162 verify_invocation(verifier_state *state)
1164 unresolved_method *um; /* struct describing the called method */
1165 constant_FMIref *mref; /* reference to the called method */
1166 methodinfo *mi; /* resolved method (if any) */
1167 methoddesc *md; /* descriptor of the called method */
1168 utf *mname; /* method name */
1169 utf *mclassname; /* name of the method's class */
1170 bool specialmethod; /* true if a <...> method is called */
1171 int opcode; /* invocation opcode */
1172 bool callinginit; /* true if <init> is called */
1173 new_instruction *ins;
1174 classref_or_classinfo initclass;
1176 stackelement *arg; /* argument pointer */
1177 stackelement *dst; /* result stack of the invocation */
1178 int i; /* counter */
1179 u1 rtype; /* return type of called method */
1180 resolve_result_t result;
1182 if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
1183 /* unresolved method */
1184 um = state->iptr->sx.s23.s3.um;
1185 mref = um->methodref;
1188 /* resolved method */
1190 mref = state->iptr->sx.s23.s3.fmiref;
1193 md = mref->parseddesc.md;
1196 if (IS_FMIREF_RESOLVED(mref)) {
1197 mi = mref->p.method;
1198 mclassname = mi->class->name;
1202 mclassname = mref->p.classref->name;
1205 specialmethod = (mname->text[0] == '<');
1206 opcode = state->iptr[0].opc;
1207 dst = state->iptr->dst.var;
1209 /* prevent compiler warnings */
1213 /* check whether we are calling <init> */
1215 callinginit = (opcode == ICMD_INVOKESPECIAL && mname == utf_init);
1216 if (specialmethod && !callinginit)
1217 TYPECHECK_VERIFYERROR_bool("Invalid invocation of special method");
1219 /* allocate parameters if necessary */
1222 if (!descriptor_params_from_paramtypes(md,
1223 (opcode == ICMD_INVOKESTATIC) ? ACC_STATIC : ACC_NONE))
1226 /* check parameter types */
1228 i = md->paramcount; /* number of parameters including 'this'*/
1231 arg = state->iptr->sx.s23.s2.args[i];
1232 td = md->paramtypes + i;
1233 if (arg->type != td->type)
1234 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch in method invocation");
1235 if (arg->type == TYPE_ADR) {
1236 LOGINFO(&(arg->typeinfo));
1237 if (i==0 && callinginit)
1239 /* first argument to <init> method */
1240 if (!TYPEINFO_IS_NEWOBJECT(arg->typeinfo))
1241 TYPECHECK_VERIFYERROR_bool("Calling <init> on initialized object");
1243 /* get the address of the NEW instruction */
1244 LOGINFO(&(arg->typeinfo));
1245 ins = (new_instruction*)TYPEINFO_NEWOBJECT_INSTRUCTION(arg->typeinfo);
1247 initclass = ins[-1].sx.val.c;
1249 initclass.cls = state->m->class;
1250 LOGSTR("class: "); LOGNAME(initclass); LOGNL;
1254 /* non-adress argument. if this is the first argument and we are */
1255 /* invoking an instance method, this is an error. */
1256 if (i==0 && opcode != ICMD_INVOKESTATIC) {
1257 TYPECHECK_VERIFYERROR_bool("Parameter type mismatch for 'this' argument");
1263 LOG("checking return type");
1264 rtype = md->returntype.type;
1265 if (rtype != TYPE_VOID) {
1266 if (rtype != dst->type)
1267 TYPECHECK_VERIFYERROR_bool("Return type mismatch in method invocation");
1268 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dst->typeinfo)))
1273 LOG("replacing uninitialized object");
1274 /* replace uninitialized object type on stack */
1276 /* for all live-in and live-through variables */
1277 for (i=0; i<state->iptr->s1.argcount; ++i) {
1278 arg = state->iptr->sx.s23.s2.args[i];
1279 if (arg->type == TYPE_ADR
1280 && TYPEINFO_IS_NEWOBJECT(arg->typeinfo)
1281 && TYPEINFO_NEWOBJECT_INSTRUCTION(arg->typeinfo) == ins)
1283 LOG("replacing uninitialized type on stack");
1285 /* If this stackslot is in the instack of
1286 * this basic block we must save the type(s)
1287 * we are going to replace.
1289 /* XXX this needs a new check */
1290 if (arg <= state->bptr->instack && !state->savedstack)
1291 typestate_save_instack(state);
1293 if (!typeinfo_init_class(&(arg->typeinfo),initclass))
1298 /* replace uninitialized object type in locals */
1299 if (!typevectorset_init_object(state->localset,ins,initclass,state->numlocals))
1302 /* initializing the 'this' reference? */
1305 TYPECHECK_ASSERT(state->initmethod);
1306 /* { we are initializing the 'this' reference } */
1307 /* must be <init> of current class or direct superclass */
1308 /* the current class is linked, so must be its superclass. thus we can be */
1309 /* sure that resolving will be trivial. */
1314 if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
1315 return false; /* exception */
1318 /* if lazy resolving did not succeed, it's not one of the allowed classes */
1319 /* otherwise we check it directly */
1320 if (cls == NULL || (cls != state->m->class && cls != state->m->class->super.cls)) {
1321 TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
1324 /* set our marker variable to type int */
1325 LOG("setting <init> marker");
1326 typevectorset_store(state->localset,state->numlocals-1,TYPE_INT,NULL);
1329 /* { we are initializing an instance created with NEW } */
1330 if ((IS_CLASSREF(initclass) ? initclass.ref->name : initclass.cls->name) != mclassname) {
1331 TYPECHECK_VERIFYERROR_bool("wrong <init> called for uninitialized reference");
1336 /* try to resolve the method lazily */
1338 result = new_resolve_method_lazy(state->iptr,state->m);
1339 if (result == resolveFailed)
1342 if (result != resolveSucceeded) {
1344 um = new_create_unresolved_method(state->m->class,
1345 state->m, state->iptr);
1351 /* record subtype constraints for parameters */
1353 if (!new_constrain_unresolved_method(um,state->m->class,state->m,state->iptr))
1354 return false; /* XXX maybe wrap exception */
1356 /* store the unresolved_method pointer */
1358 state->iptr->sx.s23.s3.um = um;
1359 state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
1362 assert(IS_FMIREF_RESOLVED(state->iptr->sx.s23.s3.fmiref));
1368 /* verify_generic_builtin ******************************************************
1370 Verify the call of a generic builtin method.
1373 state............the current state of the verifier
1376 true.............successful verification,
1377 false............an exception has been thrown.
1379 *******************************************************************************/
1382 verify_generic_builtin(verifier_state *state)
1384 builtintable_entry *bte;
1390 TYPECHECK_COUNT(stat_ins_builtin_gen);
1392 bte = state->iptr->sx.s23.s3.bte;
1396 /* check the types of the arguments on the stack */
1398 for (i--; i >= 0; i--) {
1399 arg = state->iptr->sx.s23.s2.args[i];
1401 if (arg->type != md->paramtypes[i].type) {
1402 TYPECHECK_VERIFYERROR_bool("parameter type mismatch for builtin method");
1405 #ifdef TYPECHECK_DEBUG
1406 /* generic builtins may only take primitive types and java.lang.Object references */
1407 if (arg->type == TYPE_ADR && md->paramtypes[i].classref->name != utf_java_lang_Object) {
1408 *exceptionptr = new_internalerror("generic builtin method with non-generic reference parameter");
1414 /* check the return type */
1416 rtype = md->returntype.type;
1417 if (rtype != TYPE_VOID) {
1420 dst = state->iptr->dst.var;
1421 if (rtype != dst->type)
1422 TYPECHECK_VERIFYERROR_bool("Return type mismatch in generic builtin invocation");
1423 if (!typeinfo_init_from_typedesc(&(md->returntype),NULL,&(dst->typeinfo)))
1430 /* verify_builtin **************************************************************
1432 Verify the call of a builtin method.
1435 state............the current state of the verifier
1438 true.............successful verification,
1439 false............an exception has been thrown.
1441 *******************************************************************************/
1444 verify_builtin(verifier_state *state)
1446 builtintable_entry *bte;
1447 classref_or_classinfo cls;
1448 stackptr dst; /* output stack of current instruction */
1450 bte = state->iptr->sx.s23.s3.bte;
1451 dst = state->iptr->dst.var;
1453 /* XXX this is an ugly if-chain but twisti did not want a function */
1454 /* pointer in builtintable_entry for this, so here you go.. ;) */
1456 if (ISBUILTIN(BUILTIN_new)) {
1457 if (state->iptr[-1].opc != ICMD_ACONST)
1458 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_new without class");
1459 cls = state->iptr[-1].sx.val.c;
1460 TYPEINFO_INIT_NEWOBJECT(dst->typeinfo,state->iptr);
1462 else if (ISBUILTIN(BUILTIN_newarray_boolean)) {
1463 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1464 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BOOLEAN);
1466 else if (ISBUILTIN(BUILTIN_newarray_char)) {
1467 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1468 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_CHAR);
1470 else if (ISBUILTIN(BUILTIN_newarray_float)) {
1471 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1472 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_FLOAT);
1474 else if (ISBUILTIN(BUILTIN_newarray_double)) {
1475 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1476 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_DOUBLE);
1478 else if (ISBUILTIN(BUILTIN_newarray_byte)) {
1479 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1480 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_BYTE);
1482 else if (ISBUILTIN(BUILTIN_newarray_short)) {
1483 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1484 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_SHORT);
1486 else if (ISBUILTIN(BUILTIN_newarray_int)) {
1487 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1488 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_INT);
1490 else if (ISBUILTIN(BUILTIN_newarray_long)) {
1491 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1492 TYPEINFO_INIT_PRIMITIVE_ARRAY(dst->typeinfo,ARRAYTYPE_LONG);
1494 else if (ISBUILTIN(BUILTIN_newarray))
1496 TYPECHECK_INT(state->iptr->sx.s23.s2.args[0]);
1497 if (state->iptr[-1].opc != ICMD_ACONST)
1498 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_newarray without class");
1499 /* XXX check that it is an array class(ref) */
1500 typeinfo_init_class(&(dst->typeinfo),state->iptr[-1].sx.val.c);
1502 else if (ISBUILTIN(BUILTIN_arrayinstanceof))
1504 TYPECHECK_ADR(state->iptr->sx.s23.s2.args[0]);
1505 if (state->iptr[-1].opc != ICMD_ACONST)
1506 TYPECHECK_VERIFYERROR_bool("illegal instruction: builtin_arrayinstanceof without class");
1507 /* XXX check that it is an array class(ref) */
1510 return verify_generic_builtin(state);
1515 /* verify_multianewarray *******************************************************
1517 Verify a MULTIANEWARRAY instruction.
1520 state............the current state of the verifier
1523 true.............successful verification,
1524 false............an exception has been thrown.
1526 *******************************************************************************/
1529 verify_multianewarray(verifier_state *state)
1532 classinfo *arrayclass;
1533 arraydescriptor *desc;
1536 /* check the array lengths on the stack */
1537 i = state->iptr->s1.argcount;
1539 TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
1542 arg = state->iptr->sx.s23.s2.args[i];
1543 /* XXX this should be checked in stack.c: */
1545 TYPECHECK_VERIFYERROR_bool("Unable to pop operand off an empty stack");
1549 /* check array descriptor */
1550 if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
1551 /* the array class reference has already been resolved */
1552 arrayclass = state->iptr->sx.s23.s3.c.cls;
1554 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
1555 if ((desc = arrayclass->vftbl->arraydesc) == NULL)
1556 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1557 if (desc->dimension < state->iptr->s1.argcount)
1558 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1560 /* set the array type of the result */
1561 typeinfo_init_classinfo(&(state->iptr->dst.var->typeinfo), arrayclass);
1565 constant_classref *cr;
1567 /* the array class reference is still unresolved */
1568 /* check that the reference indicates an array class of correct dimension */
1569 cr = state->iptr->sx.s23.s3.c.ref;
1574 /* { the dimension of the array class == i } */
1576 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
1577 if (i < state->iptr->s1.argcount)
1578 TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
1580 /* set the array type of the result */
1581 if (!typeinfo_init_class(&(state->iptr->dst.var->typeinfo),CLASSREF_OR_CLASSINFO(cr)))
1589 /* verify_basic_block **********************************************************
1591 Perform bytecode verification of a basic block.
1594 state............the current state of the verifier
1597 true.............successful verification,
1598 false............an exception has been thrown.
1600 *******************************************************************************/
1603 verify_basic_block(verifier_state *state)
1605 int opcode; /* current opcode */
1606 int len; /* for counting instructions, etc. */
1607 bool superblockend; /* true if no fallthrough to next block */
1608 new_instruction *iptr; /* the current instruction */
1610 basicblock *tbptr; /* temporary for target block */
1611 basicblock **tptr; /* pointer into target list of switch instr. */
1612 classinfo *cls; /* temporary */
1613 bool maythrow; /* true if this instruction may throw */
1614 unresolved_field *uf; /* for field accesses */
1615 constant_FMIref *fieldref; /* for field accesses */
1619 resolve_result_t result;
1620 branch_target_t *table;
1621 lookup_target_t *lookup;
1623 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
1626 superblockend = false;
1627 state->bptr->flags = BBFINISHED;
1628 b_index = state->bptr - state->basicblocks;
1630 /* prevent compiler warnings */
1634 /* determine the active exception handlers for this block */
1635 /* XXX could use a faster algorithm with sorted lists or */
1638 for (i = 0; i < state->cd->exceptiontablelength; ++i) {
1639 if ((state->cd->exceptiontable[i].start <= state->bptr) && (state->cd->exceptiontable[i].end > state->bptr)) {
1640 LOG1("active handler L%03d", state->cd->exceptiontable[i].handler->nr);
1641 state->handlers[len++] = state->cd->exceptiontable + i;
1644 state->handlers[len] = NULL;
1646 /* init variable types at the start of this block */
1647 typevectorset_copy_inplace(MGET_TYPEVECTOR(state->localbuf,b_index,state->numlocals),
1648 state->localset,state->numlocals);
1650 if (state->handlers[0])
1651 for (i=0; i<state->numlocals; ++i)
1652 if (state->localset->td[i].type == TYPE_ADR
1653 && TYPEINFO_IS_NEWOBJECT(state->localset->td[i].info)) {
1654 /* XXX we do not check this for the uninitialized 'this' instance in */
1655 /* <init> methods. Otherwise there are problems with try blocks in */
1656 /* <init>. The spec seems to indicate that we should perform the test*/
1657 /* in all cases, but this fails with real code. */
1658 /* Example: org/eclipse/ui/internal/PerspectiveBarNewContributionItem*/
1659 /* of eclipse 3.0.2 */
1660 /* XXX Try to show that the check is not necessary for 'this'! */
1661 if (TYPEINFO_NEWOBJECT_INSTRUCTION(state->localset->td[i].info) != NULL) {
1662 /*show_icmd_method(state->m, state->cd, state->rd);*/
1663 printf("Uninitialized variable: %d, block: %d\n", i, state->bptr->nr);
1664 TYPECHECK_VERIFYERROR_bool("Uninitialized object in local variable inside try block");
1667 DOLOG(typestate_print(typecheck_logfile,state->bptr->instack,state->localset,state->numlocals));
1670 /* loop over the instructions */
1671 len = state->bptr->icount;
1672 state->iptr = /* XXX */ (new_instruction *) state->bptr->iinstr;
1673 while (--len >= 0) {
1674 TYPECHECK_COUNT(stat_ins);
1678 DOLOG(typestate_print(typecheck_logfile,NULL,state->localset,state->numlocals));
1681 DOLOG(show_icmd(state->iptr,false)); LOGNL; LOGFLUSH;
1684 dst = iptr->dst.var;
1689 /****************************************/
1690 /* STACK MANIPULATIONS */
1692 /* We just need to copy the typeinfo */
1693 /* for slots containing addresses. */
1695 /* CAUTION: We assume that the destination stack
1696 * slots were continuously allocated in
1697 * memory! (The current implementation in
1702 TYPECHECK_COUNT(stat_ins_stack);
1703 COPYTYPE(iptr->s1.var, iptr->dst.var);
1707 TYPECHECK_COUNT(stat_ins_stack);
1708 COPYTYPE(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+2]);
1709 COPYTYPE(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+1]);
1710 COPYTYPE(iptr->dst.dupslots[2+2], iptr->dst.dupslots[2+0]);
1714 TYPECHECK_COUNT(stat_ins_stack);
1715 COPYTYPE(iptr->dst.dupslots[ 2], iptr->dst.dupslots[3+3]);
1716 COPYTYPE(iptr->dst.dupslots[ 1], iptr->dst.dupslots[3+2]);
1717 COPYTYPE(iptr->dst.dupslots[ 0], iptr->dst.dupslots[3+1]);
1718 COPYTYPE(iptr->dst.dupslots[3+3], iptr->dst.dupslots[3+0]);
1722 TYPECHECK_COUNT(stat_ins_stack);
1723 COPYTYPE(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+1]);
1724 COPYTYPE(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+0]);
1728 TYPECHECK_COUNT(stat_ins_stack);
1729 COPYTYPE(iptr->dst.dupslots[ 2], iptr->dst.dupslots[3+4]);
1730 COPYTYPE(iptr->dst.dupslots[ 1], iptr->dst.dupslots[3+3]);
1731 COPYTYPE(iptr->dst.dupslots[ 0], iptr->dst.dupslots[3+2]);
1732 COPYTYPE(iptr->dst.dupslots[3+4], iptr->dst.dupslots[3+1]);
1733 COPYTYPE(iptr->dst.dupslots[3+3], iptr->dst.dupslots[3+0]);
1737 TYPECHECK_COUNT(stat_ins_stack);
1738 COPYTYPE(iptr->dst.dupslots[ 3], iptr->dst.dupslots[4+5]);
1739 COPYTYPE(iptr->dst.dupslots[ 2], iptr->dst.dupslots[4+4]);
1740 COPYTYPE(iptr->dst.dupslots[ 1], iptr->dst.dupslots[4+3]);
1741 COPYTYPE(iptr->dst.dupslots[ 0], iptr->dst.dupslots[4+2]);
1742 COPYTYPE(iptr->dst.dupslots[4+5], iptr->dst.dupslots[4+1]);
1743 COPYTYPE(iptr->dst.dupslots[4+4], iptr->dst.dupslots[4+0]);
1747 TYPECHECK_COUNT(stat_ins_stack);
1748 COPYTYPE(iptr->dst.dupslots[ 1], iptr->dst.dupslots[2+0]);
1749 COPYTYPE(iptr->dst.dupslots[ 0], iptr->dst.dupslots[2+1]);
1752 /****************************************/
1753 /* PRIMITIVE VARIABLE ACCESS */
1755 case ICMD_ILOAD: if (!typevectorset_checktype(state->localset,state->iptr->s1.localindex,TYPE_INT))
1756 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1758 case ICMD_IINC: if (!typevectorset_checktype(state->localset,state->iptr->s1.localindex,TYPE_INT))
1759 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1761 case ICMD_FLOAD: if (!typevectorset_checktype(state->localset,state->iptr->s1.localindex,TYPE_FLT))
1762 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1764 case ICMD_LLOAD: if (!typevectorset_checktype(state->localset,state->iptr->s1.localindex,TYPE_LNG))
1765 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1767 case ICMD_DLOAD: if (!typevectorset_checktype(state->localset,state->iptr->s1.localindex,TYPE_DBL))
1768 TYPECHECK_VERIFYERROR_bool("Local variable type mismatch");
1771 case ICMD_ISTORE: typevectorset_store(state->localset,state->iptr->dst.localindex,TYPE_INT,NULL); break;
1772 case ICMD_FSTORE: typevectorset_store(state->localset,state->iptr->dst.localindex,TYPE_FLT,NULL); break;
1773 case ICMD_LSTORE: typevectorset_store_twoword(state->localset,state->iptr->dst.localindex,TYPE_LNG); break;
1774 case ICMD_DSTORE: typevectorset_store_twoword(state->localset,state->iptr->dst.localindex,TYPE_DBL); break;
1776 /****************************************/
1777 /* LOADING ADDRESS FROM VARIABLE */
1780 TYPECHECK_COUNT(stat_ins_aload);
1782 /* loading a returnAddress is not allowed */
1783 if (state->jsrencountered) {
1784 if (!typevectorset_checkreference(state->localset,state->iptr->s1.localindex)) {
1785 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1787 if (typevectorset_copymergedtype(state->m,state->localset,state->iptr->s1.localindex,&(dst->typeinfo)) == -1)
1791 if (!TYPEDESC_IS_REFERENCE(state->localset->td[state->iptr->s1.localindex])) {
1792 TYPECHECK_VERIFYERROR_bool("illegal instruction: ALOAD loading non-reference");
1794 TYPEINFO_COPY(state->localset->td[state->iptr->s1.localindex].info,dst->typeinfo);
1798 /****************************************/
1799 /* STORING ADDRESS TO VARIABLE */
1802 if (state->handlers[0] && TYPEINFO_IS_NEWOBJECT(state->iptr->s1.var->typeinfo)) {
1803 TYPECHECK_VERIFYERROR_bool("Storing uninitialized object in local variable inside try block");
1806 if (TYPESTACK_IS_RETURNADDRESS(state->iptr->s1.var)) {
1807 typevectorset_store_retaddr(state->localset,state->iptr->dst.localindex,&(state->iptr->s1.var->typeinfo));
1810 typevectorset_store(state->localset,state->iptr->dst.localindex,TYPE_ADR,
1811 &(state->iptr->s1.var->typeinfo));
1815 /****************************************/
1816 /* LOADING ADDRESS FROM ARRAY */
1819 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->iptr->s1.var->typeinfo))
1820 TYPECHECK_VERIFYERROR_bool("illegal instruction: AALOAD on non-reference array");
1822 if (!typeinfo_init_component(&state->iptr->s1.var->typeinfo,&dst->typeinfo))
1827 /****************************************/
1831 case ICMD_PUTSTATIC:
1832 case ICMD_PUTFIELDCONST:
1833 case ICMD_PUTSTATICCONST:
1834 TYPECHECK_COUNT(stat_ins_field);
1836 if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
1837 uf = state->iptr->sx.s23.s3.uf;
1838 fieldref = uf->fieldref;
1842 fieldref = state->iptr->sx.s23.s3.fmiref;
1845 goto fieldaccess_tail;
1848 case ICMD_GETSTATIC:
1849 TYPECHECK_COUNT(stat_ins_field);
1851 if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
1852 uf = state->iptr->sx.s23.s3.uf;
1853 fieldref = uf->fieldref;
1857 fieldref = state->iptr->sx.s23.s3.fmiref;
1860 /* the result is pushed on the stack */
1861 if (dst->type == TYPE_ADR) {
1862 if (!typeinfo_init_from_typedesc(fieldref->parseddesc.fd,NULL,&(dst->typeinfo)))
1867 /* try to resolve the field reference lazily */
1868 result = new_resolve_field_lazy(state->iptr, state->m);
1869 if (result == resolveFailed)
1872 if (result != resolveSucceeded) {
1874 uf = new_create_unresolved_field(state->m->class, state->m, state->iptr);
1878 state->iptr->sx.s23.s3.uf = uf;
1879 state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
1882 /* record the subtype constraints for this field access */
1883 if (!new_constrain_unresolved_field(uf,state->m->class,state->m,state->iptr))
1884 return false; /* XXX maybe wrap exception? */
1886 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(state->iptr),stat_ins_field_unresolved);
1887 TYPECHECK_COUNTIF(INSTRUCTION_IS_RESOLVED(state->iptr) && !state->iptr->sx.s23.s3.fmiref->p.field->class->initialized,stat_ins_field_uninitialized);
1893 /****************************************/
1894 /* PRIMITIVE ARRAY ACCESS */
1896 case ICMD_ARRAYLENGTH:
1897 if (!TYPEINFO_MAYBE_ARRAY(state->iptr->s1.var->typeinfo)
1898 && state->iptr->s1.var->typeinfo.typeclass.cls != pseudo_class_Arraystub)
1899 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARRAYLENGTH on non-array");
1904 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_BOOLEAN)
1905 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_BYTE))
1906 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1910 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_CHAR))
1911 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1915 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_DOUBLE))
1916 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1920 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_FLOAT))
1921 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1925 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_INT))
1926 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1930 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_SHORT))
1931 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1935 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_LONG))
1936 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1941 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_BOOLEAN)
1942 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_BYTE))
1943 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1947 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_CHAR))
1948 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1952 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_DOUBLE))
1953 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1957 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_FLOAT))
1958 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1962 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_INT))
1963 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1967 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_SHORT))
1968 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1972 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo,ARRAYTYPE_LONG))
1973 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1978 /* we just check the basic input types and that the */
1979 /* destination is an array of references. Assignability to */
1980 /* the actual array must be checked at runtime, each time the */
1981 /* instruction is performed. (See builtin_canstore.) */
1982 TYPECHECK_ADR(state->iptr->sx.s23.s3.var);
1983 TYPECHECK_INT(state->iptr->sx.s23.s2.var);
1984 TYPECHECK_ADR(state->iptr->s1.var);
1985 if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(state->iptr->s1.var->typeinfo))
1986 TYPECHECK_VERIFYERROR_bool("illegal instruction: AASTORE to non-reference array");
1990 case ICMD_IASTORECONST:
1991 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo, ARRAYTYPE_INT))
1992 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
1996 case ICMD_LASTORECONST:
1997 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo, ARRAYTYPE_LONG))
1998 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
2002 case ICMD_BASTORECONST:
2003 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo, ARRAYTYPE_BOOLEAN)
2004 && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo, ARRAYTYPE_BYTE))
2005 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
2009 case ICMD_CASTORECONST:
2010 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo, ARRAYTYPE_CHAR))
2011 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
2015 case ICMD_SASTORECONST:
2016 if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(state->iptr->s1.var->typeinfo, ARRAYTYPE_SHORT))
2017 TYPECHECK_VERIFYERROR_bool("Array type mismatch");
2021 /****************************************/
2022 /* ADDRESS CONSTANTS */
2025 if (state->iptr->flags.bits & INS_FLAG_CLASS) {
2026 /* a java.lang.Class reference */
2027 TYPEINFO_INIT_JAVA_LANG_CLASS(dst->typeinfo,state->iptr->sx.val.c);
2030 if (state->iptr->sx.val.anyptr == NULL)
2031 TYPEINFO_INIT_NULLTYPE(dst->typeinfo);
2033 /* string constant (or constant for builtin function) */
2034 typeinfo_init_classinfo(&(dst->typeinfo),class_java_lang_String);
2039 /****************************************/
2040 /* CHECKCAST AND INSTANCEOF */
2042 case ICMD_CHECKCAST:
2043 TYPECHECK_ADR(state->iptr->s1.var);
2044 /* returnAddress is not allowed */
2045 if (!TYPEINFO_IS_REFERENCE(state->iptr->s1.var->typeinfo))
2046 TYPECHECK_VERIFYERROR_bool("Illegal instruction: CHECKCAST on non-reference");
2048 if (!typeinfo_init_class(&(dst->typeinfo),state->iptr->sx.s23.s3.c))
2053 case ICMD_INSTANCEOF:
2054 TYPECHECK_ADR(state->iptr->s1.var);
2055 /* returnAddress is not allowed */
2056 if (!TYPEINFO_IS_REFERENCE(state->iptr->s1.var->typeinfo))
2057 TYPECHECK_VERIFYERROR_bool("Illegal instruction: INSTANCEOF on non-reference");
2060 /****************************************/
2061 /* BRANCH INSTRUCTIONS */
2063 case ICMD_INLINE_GOTO:
2064 COPYTYPE(state->iptr->s1.var,dst);
2067 superblockend = true;
2070 case ICMD_IFNONNULL:
2077 case ICMD_IF_ICMPEQ:
2078 case ICMD_IF_ICMPNE:
2079 case ICMD_IF_ICMPLT:
2080 case ICMD_IF_ICMPGE:
2081 case ICMD_IF_ICMPGT:
2082 case ICMD_IF_ICMPLE:
2083 case ICMD_IF_ACMPEQ:
2084 case ICMD_IF_ACMPNE:
2093 case ICMD_IF_LCMPEQ:
2094 case ICMD_IF_LCMPNE:
2095 case ICMD_IF_LCMPLT:
2096 case ICMD_IF_LCMPGE:
2097 case ICMD_IF_LCMPGT:
2098 case ICMD_IF_LCMPLE:
2100 case ICMD_IF_FCMPEQ:
2101 case ICMD_IF_FCMPNE:
2103 case ICMD_IF_FCMPL_LT:
2104 case ICMD_IF_FCMPL_GE:
2105 case ICMD_IF_FCMPL_GT:
2106 case ICMD_IF_FCMPL_LE:
2108 case ICMD_IF_FCMPG_LT:
2109 case ICMD_IF_FCMPG_GE:
2110 case ICMD_IF_FCMPG_GT:
2111 case ICMD_IF_FCMPG_LE:
2113 case ICMD_IF_DCMPEQ:
2114 case ICMD_IF_DCMPNE:
2116 case ICMD_IF_DCMPL_LT:
2117 case ICMD_IF_DCMPL_GE:
2118 case ICMD_IF_DCMPL_GT:
2119 case ICMD_IF_DCMPL_LE:
2121 case ICMD_IF_DCMPG_LT:
2122 case ICMD_IF_DCMPG_GE:
2123 case ICMD_IF_DCMPG_GT:
2124 case ICMD_IF_DCMPG_LE:
2125 TYPECHECK_COUNT(stat_ins_branch);
2127 /* propagate stack and variables to the target block */
2128 if (!typestate_reach(state,state->iptr->dst.block,
2129 state->bptr->outstack,state->localset))
2133 /****************************************/
2136 case ICMD_TABLESWITCH:
2137 TYPECHECK_COUNT(stat_ins_switch);
2139 table = iptr->dst.table;
2140 i = iptr->sx.s23.s3.tablehigh
2141 - iptr->sx.s23.s2.tablelow + 1 + 1; /* plus default */
2144 tbptr = (table++)->block;
2145 LOG2("target %d is block %04d",i,tbptr->nr);
2146 if (!typestate_reach(state,tbptr,state->bptr->outstack,
2152 superblockend = true;
2155 case ICMD_LOOKUPSWITCH:
2156 TYPECHECK_COUNT(stat_ins_switch);
2158 lookup = iptr->dst.lookup;
2159 i = iptr->sx.s23.s2.lookupcount;
2161 if (!typestate_reach(state,iptr->sx.s23.s3.lookupdefault.block,
2162 state->bptr->outstack,state->localset))
2166 tbptr = (lookup++)->target.block;
2167 LOG2("target %d is block %04d",i,tbptr->nr);
2168 if (!typestate_reach(state,tbptr,state->bptr->outstack,state->localset))
2173 superblockend = true;
2176 /****************************************/
2177 /* ADDRESS RETURNS AND THROW */
2180 TYPECHECK_COUNT(stat_ins_athrow);
2181 r = typeinfo_is_assignable_to_class(&state->iptr->s1.var->typeinfo,
2182 CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
2183 if (r == typecheck_FALSE)
2184 TYPECHECK_VERIFYERROR_bool("illegal instruction: ATHROW on non-Throwable");
2185 if (r == typecheck_FAIL)
2187 if (r == typecheck_MAYBE) {
2188 /* the check has to be postponed. we need a patcher */
2189 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
2190 iptr->sx.s23.s2.uc = create_unresolved_class(
2192 /* XXX make this more efficient, use class_java_lang_Throwable
2194 class_get_classref(state->m->class,utf_java_lang_Throwable),
2195 &state->iptr->s1.var->typeinfo);
2196 iptr->flags.bits |= INS_FLAG_UNRESOLVED;
2198 superblockend = true;
2203 TYPECHECK_COUNT(stat_ins_areturn);
2204 if (!TYPEINFO_IS_REFERENCE(state->iptr->s1.var->typeinfo))
2205 TYPECHECK_VERIFYERROR_bool("illegal instruction: ARETURN on non-reference");
2207 if (state->returntype.type != TYPE_ADR
2208 || (r = typeinfo_is_assignable(&state->iptr->s1.var->typeinfo,&(state->returntype.info)))
2210 TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2211 if (r == typecheck_FAIL)
2213 if (r == typecheck_MAYBE) {
2214 /* the check has to be postponed, we need a patcher */
2215 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
2216 iptr->sx.s23.s2.uc = create_unresolved_class(
2218 state->m->parseddesc->returntype.classref,
2219 &state->iptr->s1.var->typeinfo);
2220 iptr->flags.bits |= INS_FLAG_UNRESOLVED;
2224 /****************************************/
2225 /* PRIMITIVE RETURNS */
2228 if (state->returntype.type != TYPE_INT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2232 if (state->returntype.type != TYPE_LNG) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2236 if (state->returntype.type != TYPE_FLT) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2240 if (state->returntype.type != TYPE_DBL) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2244 if (state->returntype.type != TYPE_VOID) TYPECHECK_VERIFYERROR_bool("Return type mismatch");
2246 TYPECHECK_COUNT(stat_ins_primitive_return);
2248 if (state->initmethod && state->m->class != class_java_lang_Object) {
2249 /* Check if the 'this' instance has been initialized. */
2250 LOG("Checking <init> marker");
2251 if (!typevectorset_checktype(state->localset,state->numlocals-1,TYPE_INT))
2252 TYPECHECK_VERIFYERROR_bool("<init> method does not initialize 'this'");
2255 superblockend = true;
2259 /****************************************/
2260 /* SUBROUTINE INSTRUCTIONS */
2264 state->jsrencountered = true;
2266 tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
2267 if (state->bptr + 1 == (state->basicblocks + state->basicblockcount + 1))
2268 TYPECHECK_VERIFYERROR_bool("Illegal instruction: JSR at end of bytecode");
2269 typestack_put_retaddr(dst,state->bptr+1,state->localset);
2270 if (!typestate_reach(state,tbptr,dst,state->localset))
2273 superblockend = true;
2277 /* check returnAddress variable */
2278 if (!typevectorset_checkretaddr(state->localset,state->iptr->s1.localindex))
2279 TYPECHECK_VERIFYERROR_bool("illegal instruction: RET using non-returnAddress variable");
2281 if (!typestate_ret(state,state->iptr->s1.localindex))
2284 superblockend = true;
2287 /****************************************/
2290 case ICMD_INVOKEVIRTUAL:
2291 case ICMD_INVOKESPECIAL:
2292 case ICMD_INVOKESTATIC:
2293 case ICMD_INVOKEINTERFACE:
2294 TYPECHECK_COUNT(stat_ins_invoke);
2295 if (!verify_invocation(state))
2297 TYPECHECK_COUNTIF(!state->iptr[0].val.a,stat_ins_invoke_unresolved);
2301 /****************************************/
2302 /* MULTIANEWARRAY */
2304 case ICMD_MULTIANEWARRAY:
2305 if (!verify_multianewarray(state))
2310 /****************************************/
2314 TYPECHECK_COUNT(stat_ins_builtin);
2315 if (!verify_builtin(state))
2320 /****************************************/
2321 /* SIMPLE EXCEPTION THROWING TESTS */
2323 case ICMD_CHECKNULL:
2324 /* CHECKNULL just requires that the stack top
2325 * is an address. This is checked in stack.c */
2329 /****************************************/
2330 /* INSTRUCTIONS WHICH SHOULD HAVE BEEN */
2331 /* REPLACED BY OTHER OPCODES */
2333 #ifdef TYPECHECK_DEBUG
2336 case ICMD_ANEWARRAY:
2337 case ICMD_MONITORENTER:
2338 case ICMD_MONITOREXIT:
2339 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2340 LOG("Should have been converted to builtin function call.");
2341 TYPECHECK_ASSERT(false);
2345 /****************************************/
2346 /* UNCHECKED OPERATIONS */
2348 /*********************************************
2349 * Instructions below...
2350 * *) don't operate on local variables,
2351 * *) don't operate on references,
2352 * *) don't operate on returnAddresses,
2353 * *) don't affect control flow (except
2354 * by throwing exceptions).
2356 * (These instructions are typechecked in
2358 ********************************************/
2360 /* Instructions which may throw a runtime exception: */
2370 /* Instructions which never throw a runtime exception: */
2371 #if defined(TYPECHECK_DEBUG) || defined(TYPECHECK_STATISTICS)
2405 case ICMD_IADDCONST:
2406 case ICMD_ISUBCONST:
2407 case ICMD_IMULCONST:
2408 case ICMD_IANDCONST:
2410 case ICMD_IXORCONST:
2411 case ICMD_ISHLCONST:
2412 case ICMD_ISHRCONST:
2413 case ICMD_IUSHRCONST:
2415 case ICMD_LADDCONST:
2416 case ICMD_LSUBCONST:
2417 case ICMD_LMULCONST:
2418 case ICMD_LANDCONST:
2420 case ICMD_LXORCONST:
2421 case ICMD_LSHLCONST:
2422 case ICMD_LSHRCONST:
2423 case ICMD_LUSHRCONST:
2440 case ICMD_INT2SHORT:
2443 case ICMD_LCMPCONST:
2462 case ICMD_INLINE_START:
2463 case ICMD_INLINE_END:
2465 /* XXX What shall we do with the following ?*/
2466 case ICMD_AASTORECONST:
2467 TYPECHECK_COUNT(stat_ins_unchecked);
2470 /****************************************/
2473 LOG2("ICMD %d at %d\n", state->iptr->opc, (int)(state->iptr-state->bptr->iinstr));
2474 TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
2478 /* reach exception handlers for this instruction */
2480 TYPECHECK_COUNT(stat_ins_maythrow);
2481 TYPECHECK_MARK(state->stat_maythrow);
2482 LOG("reaching exception handlers");
2484 while (state->handlers[i]) {
2485 TYPECHECK_COUNT(stat_handlers_reached);
2486 if (state->handlers[i]->catchtype.any)
2487 state->excstack.typeinfo.typeclass = state->handlers[i]->catchtype;
2489 state->excstack.typeinfo.typeclass.cls = class_java_lang_Throwable;
2490 if (!typestate_reach(state,
2491 state->handlers[i]->handler,
2492 &(state->excstack),state->localset))
2498 LOG("next instruction");
2500 } /* while instructions */
2502 LOG("instructions done");
2503 LOGSTR("RESULT=> ");
2504 DOLOG(typestate_print(typecheck_logfile,state->bptr->outstack,state->localset,state->numlocals));
2507 /* propagate stack and variables to the following block */
2508 if (!superblockend) {
2509 LOG("reaching following block");
2510 tbptr = state->bptr + 1;
2511 while (tbptr->flags == BBDELETED) {
2513 #ifdef TYPECHECK_DEBUG
2514 /* this must be checked in parse.c */
2515 if ((tbptr->nr) >= state->basicblockcount)
2516 TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
2519 if (!typestate_reach(state,tbptr,state->bptr->outstack,state->localset))
2523 /* We may have to restore the types of the instack slots. They
2524 * have been saved if an <init> call inside the block has
2525 * modified the instack types. (see INVOKESPECIAL) */
2527 if (state->savedstack)
2528 typestate_restore_instack(state);
2533 /* verify_init_locals **********************************************************
2535 Initialize the local variables in the verifier state.
2538 state............the current state of the verifier
2541 true.............success,
2542 false............an exception has been thrown.
2544 *******************************************************************************/
2547 verify_init_locals(verifier_state *state)
2553 /* initialize the variable types of the first block */
2554 /* to the types of the arguments */
2556 lset = MGET_TYPEVECTOR(state->localbuf,0,state->numlocals);
2560 i = state->validlocals;
2562 /* allocate parameter descriptors if necessary */
2564 if (!state->m->parseddesc->params)
2565 if (!descriptor_params_from_paramtypes(state->m->parseddesc,state->m->flags))
2568 /* if this is an instance method initialize the "this" ref type */
2570 if (!(state->m->flags & ACC_STATIC)) {
2572 TYPECHECK_VERIFYERROR_bool("Not enough local variables for method arguments");
2573 td->type = TYPE_ADR;
2574 if (state->initmethod)
2575 TYPEINFO_INIT_NEWOBJECT(td->info,NULL);
2577 typeinfo_init_classinfo(&(td->info), state->m->class);
2582 LOG("'this' argument set.\n");
2584 /* the rest of the arguments and the return type */
2586 i = typedescriptors_init_from_methoddesc(td, state->m->parseddesc,
2588 true, /* two word types use two slots */
2589 (td - lset->td), /* skip 'this' pointer */
2590 &state->returntype);
2595 /* variables not used for arguments are initialized to TYPE_VOID */
2597 i = state->numlocals - (td - lset->td);
2599 td->type = TYPE_VOID;
2603 LOG("Arguments set.\n");
2607 /* typecheck_init_flags ********************************************************
2609 Initialize the basic block flags for the following CFG traversal.
2612 state............the current state of the verifier
2614 *******************************************************************************/
2617 typecheck_init_flags(verifier_state *state)
2622 /* set all BBFINISHED blocks to BBTYPECHECK_UNDEF. */
2624 i = state->basicblockcount;
2625 block = state->basicblocks;
2629 #ifdef TYPECHECK_DEBUG
2630 /* check for invalid flags */
2631 if (block->flags != BBFINISHED && block->flags != BBDELETED && block->flags != BBUNDEF)
2633 /*show_icmd_method(state->m,state->cd,state->rd);*/
2634 LOGSTR1("block flags: %d\n",block->flags); LOGFLUSH;
2635 TYPECHECK_ASSERT(false);
2639 if (block->flags >= BBFINISHED) {
2640 block->flags = BBTYPECHECK_UNDEF;
2645 /* the first block is always reached */
2647 if (state->basicblockcount && state->basicblocks[0].flags == BBTYPECHECK_UNDEF)
2648 state->basicblocks[0].flags = BBTYPECHECK_REACHED;
2651 /* typecheck_reset_flags *******************************************************
2653 Reset the flags of basic blocks we have not reached.
2656 state............the current state of the verifier
2658 *******************************************************************************/
2661 typecheck_reset_flags(verifier_state *state)
2665 /* check for invalid flags at exit */
2667 #ifdef TYPECHECK_DEBUG
2668 for (i=0; i<state->basicblockcount; ++i) {
2669 if (state->basicblocks[i].flags != BBDELETED
2670 && state->basicblocks[i].flags != BBUNDEF
2671 && state->basicblocks[i].flags != BBFINISHED
2672 && state->basicblocks[i].flags != BBTYPECHECK_UNDEF) /* typecheck may never reach
2673 * some exception handlers,
2676 LOG2("block L%03d has invalid flags after typecheck: %d",
2677 state->basicblocks[i].nr,state->basicblocks[i].flags);
2678 TYPECHECK_ASSERT(false);
2683 /* Reset blocks we never reached */
2685 for (i=0; i<state->basicblockcount; ++i) {
2686 if (state->basicblocks[i].flags == BBTYPECHECK_UNDEF)
2687 state->basicblocks[i].flags = BBFINISHED;
2691 /****************************************************************************/
2693 /* This is the main function of the bytecode verifier. It is called */
2694 /* directly after analyse_stack. */
2697 /* meth.............the method to verify */
2698 /* cdata............codegendata for the method */
2699 /* rdata............registerdata for the method */
2702 /* true.............successful verification */
2703 /* false............an exception has been thrown */
2705 /****************************************************************************/
2707 #define MAXPARAMS 255
2709 bool typecheck(jitdata *jd)
2714 verifier_state state; /* current state of the verifier */
2715 int i; /* temporary counter */
2717 /* collect statistics */
2719 #ifdef TYPECHECK_STATISTICS
2720 int count_iterations = 0;
2721 TYPECHECK_COUNT(stat_typechecked);
2722 TYPECHECK_COUNT_FREQ(stat_locals,cdata->maxlocals,STAT_LOCALS);
2723 TYPECHECK_COUNT_FREQ(stat_blocks,cdata->method->basicblockcount/10,STAT_BLOCKS);
2724 TYPECHECK_COUNTIF(cdata->method->exceptiontablelength != 0,stat_methods_with_handlers);
2725 state.stat_maythrow = false;
2728 /* get required compiler data */
2734 /* some logging on entry */
2736 DOLOG(typecheck_logfile = stdout);
2737 LOGSTR("\n==============================================================================\n");
2738 /*DOLOG( show_icmd_method(cdata->method,cdata,rdata));*/
2739 LOGSTR("\n==============================================================================\n");
2740 LOGMETHOD("Entering typecheck: ",cdata->method);
2742 /* initialize the verifier state */
2744 state.savedstackbuf = NULL;
2745 state.savedstack = NULL;
2746 state.jsrencountered = false;
2751 state.basicblockcount = jd->new_basicblockcount;
2752 state.basicblocks = jd->new_basicblocks;
2754 /* check if this method is an instance initializer method */
2756 state.initmethod = (state.m->name == utf_init);
2758 /* initialize the basic block flags for the following CFG traversal */
2760 typecheck_init_flags(&state);
2762 /* number of local variables */
2764 /* In <init> methods we use an extra local variable to indicate whether */
2765 /* the 'this' reference has been initialized. */
2766 /* TYPE_VOID...means 'this' has not been initialized, */
2767 /* TYPE_INT....means 'this' has been initialized. */
2768 state.numlocals = state.cd->maxlocals;
2769 state.validlocals = state.numlocals;
2770 if (state.initmethod) state.numlocals++;
2772 /* allocate the buffers for local variables */
2774 state.localbuf = DMNEW_TYPEVECTOR(state.basicblockcount+1, state.numlocals);
2775 state.localset = MGET_TYPEVECTOR(state.localbuf,state.basicblockcount,state.numlocals);
2777 LOG("Variable buffer allocated.\n");
2779 /* allocate the buffer of active exception handlers */
2781 state.handlers = DMNEW(exceptiontable*, state.cd->exceptiontablelength + 1);
2783 /* initialized local variables of first block */
2785 if (!verify_init_locals(&state))
2788 /* initialize the input stack of exception handlers */
2790 state.excstack.prev = NULL;
2791 state.excstack.type = TYPE_ADR;
2792 typeinfo_init_classinfo(&(state.excstack.typeinfo),
2793 class_java_lang_Throwable); /* changed later */
2795 LOG("Exception handler stacks set.\n");
2797 /* loop while there are still blocks to be checked */
2799 TYPECHECK_COUNT(count_iterations);
2801 state.repeat = false;
2803 i = state.basicblockcount;
2804 state.bptr = state.basicblocks;
2807 LOGSTR1("---- BLOCK %04d, ",state.bptr->nr);
2808 LOGSTR1("blockflags: %d\n",state.bptr->flags);
2811 /* verify reached block */
2812 if (state.bptr->flags == BBTYPECHECK_REACHED) {
2813 if (!verify_basic_block(&state))
2817 } /* while blocks */
2819 LOGIF(state.repeat,"state.repeat == true");
2820 } while (state.repeat);
2824 #ifdef TYPECHECK_STATISTICS
2825 LOG1("Typechecker did %4d iterations",count_iterations);
2826 TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
2827 TYPECHECK_COUNTIF(state.jsrencountered,stat_typechecked_jsr);
2828 TYPECHECK_COUNTIF(state.stat_maythrow,stat_methods_maythrow);
2831 /* reset the flags of blocks we haven't reached */
2833 typecheck_reset_flags(&state);
2835 /* everything's ok */
2837 LOGimp("exiting typecheck");
2841 #endif /* ENABLE_VERIFIER */
2844 * These are local overrides for various environment variables in Emacs.
2845 * Please do not remove this and leave it at the end of the file, where
2846 * Emacs will automagically detect them.
2847 * ---------------------------------------------------------------------
2850 * indent-tabs-mode: t
2854 * vim:noexpandtab:sw=4:ts=4: