* src/vm/jit/parse.cpp,
[cacao.git] / src / vm / jit / verify / typecheck.c
1 /* src/vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
2
3    Copyright (C) 1996-2005, 2006, 2007, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25 /*
26
27 What's the purpose of the `typechecker`?
28 ----------------------------------------
29
30 The typechecker analyses (the intermediate repr. of) the bytecode of
31 each method and ensures that for each instruction the values on the
32 stack and in local variables are of the correct type whenever the
33 instruction is executed.
34
35 type checking is a mandatory part of bytecode verification.
36
37
38 How does the typechecker work?
39 ------------------------------
40
41 The JVM stack and the local variables are not statically typed, so the
42 typechecker has to *infer* the static types of stack slots and local
43 variables at each point of the method. The JVM spec imposes a lot of
44 restrictions on the bytecode in order to guarantee that this is always
45 possible.
46
47 Basically the typechecker solves the data flow equations of the method.
48 This is done in the usual way for a forward data flow analysis: Starting
49 from the entry point of the method the typechecker follows the CFG and
50 records the type of each stack slot and local variable at each point[1].
51 When two or more control flow paths merge at a point, the union of the
52 types for each slot/variable is taken. The algorithm continues to follow
53 all possible paths[2] until the recorded types do not change anymore (ie.
54 the equations have been solved).
55
56 If the solution has been reached and the resulting types are valid for
57 all instructions, then type checking terminates with success, otherwise
58 an exception is thrown.
59
60
61 Why is this code so damn complicated?
62 -------------------------------------
63
64 Short answer: The devil's in the details.
65
66 While the basic operation of the typechecker is no big deal, there are
67 many properties of Java bytecode which make type checking hard. Some of
68 them are not even addressed in the JVM spec. Some problems and their
69 solutions:
70
71 *) Finding a good representation of the union of two reference types is
72 difficult because of multiple inheritance of interfaces. 
73
74         Solution: The typeinfo system can represent such "merged" types by a
75         list of proper subclasses of a class. Example:
76
77                 typeclass=java.lang.Object merged={ InterfaceA, InterfaceB }
78         
79         represents the result of merging two interface types "InterfaceA"
80         and "InterfaceB".
81
82 *) When the code of a method is verified, there may still be unresolved
83 references to classes/methods/fields in the code, which we may not force
84 to be resolved eagerly. (A similar problem arises because of the special
85 checks for protected members.)
86
87         Solution: The typeinfo system knows how to deal with unresolved
88         class references. Whenever a check has to be performed for an
89         unresolved type, the type is annotated with constraints representing
90         the check. Later, when the type is resolved, the constraints are
91         checked. (See the constrain_unresolved_... and the resolve_...
92         methods.)[3]
93
94 *) Checks for uninitialized object instances are hard because after the
95 invocation of <init> on an uninitialized object *all* slots/variables
96 referring to this object (and exactly those slots/variables) must be
97 marked as initialized.
98
99         Solution: The JVM spec describes a solution, which has been
100         implemented in this typechecker.
101
102 Note that some checks mentioned in the JVM spec are unnecessary[4] and
103 not performed by either the reference implementation, or this implementation.
104
105
106 --- Footnotes
107
108 [1] Actually only the types of slots/variables at the start of each
109 basic block are remembered. Within a basic block the algorithm only keeps
110 the types of the slots/variables for the "current" instruction which is
111 being analysed. 
112
113 [2] Actually the algorithm iterates through the basic block list until
114 there are no more changes. Theoretically it would be wise to sort the
115 basic blocks topologically beforehand, but the number of average/max
116 iterations observed is so low, that this was not deemed necessary.
117
118 [3] This is similar to a method proposed by: Alessandro Coglio et al., A
119 Formal Specification of Java Class Loading, Technical Report, Kestrel
120 Institute April 2000, revised July 2000 
121 http://www.kestrel.edu/home/people/coglio/loading.pdf
122 An important difference is that Coglio's subtype constraints are checked
123 after loading, while our constraints are checked when the field/method
124 is accessed for the first time, so we can guarantee lexically correct
125 error reporting.
126
127 [4] Alessandro Coglio
128     Improving the official specification of Java bytecode verification
129     Proceedings of the 3rd ECOOP Workshop on Formal Techniques for Java Programs
130     June 2001
131     citeseer.ist.psu.edu/article/coglio03improving.html
132 */
133
134
135 #include "config.h"
136
137 #include <assert.h>
138 #include <string.h>
139
140 #include "vm/types.h"
141
142 #ifdef ENABLE_VERIFIER
143
144 #include "mm/memory.h"
145
146 #include "native/native.hpp"
147
148 #include "toolbox/logging.h"
149
150 #include "vm/access.h"
151 #include "vm/array.hpp"
152 #include "vm/jit/builtin.hpp"
153 #include "vm/exceptions.hpp"
154 #include "vm/global.h"
155 #include "vm/globals.hpp"
156 #include "vm/loader.hpp"
157 #include "vm/options.h"
158 #include "vm/primitive.hpp"
159 #include "vm/resolve.hpp"
160
161 #include "vm/jit/jit.hpp"
162 #include "vm/jit/parse.hpp"
163 #include "vm/jit/show.hpp"
164
165 #include <typecheck-common.h>
166
167
168 /****************************************************************************/
169 /* MACROS FOR VARIABLE TYPE CHECKING                                        */
170 /****************************************************************************/
171
172 #define TYPECHECK_CHECK_TYPE(i,tp,msg)                               \
173     do {                                                             \
174         if (VAR(i)->type != (tp)) {                                  \
175             exceptions_throw_verifyerror(state->m, (msg));           \
176             return false;                                            \
177         }                                                            \
178     } while (0)
179
180 #define TYPECHECK_INT(i)                                             \
181     TYPECHECK_CHECK_TYPE(i,TYPE_INT,"Expected to find integer value")
182 #define TYPECHECK_LNG(i)                                             \
183     TYPECHECK_CHECK_TYPE(i,TYPE_LNG,"Expected to find long value")
184 #define TYPECHECK_FLT(i)                                             \
185     TYPECHECK_CHECK_TYPE(i,TYPE_FLT,"Expected to find float value")
186 #define TYPECHECK_DBL(i)                                             \
187     TYPECHECK_CHECK_TYPE(i,TYPE_DBL,"Expected to find double value")
188 #define TYPECHECK_ADR(i)                                             \
189     TYPECHECK_CHECK_TYPE(i,TYPE_ADR,"Expected to find object value")
190
191 #define TYPECHECK_INT_OP(o)  TYPECHECK_INT((o).varindex)
192 #define TYPECHECK_LNG_OP(o)  TYPECHECK_LNG((o).varindex)
193 #define TYPECHECK_FLT_OP(o)  TYPECHECK_FLT((o).varindex)
194 #define TYPECHECK_DBL_OP(o)  TYPECHECK_DBL((o).varindex)
195 #define TYPECHECK_ADR_OP(o)  TYPECHECK_ADR((o).varindex)
196
197
198 /* typestate_save_invars *******************************************************
199  
200    Save the invars of the current basic block in the space reserved by
201    parse.
202
203    This function must be called before an instruction modifies a variable
204    that is an invar of the current block. In such cases the invars of the
205    block must be saved, and restored at the end of the analysis of this
206    basic block, so that the invars again reflect the *input* to this basic
207    block (and do not randomly contain types that appear within the block).
208
209    IN:
210        state............current state of the verifier
211
212 *******************************************************************************/
213
214 static void
215 typestate_save_invars(verifier_state *state)
216 {
217         s4 i, index;
218         s4 *pindex;
219         
220         LOG("saving invars");
221
222         if (!state->savedindices) {
223                 LOG("allocating savedindices buffer");
224                 pindex = DMNEW(s4, state->m->maxstack);
225                 state->savedindices = pindex;
226                 index = state->numlocals + VERIFIER_EXTRA_VARS;
227                 for (i=0; i<state->m->maxstack; ++i)
228                         *pindex++ = index++;
229         }
230
231         /* save types */
232
233         typecheck_copy_types(state, state->bptr->invars, state->savedindices, 
234                         state->bptr->indepth);
235
236         /* set the invars of the block to the saved variables */
237         /* and remember the original invars                   */
238
239         state->savedinvars = state->bptr->invars;
240         state->bptr->invars = state->savedindices;
241 }
242
243
244 /* typestate_restore_invars  ***************************************************
245  
246    Restore the invars of the current basic block that have been previously
247    saved by `typestate_save_invars`.
248
249    IN:
250        state............current state of the verifier
251
252 *******************************************************************************/
253
254 static void
255 typestate_restore_invars(verifier_state *state)
256 {
257         TYPECHECK_COUNT(stat_savedstack);
258         LOG("restoring saved invars");
259
260         /* restore the invars pointer */
261
262         state->bptr->invars = state->savedinvars;
263
264         /* copy the types back */
265
266         typecheck_copy_types(state, state->savedindices, state->bptr->invars,
267                         state->bptr->indepth);
268
269         /* mark that there are no saved invars currently */
270
271         state->savedinvars = NULL;
272 }
273
274
275 /* handle_fieldaccess **********************************************************
276  
277    Verify an ICMD_{GET,PUT}{STATIC,FIELD}(CONST)?
278   
279    IN:
280        state............the current state of the verifier
281
282    RETURN VALUE:
283        true.............successful verification,
284            false............an exception has been thrown.
285
286 *******************************************************************************/
287
288 static bool
289 handle_fieldaccess(verifier_state *state,
290                                    varinfo *instance,
291                                    varinfo *value)
292 {
293         jitdata *jd;
294
295         jd = state->jd;
296
297 #define TYPECHECK_VARIABLESBASED
298 #define EXCEPTION  do { return false; } while (0)
299 #define VERIFY_ERROR(msg)  TYPECHECK_VERIFYERROR_bool(msg)
300 #include <typecheck-fields.inc>
301 #undef  EXCEPTION
302 #undef  VERIFY_ERROR
303 #undef  TYPECHECK_VARIABLESBASED
304
305         return true;
306 }
307
308
309 /* handle_invocation ***********************************************************
310  
311    Verify an ICMD_INVOKE* instruction.
312   
313    IN:
314        state............the current state of the verifier
315
316    RETURN VALUE:
317        true.............successful verification,
318            false............an exception has been thrown.
319
320 *******************************************************************************/
321
322 static bool
323 handle_invocation(verifier_state *state)
324 {
325         jitdata *jd;
326     varinfo *dv;               /* output variable of current instruction */
327
328         jd = state->jd;
329         dv = VAROP(state->iptr->dst);
330
331 #define TYPECHECK_VARIABLESBASED
332 #define OP1   VAR(state->iptr->sx.s23.s2.args[0])
333 #include <typecheck-invoke.inc>
334 #undef  OP1
335 #undef  TYPECHECK_VARIABLESBASED
336
337         return true;
338 }
339
340
341 /* handle_builtin **************************************************************
342  
343    Verify the call of a builtin method.
344   
345    IN:
346        state............the current state of the verifier
347
348    RETURN VALUE:
349        true.............successful verification,
350            false............an exception has been thrown.
351
352 *******************************************************************************/
353
354 static bool
355 handle_builtin(verifier_state *state)
356 {
357         jitdata *jd;
358     varinfo *dv;               /* output variable of current instruction */
359
360         jd = state->jd;
361         dv = VAROP(state->iptr->dst);
362
363 #define TYPECHECK_VARIABLESBASED
364 #define OP1   state->iptr->sx.s23.s2.args[0]
365 #include <typecheck-builtins.inc>
366 #undef  OP1
367 #undef  TYPECHECK_VARIABLESBASED
368
369         return true;
370 }
371
372 /* handle_multianewarray *******************************************************
373  
374    Verify a MULTIANEWARRAY instruction.
375   
376    IN:
377        state............the current state of the verifier
378
379    RETURN VALUE:
380        true.............successful verification,
381            false............an exception has been thrown.
382
383 *******************************************************************************/
384
385 static bool
386 handle_multianewarray(verifier_state *state)
387 {
388         jitdata *jd;
389     varinfo *dv;               /* output variable of current instruction */
390
391         jd = state->jd;
392         dv = VAROP(state->iptr->dst);
393
394 #define TYPECHECK_VARIABLESBASED
395 #define VERIFY_ERROR(msg)  TYPECHECK_VERIFYERROR_bool(msg)
396 #include <typecheck-multianewarray.inc>
397 #undef VERIFY_ERROR
398 #undef  TYPECHECK_VARIABLESBASED
399
400         return true;
401 }
402
403 /* typecheck_invalidate_locals *************************************************
404  
405    Invalidate locals that are overwritten by writing to the given local.
406   
407    IN:
408        state............the current state of the verifier
409            index............the index of the local that is written
410            twoword..........true, if a two-word type is written
411
412 *******************************************************************************/
413
414 static void typecheck_invalidate_locals(verifier_state *state, s4 index, bool twoword)
415 {
416         s4 javaindex;
417         s4 t;
418         s4 varindex;
419         jitdata *jd = state->jd;
420         s4 *localmap = jd->local_map;
421         varinfo *vars = jd->var;
422
423         javaindex = jd->reverselocalmap[index];
424
425         /* invalidate locals of two-word type at index javaindex-1 */
426
427         if (javaindex > 0) {
428                 localmap += 5 * (javaindex-1);
429                 for (t=0; t<5; ++t) {
430                         varindex = *localmap++;
431                         if (varindex >= 0 && IS_2_WORD_TYPE(vars[varindex].type)) {
432                                 LOG1("invalidate local %d", varindex);
433                                 vars[varindex].type = TYPE_VOID;
434                         }
435                 }
436         }
437         else {
438                 localmap += 5 * javaindex;
439         }
440
441         /* invalidate locals at index javaindex */
442
443         for (t=0; t<5; ++t) {
444                 varindex = *localmap++;
445                 if (varindex >= 0) {
446                         LOG1("invalidate local %d", varindex);
447                         vars[varindex].type = TYPE_VOID;
448                 }
449         }
450
451         /* if a two-word type is written, invalidate locals at index javaindex+1 */
452
453         if (twoword) {
454                 for (t=0; t<5; ++t) {
455                         varindex = *localmap++;
456                         if (varindex >= 0) {
457                                 LOG1("invalidate local %d", varindex);
458                                 vars[varindex].type = TYPE_VOID;
459                         }
460                 }
461         }
462 }
463
464
465 /* macros used by the generated code ******************************************/
466
467 #define EXCEPTION          do { return false; } while (0)
468 #define VERIFY_ERROR(msg)  TYPECHECK_VERIFYERROR_bool(msg)
469
470 #define CHECK_LOCAL_TYPE(index, t)                                   \
471     do {                                                             \
472         if (!typevector_checktype(jd->var, (index), (t)))            \
473              VERIFY_ERROR("Local variable type mismatch");           \
474     } while (0)
475
476 #define STORE_LOCAL(t, index)                                        \
477     do {                                                             \
478          s4 temp_t = (t);                                            \
479          typecheck_invalidate_locals(state, (index), false);         \
480          typevector_store(jd->var, (index), (temp_t), NULL);         \
481     } while (0)
482
483 #define STORE_LOCAL_2_WORD(t, index)                                 \
484     do {                                                             \
485          s4 temp_t = (t);                                            \
486          typecheck_invalidate_locals(state, (index), true);          \
487          typevector_store(jd->var, (index), (temp_t), NULL);         \
488     } while (0)
489
490 #define REACH_BLOCK(target)                                          \
491     do {                                                             \
492         if (!typestate_reach(state, (target),                        \
493                              state->bptr->outvars, jd->var,          \
494                              state->bptr->outdepth))                 \
495                 return false;                                        \
496     } while (0)
497
498 #define REACH(target)   REACH_BLOCK((target).block)
499
500
501 /* handle_basic_block **********************************************************
502  
503    Perform bytecode verification of a basic block.
504   
505    IN:
506        state............the current state of the verifier
507
508    RETURN VALUE:
509        true.............successful verification,
510            false............an exception has been thrown.
511
512 *******************************************************************************/
513
514 static bool
515 handle_basic_block(verifier_state *state)
516 {
517     int opcode;                                      /* current opcode */
518     int len;                        /* for counting instructions, etc. */
519     bool superblockend;        /* true if no fallthrough to next block */
520         instruction *iptr;                      /* the current instruction */
521     basicblock *tbptr;                   /* temporary for target block */
522     bool maythrow;               /* true if this instruction may throw */
523         s4 i;
524         typecheck_result r;
525         branch_target_t *table;
526         lookup_target_t *lookup;
527         jitdata *jd = state->jd;
528         exception_entry *ex;
529         varinfo constvalue;                               /* for PUT*CONST */
530         constant_FMIref *fieldref;
531
532         LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
533         LOGFLUSH;
534
535         superblockend = false;
536         state->bptr->flags = BBFINISHED;
537
538         /* prevent compiler warnings */
539
540
541         /* determine the active exception handlers for this block */
542         /* XXX could use a faster algorithm with sorted lists or  */
543         /* something?                                             */
544         len = 0;
545         for (ex = state->jd->exceptiontable; ex ; ex = ex->down) {
546                 if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
547                         LOG1("active handler L%03d", ex->handler->nr);
548                         state->handlers[len++] = ex;
549                 }
550         }
551         state->handlers[len] = NULL;
552
553         /* init variable types at the start of this block */
554         typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
555
556         DOLOG(show_basicblock(jd, state->bptr, SHOW_STACK));
557         DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars, 
558                                 state->bptr->indepth));
559         DOLOG(typevector_print(stdout, jd->var, state->numlocals));
560         LOGNL; LOGFLUSH;
561
562         /* loop over the instructions */
563         len = state->bptr->icount;
564         state->iptr = state->bptr->iinstr;
565         while (--len >= 0)  {
566                 TYPECHECK_COUNT(stat_ins);
567
568                 iptr = state->iptr;
569
570                 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
571                 LOGNL; LOGFLUSH;
572                 DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); LOGNL; LOGFLUSH;
573
574                 opcode = iptr->opc;
575                 maythrow = false;
576
577                 switch (opcode) {
578
579                         /* include generated code for ICMDs verification */
580
581 #define TYPECHECK_VARIABLESBASED
582 #define STATE  state
583 #define METHOD (state->m)
584 #define IPTR   iptr
585 #define BPTR   (state->bptr)
586 #include <typecheck-variablesbased-gen.inc>
587 #undef  STATE
588 #undef  METHOD
589 #undef  IPTR
590 #undef  BPTR
591 #undef  TYPECHECK_VARIABLESBASED
592
593                         default:
594                                 LOG1("ICMD %d\n", opcode);
595                                 TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
596                 }
597
598                 /* reach exception handlers for this instruction */
599
600                 if (maythrow) {
601                         TYPECHECK_COUNT(stat_ins_maythrow);
602                         TYPECHECK_MARK(state->stat_maythrow);
603                         LOG("reaching exception handlers");
604                         i = 0;
605                         while (state->handlers[i]) {
606                                 TYPECHECK_COUNT(stat_handlers_reached);
607                                 if (state->handlers[i]->catchtype.any)
608                                         VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
609                                 else
610                                         VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
611                                 if (!typestate_reach(state,
612                                                 state->handlers[i]->handler,
613                                                 &(state->exinvars), jd->var, 1))
614                                         return false;
615                                 i++;
616                         }
617                 }
618
619                 LOG("\t\tnext instruction");
620                 state->iptr++;
621         } /* while instructions */
622
623         LOG("instructions done");
624         LOGSTR("RESULT=> ");
625         DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
626                                 state->bptr->outdepth));
627         DOLOG(typevector_print(stdout, jd->var, state->numlocals));
628         LOGNL; LOGFLUSH;
629
630         /* propagate stack and variables to the following block */
631         if (!superblockend) {
632                 LOG("reaching following block");
633                 tbptr = state->bptr->next;
634                 while (tbptr->flags == BBDELETED) {
635                         tbptr = tbptr->next;
636 #ifdef TYPECHECK_DEBUG
637                         /* this must be checked in parse.c */
638                         if ((tbptr->nr) >= state->basicblockcount)
639                                 TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
640 #endif
641                 }
642                 if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
643                                         state->bptr->outdepth))
644                         return false;
645         }
646
647         /* We may have to restore the types of the instack slots. They
648          * have been saved if an <init> call inside the block has
649          * modified the instack types. (see INVOKESPECIAL) */
650
651         if (state->savedinvars)
652                 typestate_restore_invars(state);
653
654         return true;
655 }
656
657
658 /****************************************************************************/
659 /* typecheck()                                                              */
660 /* This is the main function of the bytecode verifier. It is called         */
661 /* directly after analyse_stack.                                            */
662 /*                                                                          */
663 /* IN:                                                                      */
664 /*    meth.............the method to verify                                 */
665 /*    cdata............codegendata for the method                           */
666 /*    rdata............registerdata for the method                          */
667 /*                                                                          */
668 /* RETURN VALUE:                                                            */
669 /*     true.............successful verification                             */
670 /*     false............an exception has been thrown                        */
671 /*                                                                          */
672 /****************************************************************************/
673
674 #define MAXPARAMS 255
675
676 bool typecheck(jitdata *jd)
677 {
678         methodinfo     *meth;
679         codegendata    *cd;
680         varinfo        *savedlocals;
681         verifier_state  state;             /* current state of the verifier */
682
683         /* collect statistics */
684
685 #ifdef TYPECHECK_STATISTICS
686         int count_iterations = 0;
687         TYPECHECK_COUNT(stat_typechecked);
688         TYPECHECK_COUNT_FREQ(stat_locals,jd->maxlocals,STAT_LOCALS);
689         TYPECHECK_COUNT_FREQ(stat_blocks,cdata->method->basicblockcount/10,STAT_BLOCKS);
690         TYPECHECK_COUNTIF(cdata->method->exceptiontablelength != 0,stat_methods_with_handlers);
691         state.stat_maythrow = false;
692 #endif
693
694         /* get required compiler data */
695
696         meth = jd->m;
697         cd   = jd->cd;
698
699         /* some logging on entry */
700
701
702     LOGSTR("\n==============================================================================\n");
703     DOLOG( show_method(jd, SHOW_STACK) );
704     LOGSTR("\n==============================================================================\n");
705     LOGMETHOD("Entering typecheck: ",cd->method);
706
707         /* initialize the verifier state */
708
709         state.m = meth;
710         state.jd = jd;
711         state.cd = cd;
712         state.basicblockcount = jd->basicblockcount;
713         state.basicblocks = jd->basicblocks;
714         state.savedindices = NULL;
715         state.savedinvars = NULL;
716
717         /* check that the basicblock numbers are valid */
718
719 #if !defined(NDEBUG)
720         jit_check_basicblock_numbers(jd);
721 #endif
722
723         /* check if this method is an instance initializer method */
724
725     state.initmethod = (state.m->name == utf_init);
726
727         /* initialize the basic block flags for the following CFG traversal */
728
729         typecheck_init_flags(&state, BBFINISHED);
730
731     /* number of local variables */
732     
733     /* In <init> methods we use an extra local variable to indicate whether */
734     /* the 'this' reference has been initialized.                           */
735         /*         TYPE_VOID...means 'this' has not been initialized,           */
736         /*         TYPE_INT....means 'this' has been initialized.               */
737
738     state.numlocals = state.jd->localcount;
739         state.validlocals = state.numlocals;
740     if (state.initmethod) 
741                 state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
742
743         DOLOG(
744                 s4 i;
745                 s4 t;
746                 LOG("reverselocalmap:");
747                 for (i=0; i<state.validlocals; ++i) {
748                         LOG2("    %i => javaindex %i", i, jd->reverselocalmap[i]);
749                 });
750
751     /* allocate the buffer of active exception handlers */
752         
753     state.handlers = DMNEW(exception_entry*, state.jd->exceptiontablelength + 1);
754
755         /* save local variables */
756
757         savedlocals = DMNEW(varinfo, state.numlocals);
758         MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
759
760         /* initialized local variables of first block */
761
762         if (!typecheck_init_locals(&state, true))
763                 return false;
764
765     /* initialize invars of exception handlers */
766         
767         state.exinvars = state.numlocals;
768         VAR(state.exinvars)->type = TYPE_ADR;
769         typeinfo_init_classinfo(&(VAR(state.exinvars)->typeinfo),
770                                                         class_java_lang_Throwable); /* changed later */
771
772     LOG("Exception handler stacks set.\n");
773
774     /* loop while there are still blocks to be checked */
775     do {
776                 TYPECHECK_COUNT(count_iterations);
777
778         state.repeat = false;
779         
780         state.bptr = state.basicblocks;
781
782         for (; state.bptr; state.bptr = state.bptr->next) {
783             LOGSTR1("---- BLOCK %04d, ",state.bptr->nr);
784             LOGSTR1("blockflags: %d\n",state.bptr->flags);
785             LOGFLUSH;
786             
787                     /* verify reached block */  
788             if (state.bptr->flags == BBTYPECHECK_REACHED) {
789                 if (!handle_basic_block(&state))
790                                         return false;
791             }
792         } /* for blocks */
793
794         LOGIF(state.repeat,"state.repeat == true");
795     } while (state.repeat);
796
797         /* statistics */
798         
799 #ifdef TYPECHECK_STATISTICS
800         LOG1("Typechecker did %4d iterations",count_iterations);
801         TYPECHECK_COUNT_FREQ(stat_iterations,count_iterations,STAT_ITERATIONS);
802         TYPECHECK_COUNTIF(state.jsrencountered,stat_typechecked_jsr);
803         TYPECHECK_COUNTIF(state.stat_maythrow,stat_methods_maythrow);
804 #endif
805
806         /* reset the flags of blocks we haven't reached */
807
808         typecheck_reset_flags(&state);
809
810         /* restore locals */
811
812         MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
813
814         /* everything's ok */
815
816     LOGimp("exiting typecheck");
817         return true;
818 }
819 #endif /* ENABLE_VERIFIER */
820
821 /*
822  * These are local overrides for various environment variables in Emacs.
823  * Please do not remove this and leave it at the end of the file, where
824  * Emacs will automagically detect them.
825  * ---------------------------------------------------------------------
826  * Local variables:
827  * mode: c
828  * indent-tabs-mode: t
829  * c-basic-offset: 4
830  * tab-width: 4
831  * End:
832  * vim:noexpandtab:sw=4:ts=4:
833  */