Line data Source code
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 :
173 : #include "vm/jit/verify/typecheck-common.hpp"
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
223 721 : typestate_save_invars(verifier_state *state)
224 : {
225 : s4 i, index;
226 : s4 *pindex;
227 :
228 : OLD_LOG("saving invars");
229 :
230 721 : if (!state->savedindices) {
231 : OLD_LOG("allocating savedindices buffer");
232 574 : pindex = (s4*) DumpMemory::allocate(sizeof(s4) * state->m->maxstack);
233 574 : state->savedindices = pindex;
234 574 : index = state->numlocals + VERIFIER_EXTRA_VARS;
235 3612 : for (i=0; i<state->m->maxstack; ++i)
236 3038 : *pindex++ = index++;
237 : }
238 :
239 : /* save types */
240 :
241 : typecheck_copy_types(state, state->bptr->invars, state->savedindices,
242 721 : state->bptr->indepth);
243 :
244 : /* set the invars of the block to the saved variables */
245 : /* and remember the original invars */
246 :
247 721 : state->savedinvars = state->bptr->invars;
248 721 : state->bptr->invars = state->savedindices;
249 721 : }
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
263 721 : typestate_restore_invars(verifier_state *state)
264 : {
265 : TYPECHECK_COUNT(stat_savedstack);
266 : OLD_LOG("restoring saved invars");
267 :
268 : /* restore the invars pointer */
269 :
270 721 : state->bptr->invars = state->savedinvars;
271 :
272 : /* copy the types back */
273 :
274 : typecheck_copy_types(state, state->savedindices, state->bptr->invars,
275 721 : state->bptr->indepth);
276 :
277 : /* mark that there are no saved invars currently */
278 :
279 721 : state->savedinvars = NULL;
280 721 : }
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
297 225545 : handle_fieldaccess(verifier_state *state,
298 : varinfo *instance,
299 : varinfo *value)
300 : {
301 : jitdata *jd;
302 :
303 225545 : 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 225545 : 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
331 289993 : handle_invocation(verifier_state *state)
332 : {
333 : jitdata *jd;
334 : varinfo *dv; /* output variable of current instruction */
335 :
336 289993 : jd = state->jd;
337 289993 : 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 289988 : 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
363 79492 : handle_builtin(verifier_state *state)
364 : {
365 : jitdata *jd;
366 : varinfo *dv; /* output variable of current instruction */
367 :
368 79492 : jd = state->jd;
369 79492 : 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 79492 : 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
394 15 : handle_multianewarray(verifier_state *state)
395 : {
396 : jitdata *jd;
397 : varinfo *dv; /* output variable of current instruction */
398 :
399 15 : jd = state->jd;
400 15 : dv = VAROP(state->iptr->dst);
401 :
402 : #define TYPECHECK_VARIABLESBASED
403 : #define VERIFY_ERROR(msg) TYPECHECK_VERIFYERROR_bool(msg)
404 : #include <typecheck-multianewarray.inc>
405 : #undef VERIFY_ERROR
406 : #undef TYPECHECK_VARIABLESBASED
407 :
408 15 : 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 100480 : static void typecheck_invalidate_locals(verifier_state *state, s4 index, bool twoword)
423 : {
424 : s4 javaindex;
425 : s4 t;
426 : s4 varindex;
427 100480 : jitdata *jd = state->jd;
428 100480 : s4 *localmap = jd->local_map;
429 100480 : varinfo *vars = jd->var;
430 :
431 100480 : javaindex = jd->reverselocalmap[index];
432 :
433 : /* invalidate locals of two-word type at index javaindex-1 */
434 :
435 100480 : if (javaindex > 0) {
436 96281 : localmap += 5 * (javaindex-1);
437 577686 : for (t=0; t<5; ++t) {
438 481405 : varindex = *localmap++;
439 481405 : if (varindex >= 0 && IS_2_WORD_TYPE(vars[varindex].type)) {
440 : OLD_LOG1("invalidate local %d", varindex);
441 3 : vars[varindex].type = TYPE_VOID;
442 : }
443 : }
444 : }
445 : else {
446 4199 : localmap += 5 * javaindex;
447 : }
448 :
449 : /* invalidate locals at index javaindex */
450 :
451 602880 : for (t=0; t<5; ++t) {
452 502400 : varindex = *localmap++;
453 502400 : if (varindex >= 0) {
454 : OLD_LOG1("invalidate local %d", varindex);
455 109170 : vars[varindex].type = TYPE_VOID;
456 : }
457 : }
458 :
459 : /* if a two-word type is written, invalidate locals at index javaindex+1 */
460 :
461 100480 : if (twoword) {
462 31380 : for (t=0; t<5; ++t) {
463 26150 : varindex = *localmap++;
464 26150 : if (varindex >= 0) {
465 : OLD_LOG1("invalidate local %d", varindex);
466 9 : vars[varindex].type = TYPE_VOID;
467 : }
468 : }
469 : }
470 100480 : }
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
523 327877 : handle_basic_block(verifier_state *state)
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;
532 : typecheck_result r;
533 : branch_target_t *table;
534 : lookup_target_t *lookup;
535 327877 : 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 327877 : superblockend = false;
544 327877 : 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 327877 : len = 0;
553 645025 : for (ex = state->jd->exceptiontable; ex ; ex = ex->down) {
554 317148 : if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
555 : OLD_LOG1("active handler L%03d", ex->handler->nr);
556 36802 : state->handlers[len++] = ex;
557 : }
558 : }
559 327877 : state->handlers[len] = NULL;
560 :
561 : /* init variable types at the start of this block */
562 327877 : 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));
568 : OLD_LOGNL; OLD_LOGFLUSH;
569 :
570 : /* loop over the instructions */
571 327876 : len = state->bptr->icount;
572 327876 : state->iptr = state->bptr->iinstr;
573 5133432 : while (--len >= 0) {
574 : TYPECHECK_COUNT(stat_ins);
575 :
576 4477694 : iptr = state->iptr;
577 :
578 : DOLOG(typevector_print(stdout, jd->var, state->numlocals));
579 : OLD_LOGNL; OLD_LOGFLUSH;
580 : DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); OLD_LOGNL; OLD_LOGFLUSH;
581 :
582 4477694 : opcode = iptr->opc;
583 4477694 : maythrow = false;
584 :
585 4477694 : 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 0 : TYPECHECK_VERIFYERROR_bool("Missing ICMD code during typecheck");
604 : }
605 :
606 : /* reach exception handlers for this instruction */
607 :
608 4477680 : if (maythrow) {
609 : TYPECHECK_COUNT(stat_ins_maythrow);
610 : TYPECHECK_MARK(state->stat_maythrow);
611 : OLD_LOG("reaching exception handlers");
612 1450758 : i = 0;
613 3008816 : while (state->handlers[i]) {
614 : TYPECHECK_COUNT(stat_handlers_reached);
615 107300 : if (state->handlers[i]->catchtype.any)
616 70839 : VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
617 : else
618 36461 : VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
619 214600 : if (!typestate_reach(state,
620 107300 : state->handlers[i]->handler,
621 : &(state->exinvars), jd->var, 1))
622 0 : return false;
623 107300 : i++;
624 : }
625 : }
626 :
627 : OLD_LOG("\t\tnext instruction");
628 4477680 : 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));
636 : OLD_LOGNL; OLD_LOGFLUSH;
637 :
638 : /* propagate stack and variables to the following block */
639 327862 : if (!superblockend) {
640 : OLD_LOG("reaching following block");
641 168579 : tbptr = state->bptr->next;
642 337158 : while (tbptr->state == basicblock::DELETED) {
643 0 : tbptr = tbptr->next;
644 : #ifdef TYPECHECK_DEBUG
645 : /* this must be checked in parse.c */
646 0 : if ((tbptr->nr) >= state->basicblockcount)
647 0 : TYPECHECK_VERIFYERROR_bool("Control flow falls off the last block");
648 : #endif
649 : }
650 168579 : if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
651 : state->bptr->outdepth))
652 2 : 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 327860 : if (state->savedinvars)
660 721 : typestate_restore_invars(state);
661 :
662 327860 : 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 :
684 86416 : bool typecheck(jitdata *jd)
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 86416 : meth = jd->m;
705 86416 : 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 86416 : state.m = meth;
718 86416 : state.jd = jd;
719 86416 : state.cd = cd;
720 86416 : state.basicblockcount = jd->basicblockcount;
721 86416 : state.basicblocks = jd->basicblocks;
722 86416 : state.savedindices = NULL;
723 86416 : state.savedinvars = NULL;
724 :
725 : /* check that the basicblock numbers are valid */
726 :
727 : #if !defined(NDEBUG)
728 86416 : jit_check_basicblock_numbers(jd);
729 : #endif
730 :
731 : /* check if this method is an instance initializer method */
732 :
733 86416 : state.initmethod = (state.m->name == utf8::init);
734 :
735 : /* initialize the basic block flags for the following CFG traversal */
736 :
737 86416 : typecheck_init_state(&state, basicblock::FINISHED);
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 86416 : state.numlocals = state.jd->localcount;
747 86416 : state.validlocals = state.numlocals;
748 86416 : if (state.initmethod)
749 25532 : 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 :
761 86416 : state.handlers = (exception_entry**) DumpMemory::allocate(sizeof(exception_entry*) * (state.jd->exceptiontablelength + 1));
762 :
763 : /* save local variables */
764 :
765 86416 : savedlocals = (varinfo*) DumpMemory::allocate(sizeof(varinfo) * state.numlocals);
766 86416 : MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
767 :
768 : /* initialized local variables of first block */
769 :
770 86416 : if (!typecheck_init_locals(&state, true))
771 0 : return false;
772 :
773 : /* initialize invars of exception handlers */
774 :
775 86416 : state.exinvars = state.numlocals;
776 86416 : VAR(state.exinvars)->type = TYPE_ADR;
777 86416 : 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 94946 : do {
783 : TYPECHECK_COUNT(count_iterations);
784 :
785 94963 : state.repeat = false;
786 94963 : state.bptr = state.basicblocks;
787 :
788 640062 : 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 545116 : if (state.bptr->state == basicblock::TYPECHECK_REACHED) {
795 327877 : if (!handle_basic_block(&state))
796 17 : 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 86399 : typecheck_reset_state(&state);
815 :
816 : /* restore locals */
817 :
818 86399 : MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
819 :
820 : /* everything's ok */
821 :
822 : OLD_LOGimp("exiting typecheck");
823 86399 : 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 : */
|