1 /* src/vm/jit/verify/typecheck-typeinferer.c - type inference pass
3 Copyright (C) 1996-2005, 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
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.
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.
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
27 #include "vm/global.h"
32 #include "mm/memory.hpp"
34 #include "native/native.hpp"
36 #include "toolbox/logging.hpp"
38 #include "vm/access.hpp"
39 #include "vm/array.hpp"
40 #include "vm/jit/builtin.hpp"
41 #include "vm/exceptions.hpp"
42 #include "vm/globals.hpp"
43 #include "vm/loader.hpp"
44 #include "vm/options.h"
45 #include "vm/primitive.hpp"
46 #include "vm/resolve.hpp"
49 #include "vm/jit/jit.hpp"
50 #include "vm/jit/show.hpp"
51 #include "vm/jit/parse.hpp"
53 #include "vm/jit/verify/typecheck-typeinferer.hpp"
55 #define TYPECHECK_NO_STATISTICS
56 #include "vm/jit/verify/typecheck-common.hpp"
58 #if defined(__cplusplus)
62 /* macros used by the generated code ******************************************/
64 #define EXCEPTION do { return false; } while (0)
65 #define VERIFY_ERROR(msg) assert(false)
67 #define CHECK_LOCAL_TYPE(index, t) \
68 assert(jd->var[(index)].type == (t));
70 #define STORE_LOCAL(t, index) \
72 typevector_store(jd->var, (index), (t), NULL); \
75 #define STORE_LOCAL_2_WORD(t, index) \
77 typevector_store(jd->var, (index), (t), NULL); \
80 #define REACH_BLOCK(target) \
82 if (!typestate_reach(state, (target), \
83 state->bptr->outvars, jd->var, \
84 state->bptr->outdepth)) \
88 #define REACH(target) REACH_BLOCK((target).block)
90 #define TYPECHECK_INT(v) assert(jd->var[(v)].type == TYPE_INT)
91 #define TYPECHECK_ADR(v) assert(jd->var[(v)].type == TYPE_ADR)
94 /* handle_fieldaccess **********************************************************
96 Verify an ICMD_{GET,PUT}{STATIC,FIELD}(CONST)?
99 state............the current state of the verifier
102 true.............successful verification,
103 false............an exception has been thrown.
105 *******************************************************************************/
108 handle_fieldaccess(verifier_state *state,
116 #define TYPECHECK_TYPEINFERER
117 #include <typecheck-fields.inc>
118 #undef TYPECHECK_TYPEINFERER
124 /* handle_invocation ***********************************************************
126 Verify an ICMD_INVOKE* instruction.
129 state............the current state of the verifier
132 true.............successful verification,
133 false............an exception has been thrown.
135 *******************************************************************************/
138 handle_invocation(verifier_state *state)
141 varinfo *dv; /* output variable of current instruction */
144 dv = VAROP(state->iptr->dst);
146 #define TYPECHECK_TYPEINFERER
147 #define OP1 VAR(state->iptr->sx.s23.s2.args[0])
148 #include <typecheck-invoke.inc>
150 #undef TYPECHECK_TYPEINFERER
156 /* handle_builtin **************************************************************
158 Verify the call of a builtin method.
161 state............the current state of the verifier
164 true.............successful verification,
165 false............an exception has been thrown.
167 *******************************************************************************/
170 handle_builtin(verifier_state *state)
173 varinfo *dv; /* output variable of current instruction */
176 dv = VAROP(state->iptr->dst);
178 #define TYPECHECK_TYPEINFERER
179 #define OP1 state->iptr->sx.s23.s2.args[0]
180 #include <typecheck-builtins.inc>
182 #undef TYPECHECK_TYPEINFERER
187 /* handle_multianewarray *******************************************************
189 Verify a MULTIANEWARRAY instruction.
192 state............the current state of the verifier
195 true.............successful verification,
196 false............an exception has been thrown.
198 *******************************************************************************/
201 handle_multianewarray(verifier_state *state)
204 varinfo *dv; /* output variable of current instruction */
207 dv = VAROP(state->iptr->dst);
209 #define TYPECHECK_TYPEINFERER
210 #include <typecheck-multianewarray.inc>
211 #undef TYPECHECK_TYPEINFERER
217 /* handle_basic_block **********************************************************
219 Perform bytecode verification of a basic block.
222 state............the current state of the verifier
225 true.............successful verification,
226 false............an exception has been thrown.
228 *******************************************************************************/
231 handle_basic_block(verifier_state *state)
233 int opcode; /* current opcode */
234 int len; /* for counting instructions, etc. */
235 bool superblockend; /* true if no fallthrough to next block */
236 instruction *iptr; /* the current instruction */
237 basicblock *tbptr; /* temporary for target block */
238 bool maythrow; /* true if this instruction may throw */
240 branch_target_t *table;
241 lookup_target_t *lookup;
242 jitdata *jd = state->jd;
245 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
247 DOLOG(show_basicblock(jd, state->bptr, SHOW_STACK));
249 superblockend = false;
250 state->bptr->flags = BBFINISHED;
252 /* prevent compiler warnings */
255 /* determine the active exception handlers for this block */
256 /* XXX could use a faster algorithm with sorted lists or */
259 for (ex = state->jd->exceptiontable; ex ; ex = ex->down) {
260 if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
261 LOG1("active handler L%03d", ex->handler->nr);
262 state->handlers[len++] = ex;
265 state->handlers[len] = NULL;
267 /* init variable types at the start of this block */
268 typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
270 DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars,
271 state->bptr->indepth));
272 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
275 /* loop over the instructions */
276 len = state->bptr->icount;
277 state->iptr = state->bptr->iinstr;
279 TYPECHECK_COUNT(stat_ins);
283 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
285 DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); LOGNL; LOGFLUSH;
292 /* include generated code for ICMDs verification */
294 #define TYPECHECK_TYPEINFERER
296 #define METHOD (state->m)
298 #define BPTR (state->bptr)
299 #include <typecheck-typeinferer-gen.inc>
304 #undef TYPECHECK_TYPEINFERER
307 vm_abort("missing ICMD in type inferer: %d\n", opcode);
310 /* reach exception handlers for this instruction */
313 TYPECHECK_COUNT(stat_ins_maythrow);
314 TYPECHECK_MARK(state->stat_maythrow);
315 LOG("reaching exception handlers");
317 while (state->handlers[i]) {
318 TYPECHECK_COUNT(stat_handlers_reached);
319 if (state->handlers[i]->catchtype.any)
320 VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
322 VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
323 if (!typestate_reach(state,
324 state->handlers[i]->handler,
325 &(state->exinvars), jd->var, 1))
331 LOG("\t\tnext instruction");
333 } /* while instructions */
335 LOG("instructions done");
337 DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
338 state->bptr->outdepth));
339 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
342 /* propagate stack and variables to the following block */
343 if (!superblockend) {
344 LOG("reaching following block");
345 tbptr = state->bptr->next;
346 while (tbptr->flags == BBDELETED) {
349 if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
350 state->bptr->outdepth))
358 bool typecheck_infer_types(jitdata *jd)
362 varinfo *savedlocals;
363 verifier_state state; /* current state of the verifier */
365 /* get required compiler data */
370 /* some logging on entry */
373 LOGSTR("\n==============================================================================\n");
374 DOLOG( show_method(jd, SHOW_STACK) );
375 LOGSTR("\n==============================================================================\n");
376 LOGMETHOD("Entering type inference: ",cd->method);
378 /* initialize the verifier state */
383 state.basicblockcount = jd->basicblockcount;
384 state.basicblocks = jd->basicblocks;
385 state.savedindices = NULL;
386 state.savedinvars = NULL;
388 /* check that the basicblock numbers are valid */
391 jit_check_basicblock_numbers(jd);
394 /* check if this method is an instance initializer method */
396 state.initmethod = (state.m->name == utf_init);
398 /* initialize the basic block flags for the following CFG traversal */
400 typecheck_init_flags(&state, BBFINISHED);
402 /* number of local variables */
404 /* In <init> methods we use an extra local variable to indicate whether */
405 /* the 'this' reference has been initialized. */
406 /* TYPE_VOID...means 'this' has not been initialized, */
407 /* TYPE_INT....means 'this' has been initialized. */
409 state.numlocals = state.jd->localcount;
410 state.validlocals = state.numlocals;
411 if (state.initmethod)
412 state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
414 /* allocate the buffer of active exception handlers */
416 state.handlers = (exception_entry**) DumpMemory::allocate(sizeof(exception_entry*) * (state.jd->exceptiontablelength + 1));
418 /* save local variables */
420 savedlocals = (varinfo*) DumpMemory::allocate(sizeof(varinfo) * state.numlocals);
421 MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
423 /* initialized local variables of first block */
425 if (!typecheck_init_locals(&state, false))
428 /* initialize invars of exception handlers */
430 state.exinvars = state.numlocals;
431 VAR(state.exinvars)->type = TYPE_ADR;
432 typeinfo_init_classinfo(&(VAR(state.exinvars)->typeinfo),
433 class_java_lang_Throwable); /* changed later */
435 LOG("Exception handler stacks set.\n");
437 /* loop while there are still blocks to be checked */
439 TYPECHECK_COUNT(count_iterations);
441 state.repeat = false;
443 state.bptr = state.basicblocks;
445 for (; state.bptr; state.bptr = state.bptr->next) {
446 LOGSTR1("---- BLOCK %04d, ",state.bptr->nr);
447 LOGSTR1("blockflags: %d\n",state.bptr->flags);
450 /* verify reached block */
451 if (state.bptr->flags == BBTYPECHECK_REACHED) {
452 if (!handle_basic_block(&state))
457 LOGIF(state.repeat,"state.repeat == true");
458 } while (state.repeat);
462 /* reset the flags of blocks we haven't reached */
464 typecheck_reset_flags(&state);
468 MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
470 /* everything's ok */
472 LOGimp("exiting type inference");
476 #if defined(__cplusplus)
481 * These are local overrides for various environment variables in Emacs.
482 * Please do not remove this and leave it at the end of the file, where
483 * Emacs will automagically detect them.
484 * ---------------------------------------------------------------------
487 * indent-tabs-mode: t
491 * vim:noexpandtab:sw=4:ts=4: