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