CACAO
typecheck-typeinferer.cpp
Go to the documentation of this file.
1 /* src/vm/jit/verify/typecheck-typeinferer.c - type inference pass
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 
26 #include "config.h"
27 
28 #include <assert.h>
29 #include <string.h>
30 
31 #include "mm/memory.hpp"
32 #include "mm/dumpmemory.hpp"
33 
34 #include "native/native.hpp"
35 
36 #include "toolbox/logging.hpp"
37 
38 #include "vm/access.hpp"
39 #include "vm/array.hpp"
40 #include "vm/descriptor.hpp" // for typedesc, methoddesc, etc
41 #include "vm/exceptions.hpp"
42 #include "vm/global.hpp"
43 #include "vm/globals.hpp"
44 #include "vm/options.hpp"
45 #include "vm/primitive.hpp"
46 #include "vm/resolve.hpp"
47 #include "vm/types.hpp"
48 #include "vm/vm.hpp"
49 
50 #include "vm/jit/builtin.hpp"
51 #include "vm/jit/jit.hpp"
52 #include "vm/jit/show.hpp"
53 #include "vm/jit/parse.hpp"
54 
56 
57 #define TYPECHECK_NO_STATISTICS
59 
60 
61 /* macros used by the generated code ******************************************/
62 
63 #define EXCEPTION do { return false; } while (0)
64 #define VERIFY_ERROR(msg) assert(false)
65 
66 #define CHECK_LOCAL_TYPE(index, t) \
67  assert(jd->var[(index)].type == (t));
68 
69 #define STORE_LOCAL(t, index) \
70  do { \
71  typevector_store(jd->var, (index), (t), NULL); \
72  } while (0)
73 
74 #define STORE_LOCAL_2_WORD(t, index) \
75  do { \
76  typevector_store(jd->var, (index), (t), NULL); \
77  } while (0)
78 
79 #define REACH_BLOCK(target) \
80  do { \
81  if (!typestate_reach(state, (target), \
82  state->bptr->outvars, jd->var, \
83  state->bptr->outdepth)) \
84  return false; \
85  } while (0)
86 
87 #define REACH(target) REACH_BLOCK((target).block)
88 
89 #define TYPECHECK_INT(v) assert(jd->var[(v)].type == TYPE_INT)
90 #define TYPECHECK_ADR(v) assert(jd->var[(v)].type == TYPE_ADR)
91 
92 
93 /* handle_fieldaccess **********************************************************
94 
95  Verify an ICMD_{GET,PUT}{STATIC,FIELD}(CONST)?
96 
97  IN:
98  state............the current state of the verifier
99 
100  RETURN VALUE:
101  true.............successful verification,
102  false............an exception has been thrown.
103 
104 *******************************************************************************/
105 
106 static bool
108  varinfo *instance,
109  varinfo *value)
110 {
111  jitdata *jd;
112 
113  jd = state->jd;
114 
115 #define TYPECHECK_TYPEINFERER
116 #include <typecheck-fields.inc>
117 #undef TYPECHECK_TYPEINFERER
118 
119  return true;
120 }
121 
122 
123 /* handle_invocation ***********************************************************
124 
125  Verify an ICMD_INVOKE* instruction.
126 
127  IN:
128  state............the current state of the verifier
129 
130  RETURN VALUE:
131  true.............successful verification,
132  false............an exception has been thrown.
133 
134 *******************************************************************************/
135 
136 static bool
138 {
139  jitdata *jd;
140  varinfo *dv; /* output variable of current instruction */
141 
142  jd = state->jd;
143  dv = VAROP(state->iptr->dst);
144 
145 #define TYPECHECK_TYPEINFERER
146 #define OP1 VAR(state->iptr->sx.s23.s2.args[0])
147 #include <typecheck-invoke.inc>
148 #undef OP1
149 #undef TYPECHECK_TYPEINFERER
150 
151  return true;
152 }
153 
154 
155 /* handle_builtin **************************************************************
156 
157  Verify the call of a builtin method.
158 
159  IN:
160  state............the current state of the verifier
161 
162  RETURN VALUE:
163  true.............successful verification,
164  false............an exception has been thrown.
165 
166 *******************************************************************************/
167 
168 static bool
170 {
171  jitdata *jd;
172  varinfo *dv; /* output variable of current instruction */
173 
174  jd = state->jd;
175  dv = VAROP(state->iptr->dst);
176 
177 #define TYPECHECK_TYPEINFERER
178 #define OP1 state->iptr->sx.s23.s2.args[0]
179 #include <typecheck-builtins.inc>
180 #undef OP1
181 #undef TYPECHECK_TYPEINFERER
182 
183  return true;
184 }
185 
186 /* handle_multianewarray *******************************************************
187 
188  Verify a MULTIANEWARRAY instruction.
189 
190  IN:
191  state............the current state of the verifier
192 
193  RETURN VALUE:
194  true.............successful verification,
195  false............an exception has been thrown.
196 
197 *******************************************************************************/
198 
199 static bool
201 {
202  jitdata *jd;
203  varinfo *dv; /* output variable of current instruction */
204 
205  jd = state->jd;
206  dv = VAROP(state->iptr->dst);
207 
208 #define TYPECHECK_TYPEINFERER
210 #undef TYPECHECK_TYPEINFERER
211 
212  return true;
213 }
214 
215 
216 /* handle_basic_block **********************************************************
217 
218  Perform bytecode verification of a basic block.
219 
220  IN:
221  state............the current state of the verifier
222 
223  RETURN VALUE:
224  true.............successful verification,
225  false............an exception has been thrown.
226 
227 *******************************************************************************/
228 
229 static bool
231 {
232  int opcode; /* current opcode */
233  int len; /* for counting instructions, etc. */
234  bool superblockend; /* true if no fallthrough to next block */
235  instruction *iptr; /* the current instruction */
236  basicblock *tbptr; /* temporary for target block */
237  bool maythrow; /* true if this instruction may throw */
238  s4 i;
239  branch_target_t *table;
240  lookup_target_t *lookup;
241  jitdata *jd = state->jd;
242  exception_entry *ex;
243 
244  OLD_LOGSTR1("\n---- BLOCK %04d ------------------------------------------------\n",state->bptr->nr);
245  OLD_LOGFLUSH;
246  DOLOG(show_basicblock(jd, state->bptr, SHOW_STACK));
247 
248  superblockend = false;
249  state->bptr->state = basicblock::FINISHED;
250 
251  /* prevent compiler warnings */
252 
253 
254  /* determine the active exception handlers for this block */
255  /* XXX could use a faster algorithm with sorted lists or */
256  /* something? */
257  len = 0;
258  for (ex = state->jd->exceptiontable; ex ; ex = ex->down) {
259  if ((ex->start->nr <= state->bptr->nr) && (ex->end->nr > state->bptr->nr)) {
260  OLD_LOG1("active handler L%03d", ex->handler->nr);
261  state->handlers[len++] = ex;
262  }
263  }
264  state->handlers[len] = NULL;
265 
266  /* init variable types at the start of this block */
267  typevector_copy_inplace(state->bptr->inlocals, jd->var, state->numlocals);
268 
269  DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->invars,
270  state->bptr->indepth));
271  DOLOG(typevector_print(stdout, jd->var, state->numlocals));
273 
274  /* loop over the instructions */
275  len = state->bptr->icount;
276  state->iptr = state->bptr->iinstr;
277  while (--len >= 0) {
278  TYPECHECK_COUNT(stat_ins);
279 
280  iptr = state->iptr;
281 
282  DOLOG(typevector_print(stdout, jd->var, state->numlocals));
284  DOLOG(show_icmd(jd, state->iptr, false, SHOW_STACK)); OLD_LOGNL; OLD_LOGFLUSH;
285 
286  opcode = iptr->opc;
287  maythrow = false;
288 
289  switch (opcode) {
290 
291  /* include generated code for ICMDs verification */
292 
293 #define TYPECHECK_TYPEINFERER
294 #define STATE state
295 #define METHOD (state->m)
296 #define IPTR iptr
297 #define BPTR (state->bptr)
298 #include <typecheck-typeinferer-gen.inc>
299 #undef STATE
300 #undef METHOD
301 #undef IPTR
302 #undef BPTR
303 #undef TYPECHECK_TYPEINFERER
304 
305  default:
306  vm_abort("missing ICMD in type inferer: %d\n", opcode);
307  }
308 
309  /* reach exception handlers for this instruction */
310 
311  if (maythrow) {
312  TYPECHECK_COUNT(stat_ins_maythrow);
313  TYPECHECK_MARK(state->stat_maythrow);
314  OLD_LOG("reaching exception handlers");
315  i = 0;
316  while (state->handlers[i]) {
317  TYPECHECK_COUNT(stat_handlers_reached);
318  if (state->handlers[i]->catchtype.any)
319  VAR(state->exinvars)->typeinfo.typeclass = state->handlers[i]->catchtype;
320  else
321  VAR(state->exinvars)->typeinfo.typeclass.cls = class_java_lang_Throwable;
322  if (!typestate_reach(state,
323  state->handlers[i]->handler,
324  &(state->exinvars), jd->var, 1))
325  return false;
326  i++;
327  }
328  }
329 
330  OLD_LOG("\t\tnext instruction");
331  state->iptr++;
332  } /* while instructions */
333 
334  OLD_LOG("instructions done");
335  OLD_LOGSTR("RESULT=> ");
336  DOLOG(typecheck_print_vararray(stdout, jd, state->bptr->outvars,
337  state->bptr->outdepth));
338  DOLOG(typevector_print(stdout, jd->var, state->numlocals));
340 
341  /* propagate stack and variables to the following block */
342  if (!superblockend) {
343  OLD_LOG("reaching following block");
344  tbptr = state->bptr->next;
345  while (tbptr->state == basicblock::DELETED) {
346  tbptr = tbptr->next;
347  }
348  if (!typestate_reach(state,tbptr,state->bptr->outvars, jd->var,
349  state->bptr->outdepth))
350  return false;
351  }
352 
353  return true;
354 }
355 
356 
358 {
359  methodinfo *meth;
360  codegendata *cd;
361  varinfo *savedlocals;
362  verifier_state state; /* current state of the verifier */
363 
364  /* get required compiler data */
365 
366  meth = jd->m;
367  cd = jd->cd;
368 
369  /* some logging on entry */
370 
371 
372  OLD_LOGSTR("\n==============================================================================\n");
373  DOLOG( show_method(jd, SHOW_STACK) );
374  OLD_LOGSTR("\n==============================================================================\n");
375  OLD_LOGMETHOD("Entering type inference: ",cd->method);
376 
377  /* initialize the verifier state */
378 
379  state.m = meth;
380  state.jd = jd;
381  state.cd = cd;
382  state.basicblockcount = jd->basicblockcount;
383  state.basicblocks = jd->basicblocks;
384  state.savedindices = NULL;
385  state.savedinvars = NULL;
386 
387  /* check that the basicblock numbers are valid */
388 
389 #if !defined(NDEBUG)
391 #endif
392 
393  /* check if this method is an instance initializer method */
394 
395  state.initmethod = (state.m->name == utf8::init);
396 
397  /* initialize the basic block flags for the following CFG traversal */
398 
400 
401  /* number of local variables */
402 
403  /* In <init> methods we use an extra local variable to indicate whether */
404  /* the 'this' reference has been initialized. */
405  /* TYPE_VOID...means 'this' has not been initialized, */
406  /* TYPE_INT....means 'this' has been initialized. */
407 
408  state.numlocals = state.jd->localcount;
409  state.validlocals = state.numlocals;
410  if (state.initmethod)
411  state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
412 
413  /* allocate the buffer of active exception handlers */
414 
416 
417  /* save local variables */
418 
419  savedlocals = (varinfo*) DumpMemory::allocate(sizeof(varinfo) * state.numlocals);
420  MCOPY(savedlocals, jd->var, varinfo, state.numlocals);
421 
422  /* initialized local variables of first block */
423 
424  if (!typecheck_init_locals(&state, false))
425  return false;
426 
427  /* initialize invars of exception handlers */
428 
429  state.exinvars = state.numlocals;
430  VAR(state.exinvars)->type = TYPE_ADR;
431  VAR(state.exinvars)->typeinfo.init_class(class_java_lang_Throwable); /* changed later */
432 
433  OLD_LOG("Exception handler stacks set.\n");
434 
435  // loop while there are still blocks to be checked
436  do {
437  TYPECHECK_COUNT(count_iterations);
438 
439  state.repeat = false;
440  state.bptr = state.basicblocks;
441 
442  for (; state.bptr; state.bptr = state.bptr->next) {
443  OLD_LOGSTR1("---- BLOCK %04d, ", state.bptr->nr);
444  OLD_LOGSTR1("blockflags: %d\n", state.bptr->state);
445  OLD_LOGFLUSH;
446 
447  // verify reached block
448  if (state.bptr->state == basicblock::TYPECHECK_REACHED) {
449  if (!handle_basic_block(&state))
450  return false;
451  }
452  } // for blocks
453 
454  OLD_LOGIF(state.repeat,"state.repeat == true");
455  } while (state.repeat);
456 
457  /* statistics */
458  /* reset the flags of blocks we haven't reached */
459 
460  typecheck_reset_state(&state);
461 
462  /* restore locals */
463 
464  MCOPY(jd->var, savedlocals, varinfo, state.numlocals);
465 
466  /* everything's ok */
467 
468  OLD_LOGimp("exiting type inference");
469  return true;
470 }
471 
472 
473 /*
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  * ---------------------------------------------------------------------
478  * Local variables:
479  * mode: c++
480  * indent-tabs-mode: t
481  * c-basic-offset: 4
482  * tab-width: 4
483  * End:
484  * vim:noexpandtab:sw=4:ts=4:
485  */
Utf8String name
Definition: method.hpp:71
s4 exceptiontablelength
Definition: jit.hpp:167
#define OLD_LOG(str)
#define TYPECHECK_COUNT(cnt)
exception_entry ** handlers
static bool handle_invocation(verifier_state *state)
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 * invars
Definition: jit.hpp:323
basicblock * next
Definition: jit.hpp:337
s4 outdepth
Definition: jit.hpp:326
varinfo * var
Definition: jit.hpp:148
#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_basic_block(verifier_state *state)
#define OLD_LOGSTR1(str, a)
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 vm_abort(const char *text,...)
Definition: vm.cpp:2586
void typevector_print(FILE *file, const varinfo *vec, int size)
Definition: typeinfo.cpp:2289
void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
Definition: show.cpp:449
codegendata * cd
static bool handle_builtin(verifier_state *state)
#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
void typevector_copy_inplace(varinfo *src, varinfo *dst, int size)
Definition: typeinfo.cpp:111
MIIterator i
int32_t s4
Definition: types.hpp:45
s4 * outvars
Definition: jit.hpp:324
exception_entry * down
Definition: jit.hpp:240
#define DOLOG(code)
Definition: inline.cpp:116
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
#define OLD_LOGSTR(str)
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
static bool handle_multianewarray(verifier_state *state)
bool typecheck_infer_types(jitdata *jd)
classinfo * class_java_lang_Throwable
Definition: globals.cpp:43
static bool handle_fieldaccess(verifier_state *state, varinfo *instance, varinfo *value)
#define OLD_LOGMETHOD(str, m)
methodinfo * method