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.h"
34 #include "native/native.h"
36 #include "toolbox/logging.h"
38 #include "vm/access.h"
40 #include "vm/builtin.h"
41 #include "vm/exceptions.hpp"
42 #include "vm/globals.hpp"
43 #include "vm/loader.h"
44 #include "vm/options.h"
45 #include "vm/primitive.hpp"
46 #include "vm/resolve.h"
49 #include "vm/jit/jit.h"
50 #include "vm/jit/show.h"
51 #include "vm/jit/parse.h"
53 #include "vm/jit/verify/typecheck-typeinferer.h"
55 #define TYPECHECK_NO_STATISTICS
56 #include <typecheck-common.h>
59 /* macros used by the generated code ******************************************/
61 #define EXCEPTION do { return false; } while (0)
62 #define VERIFY_ERROR(msg) assert(false)
64 #define CHECK_LOCAL_TYPE(index, t) \
65 assert(jd->var[(index)].type == (t));
67 #define STORE_LOCAL(t, index) \
69 typevector_store(jd->var, (index), (t), NULL); \
72 #define STORE_LOCAL_2_WORD(t, index) \
74 typevector_store(jd->var, (index), (t), NULL); \
77 #define REACH_BLOCK(target) \
79 if (!typestate_reach(state, (target), \
80 state->bptr->outvars, jd->var, \
81 state->bptr->outdepth)) \
85 #define REACH(target) REACH_BLOCK((target).block)
87 #define TYPECHECK_INT(v) assert(jd->var[(v)].type == TYPE_INT)
88 #define TYPECHECK_ADR(v) assert(jd->var[(v)].type == TYPE_ADR)
91 /* handle_fieldaccess **********************************************************
93 Verify an ICMD_{GET,PUT}{STATIC,FIELD}(CONST)?
96 state............the current state of the verifier
99 true.............successful verification,
100 false............an exception has been thrown.
102 *******************************************************************************/
105 handle_fieldaccess(verifier_state *state,
113 #define TYPECHECK_TYPEINFERER
114 #include <typecheck-fields.inc>
115 #undef TYPECHECK_TYPEINFERER
121 /* handle_invocation ***********************************************************
123 Verify an ICMD_INVOKE* instruction.
126 state............the current state of the verifier
129 true.............successful verification,
130 false............an exception has been thrown.
132 *******************************************************************************/
135 handle_invocation(verifier_state *state)
138 varinfo *dv; /* output variable of current instruction */
141 dv = VAROP(state->iptr->dst);
143 #define TYPECHECK_TYPEINFERER
144 #define OP1 VAR(state->iptr->sx.s23.s2.args[0])
145 #include <typecheck-invoke.inc>
147 #undef TYPECHECK_TYPEINFERER
153 /* handle_builtin **************************************************************
155 Verify the call of a builtin method.
158 state............the current state of the verifier
161 true.............successful verification,
162 false............an exception has been thrown.
164 *******************************************************************************/
167 handle_builtin(verifier_state *state)
170 varinfo *dv; /* output variable of current instruction */
173 dv = VAROP(state->iptr->dst);
175 #define TYPECHECK_TYPEINFERER
176 #define OP1 state->iptr->sx.s23.s2.args[0]
177 #include <typecheck-builtins.inc>
179 #undef TYPECHECK_TYPEINFERER
184 /* handle_multianewarray *******************************************************
186 Verify a MULTIANEWARRAY instruction.
189 state............the current state of the verifier
192 true.............successful verification,
193 false............an exception has been thrown.
195 *******************************************************************************/
198 handle_multianewarray(verifier_state *state)
201 varinfo *dv; /* output variable of current instruction */
204 dv = VAROP(state->iptr->dst);
206 #define TYPECHECK_TYPEINFERER
207 #include <typecheck-multianewarray.inc>
208 #undef TYPECHECK_TYPEINFERER
214 /* handle_basic_block **********************************************************
216 Perform bytecode verification of a basic block.
219 state............the current state of the verifier
222 true.............successful verification,
223 false............an exception has been thrown.
225 *******************************************************************************/
228 handle_basic_block(verifier_state *state)
230 int opcode; /* current opcode */
231 int len; /* for counting instructions, etc. */
232 bool superblockend; /* true if no fallthrough to next block */
233 instruction *iptr; /* the current instruction */
234 basicblock *tbptr; /* temporary for target block */
235 bool maythrow; /* true if this instruction may throw */
237 branch_target_t *table;
238 lookup_target_t *lookup;
239 jitdata *jd = state->jd;
242 LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
244 DOLOG(show_basicblock(jd, state->bptr, SHOW_STACK));
246 superblockend = false;
247 state->bptr->flags = BBFINISHED;
249 /* prevent compiler warnings */
252 /* determine the active exception handlers for this block */
253 /* XXX could use a faster algorithm with sorted lists or */
256 for (ex = state->jd->exceptiontable; ex ; ex = ex->down) {
257 if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
258 LOG1("active handler L%03d", ex->handler->nr);
259 state->handlers[len++] = ex;
262 state->handlers[len] = NULL;
264 /* init variable types at the start of this block */
265 typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
267 DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars,
268 state->bptr->indepth));
269 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
272 /* loop over the instructions */
273 len = state->bptr->icount;
274 state->iptr = state->bptr->iinstr;
276 TYPECHECK_COUNT(stat_ins);
280 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
282 DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); LOGNL; LOGFLUSH;
289 /* include generated code for ICMDs verification */
291 #define TYPECHECK_TYPEINFERER
293 #define METHOD (state->m)
295 #define BPTR (state->bptr)
296 #include <typecheck-typeinferer-gen.inc>
301 #undef TYPECHECK_TYPEINFERER
304 vm_abort("missing ICMD in type inferer: %d\n", opcode);
307 /* reach exception handlers for this instruction */
310 TYPECHECK_COUNT(stat_ins_maythrow);
311 TYPECHECK_MARK(state->stat_maythrow);
312 LOG("reaching exception handlers");
314 while (state->handlers[i]) {
315 TYPECHECK_COUNT(stat_handlers_reached);
316 if (state->handlers[i]->catchtype.any)
317 VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
319 VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
320 if (!typestate_reach(state,
321 state->handlers[i]->handler,
322 &(state->exinvars), jd->var, 1))
328 LOG("\t\tnext instruction");
330 } /* while instructions */
332 LOG("instructions done");
334 DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
335 state->bptr->outdepth));
336 DOLOG(typevector_print(stdout, jd->var, state->numlocals));
339 /* propagate stack and variables to the following block */
340 if (!superblockend) {
341 LOG("reaching following block");
342 tbptr = state->bptr->next;
343 while (tbptr->flags == BBDELETED) {
346 if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
347 state->bptr->outdepth))
355 bool typecheck_infer_types(jitdata *jd)
359 varinfo *savedlocals;
360 verifier_state state; /* current state of the verifier */
362 /* get required compiler data */
367 /* some logging on entry */
370 LOGSTR("\n==============================================================================\n");
371 DOLOG( show_method(jd, SHOW_STACK) );
372 LOGSTR("\n==============================================================================\n");
373 LOGMETHOD("Entering type inference: ",cd->method);
375 /* initialize the verifier state */
380 state.basicblockcount = jd->basicblockcount;
381 state.basicblocks = jd->basicblocks;
382 state.savedindices = NULL;
383 state.savedinvars = NULL;
385 /* check that the basicblock numbers are valid */
388 jit_check_basicblock_numbers(jd);
391 /* check if this method is an instance initializer method */
393 state.initmethod = (state.m->name == utf_init);
395 /* initialize the basic block flags for the following CFG traversal */
397 typecheck_init_flags(&state, BBFINISHED);
399 /* number of local variables */
401 /* In <init> methods we use an extra local variable to indicate whether */
402 /* the 'this' reference has been initialized. */
403 /* TYPE_VOID...means 'this' has not been initialized, */
404 /* TYPE_INT....means 'this' has been initialized. */
406 state.numlocals = state.jd->localcount;
407 state.validlocals = state.numlocals;
408 if (state.initmethod)
409 state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
411 /* allocate the buffer of active exception handlers */
413 state.handlers = DMNEW(exception_entry*, state.jd->exceptiontablelength + 1);
415 /* save local variables */
417 savedlocals = DMNEW(varinfo, state.numlocals);
418 MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
420 /* initialized local variables of first block */
422 if (!typecheck_init_locals(&state, false))
425 /* initialize invars of exception handlers */
427 state.exinvars = state.numlocals;
428 VAR(state.exinvars)->type = TYPE_ADR;
429 typeinfo_init_classinfo(&(VAR(state.exinvars)->typeinfo),
430 class_java_lang_Throwable); /* changed later */
432 LOG("Exception handler stacks set.\n");
434 /* loop while there are still blocks to be checked */
436 TYPECHECK_COUNT(count_iterations);
438 state.repeat = false;
440 state.bptr = state.basicblocks;
442 for (; state.bptr; state.bptr = state.bptr->next) {
443 LOGSTR1("---- BLOCK %04d, ",state.bptr->nr);
444 LOGSTR1("blockflags: %d\n",state.bptr->flags);
447 /* verify reached block */
448 if (state.bptr->flags == BBTYPECHECK_REACHED) {
449 if (!handle_basic_block(&state))
454 LOGIF(state.repeat,"state.repeat == true");
455 } while (state.repeat);
459 /* reset the flags of blocks we haven't reached */
461 typecheck_reset_flags(&state);
465 MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
467 /* everything's ok */
469 LOGimp("exiting type inference");
474 * These are local overrides for various environment variables in Emacs.
475 * Please do not remove this and leave it at the end of the file, where
476 * Emacs will automagically detect them.
477 * ---------------------------------------------------------------------
480 * indent-tabs-mode: t
484 * vim:noexpandtab:sw=4:ts=4: