CACAO
typecheck-stackbased.cpp
Go to the documentation of this file.
1 /* src/vm/jit/verify/typecheck-stackbased.c - stack-based verifier
2 
3  Copyright (C) 1996-2014
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 #include "config.h"
27 
28 #include <assert.h>
29 
30 #include "vm/method.hpp"
31 #include "vm/types.hpp"
32 
33 #include "mm/memory.hpp"
34 #include "mm/dumpmemory.hpp"
35 
36 #include "vm/array.hpp"
37 #include "vm/descriptor.hpp"
38 #include "vm/exceptions.hpp"
39 #include "vm/field.hpp"
40 #include "vm/global.hpp"
41 #include "vm/globals.hpp"
42 #include "vm/primitive.hpp"
43 
44 #include "vm/jit/builtin.hpp"
45 #include "vm/jit/parse.hpp"
46 #include "vm/jit/show.hpp"
47 #include "vm/jit/stack.hpp"
50 
51 
52 /* this #if runs over the whole file: */
53 #if defined(ENABLE_VERIFIER)
54 
56 
57 #if defined(TYPECHECK_VERBOSE)
58 static void typecheck_stackbased_show_state(verifier_state *state,
59  typedescriptor *stack,
60  typedescriptor *stackfloor,
61  bool showins);
62 #endif
63 
64 
65 #define CHECK_STACK_DEPTH(d) \
66  if (((u1*)stack - (u1*)stackfloor) \
67  < (((d)-1) * (int)sizeof(verifier_slot_t))) \
68  goto throw_stack_underflow;
69 
70 /* XXX don't need to check against ACONST for every ICMD */
71 #define CHECK_STACK_SPACE(d) \
72  if (((u1*)STATE->stackceiling - (u1*)stack) \
73  < (((d)+1) * (int)sizeof(verifier_slot_t))) \
74  if (STATE->iptr->opc != ICMD_ACONST \
75  || INSTRUCTION_MUST_CHECK(STATE->iptr)) \
76  goto throw_stack_overflow;
77 
78 #define CHECK_STACK_TYPE(s, t) \
79  if ((s).type != (t)) \
80  goto throw_stack_type_error;
81 
82 /* XXX inefficient */
83 #define CHECK_LOCAL_TYPE(index, t) \
84  do { \
85  if (state.locals[(index)].type != (t)) \
86  goto throw_local_type_error; \
87  if (STATE->topjsr) \
88  STATE->topjsr->usedlocals[(index)] = 1; \
89  if (STATE->topjsr && IS_2_WORD_TYPE(t)) \
90  STATE->topjsr->usedlocals[(index) + 1] = 1; \
91  } while(0)
92 
93 /* XXX inefficient */
94 #define STORE_LOCAL(t, index) \
95  do { \
96  state.locals[(index)].type = (t); \
97  if ((index) && IS_2_WORD_TYPE(state.locals[(index)-1].type)) \
98  state.locals[(index-1)].type = TYPE_VOID; \
99  if (STATE->topjsr) \
100  STATE->topjsr->usedlocals[(index)] = 1; \
101  } while (0)
102 
103 /* XXX inefficient */
104 #define STORE_LOCAL_2_WORD(t, index) \
105  do { \
106  STORE_LOCAL(t, index); \
107  state.locals[(index)+1].type = TYPE_VOID; \
108  if (STATE->topjsr) \
109  STATE->topjsr->usedlocals[(index)] = 1; \
110  } while (0)
111 
112 #define VERIFY_ERROR_ret(msg,ret) \
113  do { \
114  OLD_LOG1("VerifyError: %s", msg); \
115  exceptions_throw_verifyerror(STATE->m, msg); \
116  return ret; \
117  } while (0)
118 
119 #define VERIFY_ERROR(msg) VERIFY_ERROR_ret(msg,false)
120 
121 #define IS_CAT1(slot) \
122  ((slot).type != TYPE_VOID && !IS_2_WORD_TYPE((slot).type))
123 
124 #define IS_CAT2(slot) \
125  ((slot).type != TYPE_VOID && IS_2_WORD_TYPE((slot).type))
126 
127 #define CHECK_CAT1(slot) \
128  do { \
129  if (!IS_CAT1(slot)) \
130  goto throw_stack_category_error; \
131  } while (0)
132 
133 #define CHECK_CAT2(slot) \
134  do { \
135  if (!IS_CAT2(slot)) \
136  goto throw_stack_category_error; \
137  } while (0)
138 
139 #define COPY_SLOT(s, d) \
140  do { (d) = (s); } while (0)
141 
142 #define REACH_BLOCK(target) \
143  do { \
144  if (!typecheck_stackbased_reach(STATE, (target), stack, \
145  (stack - stackfloor) + 1)) \
146  return false; \
147  } while (0)
148 
149 #define REACH(target) \
150  do { \
151  REACH_BLOCK((target).block); \
152  } while (0)
153 
154 #undef TYPECHECK_INT
155 #undef TYPECHECK_LNG
156 #undef TYPECHECK_FLT
157 #undef TYPECHECK_DBL
158 #undef TYPECHECK_ADR
159 
160 /* XXX should reuse typevector code */
162  typedescriptor_t *dst,
163  typedescriptor_t *y,
164  int size)
165 {
166  bool changed = false;
168 
169  typedescriptor_t *a = dst;
170  typedescriptor_t *b = y;
171  while (size--) {
172  if (a->type != TYPE_VOID && a->type != b->type) {
173  a->type = TYPE_VOID;
174  changed = true;
175  }
176  else if (a->type == TYPE_ADR) {
177  if (a->typeinfo.is_primitive()) {
178  /* 'a' is a returnAddress */
180  {
181  a->type = TYPE_VOID;
182  changed = true;
183  }
184  }
185  else {
186  /* 'a' is a reference */
187  if (b->typeinfo.is_primitive()) {
188  a->type = TYPE_VOID;
189  changed = true;
190  }
191  else {
192  /* two reference types are merged. There cannot be */
193  /* a merge error. In the worst case we get j.l.O. */
194  r = a->typeinfo.merge(m, &(b->typeinfo));
195  if (r == typecheck_FAIL)
196  return r;
197  changed |= r;
198  }
199  }
200  }
201  a++;
202  b++;
203  }
204  return (typecheck_result) changed;
205 }
206 
208  basicblock *destblock,
210  s4 stackdepth)
211 {
212  s4 i;
213  s4 destidx;
214  typedescriptor_t *stackfloor;
216  typedescriptor_t *dp;
218  bool changed = false;
219 
220  destidx = destblock->nr;
221 
222  if (stackdepth != state->indepth[destidx]) {
223  exceptions_throw_verifyerror(state->m, "Stack depth mismatch");
224  return typecheck_FAIL;
225  }
226 
227  stackfloor = stack - (stackdepth - 1);
228 
229  sp = stackfloor;
230  dp = state->startstack + (destidx * state->m->maxstack);
231 
232  for (i=0; i<stackdepth; ++i, ++sp, ++dp) {
233  if (sp->type != dp->type) {
234  exceptions_throw_verifyerror(state->m, "Mismatched stack types");
235  return typecheck_FAIL;
236  }
237  if (dp->type == TYPE_ADR) {
238  if (dp->typeinfo.is_primitive()) {
239  /* dp has returnAddress type */
240  if (sp->typeinfo.is_primitive()) {
241  if (dp->typeinfo.returnaddress() != sp->typeinfo.returnaddress()) {
242  exceptions_throw_verifyerror(state->m, "Mismatched stack types");
243  return typecheck_FAIL;
244  }
245  }
246  else {
247  exceptions_throw_verifyerror(state->m,"Merging returnAddress with reference");
248  return typecheck_FAIL;
249  }
250  }
251  else {
252  /* dp has reference type */
253  if (sp->typeinfo.is_primitive()) {
254  exceptions_throw_verifyerror(state->m,"Merging reference with returnAddress");
255  return typecheck_FAIL;
256  }
257  r = dp->typeinfo.merge(state->m, &(sp->typeinfo));
258  if (r == typecheck_FAIL)
259  return r;
260  changed |= r;
261  }
262  }
263  }
264 
265  dp = state->startlocals + (destidx * state->numlocals);
266  r = typecheck_stackbased_merge_locals(state->m, dp, state->locals, state->numlocals);
267  if (r == typecheck_FAIL)
268  return r;
269  changed |= r;
270 
271  return (typecheck_result) changed;
272 }
273 
275  basicblock *destblock,
277  s4 stackdepth)
278 {
279  bool changed = false;
281 
282  assert(destblock);
283 
284  if (destblock->state == basicblock::TYPECHECK_UNDEF) {
285  /* The destblock has never been reached before */
286 
287  TYPECHECK_COUNT(stat_copied);
288  OLD_LOG1("block L%03d reached first time",destblock->nr); OLD_LOGSTR("\t");
289  DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
290 
291  state->indepth[destblock->nr] = stackdepth;
292 
293  MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
294  stack - (stackdepth - 1),
296  stackdepth);
297 
298  MCOPY(state->startlocals + (destblock->nr * state->numlocals),
299  state->locals,
301  state->numlocals);
302 
303  changed = true;
304  }
305  else {
306  /* The destblock has already been reached before */
307 
308  TYPECHECK_COUNT(stat_merged);
309  OLD_LOG1("block L%03d reached before", destblock->nr); OLD_LOGSTR("\t");
310  DOLOG( typecheck_stackbased_show_state(state, stack, stack - (stackdepth - 1), false); );
311 
312  r = typecheck_stackbased_merge(state, destblock, stack, stackdepth);
313  if (r == typecheck_FAIL)
314  return false;
315  changed = r;
316 
317  TYPECHECK_COUNTIF(changed,stat_merging_changed);
318  }
319 
320  if (changed) {
321  OLD_LOG("\tchanged!");
323  /* XXX is this check ok? */
324  if (destblock->nr <= state->bptr->nr) {
325  OLD_LOG("\tREPEAT!");
326  state->repeat = true;
327  }
328  }
329  return true;
330 }
331 
332 
333 /* typecheck_stackbased_verify_fieldaccess *************************************
334 
335  Verify an ICMD_{GET,PUT}{STATIC,FIELD}
336 
337  IN:
338  state............the current state of the verifier
339  instance.........the instance slot, or NULL
340  value............the value slot, or NULL
341  stack............stack after popping the arguments
342 
343  RETURN VALUE:
344  stack pointer....successful verification,
345  NULL.............an exception has been thrown.
346 
347 *******************************************************************************/
348 
350  verifier_state *state,
351  typedescriptor_t *instance,
352  typedescriptor_t *value,
354 {
355  //jitdata *jd;
356 
357  //jd = state->jd;
358 
359 #define TYPECHECK_STACKBASED
360 #define EXCEPTION do { return NULL; } while (0)
361 #define STATE state
362 #undef VERIFY_ERROR
363 #define VERIFY_ERROR(msg) VERIFY_ERROR_ret(msg,NULL)
364 #include <typecheck-fields.inc>
365 #undef EXCEPTION
366 #undef STATE
367 #undef TYPECHECK_STACKBASED
368 #undef VERIFY_ERROR
369 #define VERIFY_ERROR(msg) VERIFY_ERROR_ret(msg,false)
370 
371  return stack;
372 
373 throw_stack_overflow:
374  OLD_LOG("STACK OVERFLOW!");
375  exceptions_throw_verifyerror(state->m, "Stack size too large");
376  return NULL;
377 }
378 
381  typedescriptor_t *stackfloor)
382 {
383  s4 paramslots;
384  methoddesc *md;
385  typedescriptor_t *dv;
386 
387  /* check stack depth */
388 
389  /* XXX parse params */
390 
391  INSTRUCTION_GET_METHODDESC(state->iptr, md);
392 
393  paramslots = md->paramslots;
394 
395  if ((stack - stackfloor) + 1 < paramslots) {
397  "Trying to pop operand of an empty stack");
398  return false;
399  }
400 
401  dv = stack - (paramslots - 1);
402 
403 #define TYPECHECK_STACKBASED
404 #define OP1 dv
405 #include <typecheck-invoke.inc>
406 #undef OP1
407 #undef TYPECHECK_STACKBASED
408 
409  return true;
410 }
411 
414  typedescriptor_t *stackfloor)
415 {
416  s4 paramslots;
417  typedescriptor_t *dv;
418 
419  /* check stack depth */
420 
421  /* XXX parse params */
422 
423  paramslots = state->iptr->sx.s23.s3.bte->md->paramslots;
424 
425  if ((stack - stackfloor) + 1 < paramslots) {
427  "Trying to pop operand of an empty stack");
428  return false;
429  }
430 
431  dv = stack - (paramslots - 1);
432 
433 #define TYPECHECK_STACKBASED
434 #define OP1 dv
435 #define TYPECHECK_INT(s) CHECK_STACK_TYPE(*(s), TYPE_INT)
436 #define TYPECHECK_ADR(s) CHECK_STACK_TYPE(*(s), TYPE_ADR)
437 #define TYPECHECK_LNG(s) CHECK_STACK_TYPE(*(s), TYPE_LNG)
438 #define TYPECHECK_FLT(s) CHECK_STACK_TYPE(*(s), TYPE_FLT)
439 #define TYPECHECK_DBL(s) CHECK_STACK_TYPE(*(s), TYPE_DBL)
440 #include <typecheck-builtins.inc>
441 #undef OP1
442 #undef TYPECHECK_STACKBASED
443 
444  return true;
445 
446 throw_stack_type_error:
447  exceptions_throw_verifyerror(state->m, "Wrong type on stack"); /* XXX */
448  return false;
449 }
450 
453  typedescriptor_t *stackfloor)
454 {
455  /* XXX recombine with verify_multianewarray */
456 
457  classinfo *arrayclass;
458  arraydescriptor *desc;
459  s4 i;
461  typedescriptor_t *dst;
462 
463  /* destination slot */
464 
465  i = state->iptr->s1.argcount;
466 
467  dst = stack - (i-1);
468 
469  /* check the array lengths on the stack */
470 
471  if ((stack - stackfloor) + 1 < i) {
473  "Trying to pop operand of an empty stack");
474  return false;
475  }
476 
477  if (i < 1)
478  TYPECHECK_VERIFYERROR_bool("Illegal dimension argument");
479 
480  for (sp = dst; sp <= stack; ++sp) {
481  if (sp->type != TYPE_INT) {
483  return false;
484  }
485  }
486 
487  /* check array descriptor */
488 
489  if (INSTRUCTION_IS_RESOLVED(state->iptr)) {
490  /* the array class reference has already been resolved */
491  arrayclass = state->iptr->sx.s23.s3.c.cls;
492  if (!arrayclass)
493  TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with unlinked class");
494  if ((desc = arrayclass->vftbl->arraydesc) == NULL)
495  TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
496  if (desc->dimension < state->iptr->s1.argcount)
497  TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
498 
499  /* set the array type of the result */
500  dst->typeinfo.init_class(arrayclass);
501  }
502  else {
503  const char *p;
504  constant_classref *cr;
505 
506  /* the array class reference is still unresolved */
507  /* check that the reference indicates an array class of correct dimension */
508  cr = state->iptr->sx.s23.s3.c.ref;
509  i = 0;
510  p = cr->name.begin();
511  while (p[i] == '[')
512  i++;
513  /* { the dimension of the array class == i } */
514  if (i < 1)
515  TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY with non-array class");
516  if (i < state->iptr->s1.argcount)
517  TYPECHECK_VERIFYERROR_bool("MULTIANEWARRAY dimension to high");
518 
519  /* set the array type of the result */
520  if (!dst->typeinfo.init_class(cr))
521  return false;
522  }
523 
524  /* everything ok */
525  return true;
526 
527 }
528 
530  basicblock *bptr)
531 {
533 
534  for (jc = jsr->callers; jc; jc = jc->next)
535  if (jc->callblock == bptr)
536  return;
537 
539  jc->next = jsr->callers;
540  jc->callblock = bptr;
541  jsr->callers = jc;
542 }
543 
546  typedescriptor_t *stackfloor)
547 {
548  typecheck_jsr_t *jsr;
549  basicblock *tbptr;
550  //jitdata *jd;
551  s4 i;
552 
553  //jd = state->jd;
554 
555  tbptr = state->iptr->sx.s23.s3.jsrtarget.block;
556  jsr = state->jsrinfos[tbptr->nr];
557 
558  if (jsr && tbptr->state == basicblock::FINISHED) {
559 
560  OLD_LOG1("another JSR to analysed subroutine L%03d", tbptr->nr);
561  if (jsr->active) {
562  exceptions_throw_verifyerror(state->m, "Recursive JSR");
563  return NULL;
564  }
565 
566  assert(jsr->callers);
567  assert(jsr->callers->callblock);
568 
569  /* copy the stack of the RET edge */
570 
571  MCOPY(stackfloor, jsr->retstack, typedescriptor_t, jsr->retdepth);
572  stack = stackfloor + (jsr->retdepth - 1);
573 
574  /* copy variables that were used in the subroutine from the RET edge */
575 
576  for (i=0; i<state->numlocals; ++i)
577  if (jsr->usedlocals[i])
578  state->locals[i] = jsr->retlocals[i];
579 
580  /* reach the following block */
581 
582  if (!typecheck_stackbased_reach(state, state->bptr->next, stack,
583  (stack - stackfloor) + 1))
584  return NULL;
585  }
586  else {
587  if (!jsr) {
588  OLD_LOG1("first JSR to block L%03d", tbptr->nr);
589 
591  state->jsrinfos[tbptr->nr] = jsr;
592  jsr->callers = NULL;
593  jsr->blockflags = (char*) DumpMemory::allocate(sizeof(char) * state->basicblockcount);
594  jsr->retblock = NULL;
595  jsr->start = tbptr;
596  jsr->usedlocals = (char*) DumpMemory::allocate(sizeof(char) * state->numlocals);
597  MZERO(jsr->usedlocals, char, state->numlocals);
600  jsr->retdepth = 0;
601  }
602  else {
603  OLD_LOG1("re-analysing JSR to block L%03d", tbptr->nr);
604  }
605 
606  jsr->active = true;
607  jsr->next = state->topjsr;
608  state->topjsr = jsr;
609 
610  assert(state->iptr->sx.s23.s3.jsrtarget.block->state == basicblock::TYPECHECK_REACHED);
611 
612  tbptr->state = basicblock::FINISHED;
613 
614  for (tbptr = state->basicblocks; tbptr != NULL; tbptr = tbptr->next) {
615  jsr->blockflags[tbptr->nr] = tbptr->state;
616 
617  if (tbptr->state == basicblock::TYPECHECK_REACHED)
618  tbptr->state = basicblock::FINISHED;
619  }
620 
621  state->iptr->sx.s23.s3.jsrtarget.block->state = basicblock::TYPECHECK_REACHED;
622  }
623 
624  /* register this block as a caller, if not already done */
625 
627 
628  return stack;
629 }
630 
633  typedescriptor_t *stackfloor)
634 {
635  basicblock *tbptr;
636  typecheck_jsr_caller_t *jsrcaller;
637  typecheck_jsr_t *jsr;
638  s4 i;
639 
640  /* get the subroutine we are RETurning from */
641 
642  tbptr = (basicblock*) state->locals[state->iptr->s1.varindex].typeinfo.returnaddress();
643  if (tbptr == NULL) {
644  exceptions_throw_verifyerror(state->m, "Illegal RET");
645  return false;
646  }
647 
648  OLD_LOG1("RET from subroutine L%03d", tbptr->nr);
649  jsr = state->jsrinfos[tbptr->nr];
650  assert(jsr);
651 
652  /* check against recursion */
653 
654  if (!jsr->active) {
655  exceptions_throw_verifyerror(state->m, "RET outside of local subroutine");
656  return false;
657  }
658 
659  /* check against multiple RETs for one subroutine */
660 
661  if (jsr->retblock && jsr->retblock != state->bptr) {
662  exceptions_throw_verifyerror(state->m, "Multiple RETs from local subroutine");
663  return false;
664  }
665 
666  /* store data-flow of the RET edge */
667 
668  jsr->retblock = state->bptr;
669  jsr->retdepth = (stack - stackfloor) + 1;
670  MCOPY(jsr->retstack, stackfloor, typedescriptor_t, jsr->retdepth);
671  MCOPY(jsr->retlocals, state->locals, typedescriptor_t, state->numlocals);
672 
673  /* invalidate the returnAddress used by this RET */
674  /* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
675 
676  for (i=0; i<state->numlocals; ++i) {
677  typedescriptor_t *lc = &(jsr->retlocals[i]);
678  if (lc->is_returnaddress())
679  if (lc->typeinfo.returnaddress() == tbptr) {
680  OLD_LOG1("invalidating returnAddress in local %d", i);
681  lc->typeinfo.init_returnaddress(NULL);
682  }
683  }
684 
685  /* touch all callers of the subroutine, so they are analysed again */
686 
687  for (jsrcaller = jsr->callers; jsrcaller != NULL; jsrcaller = jsrcaller->next) {
688  tbptr = jsrcaller->callblock;
689  OLD_LOG1("touching caller L%03d from RET", tbptr->nr);
690  assert(jsr->blockflags[tbptr->nr] >= basicblock::FINISHED);
691  jsr->blockflags[tbptr->nr] = basicblock::TYPECHECK_REACHED; /* XXX repeat? */
692  }
693 
694  return true;
695 }
696 
698 {
699  register verifier_slot_t *stack;
700  verifier_slot_t *stackfloor;
701  s4 len;
702  methoddesc *md;
703  bool maythrow;
704  bool superblockend;
705  verifier_slot_t temp;
706  branch_target_t *table;
707  lookup_target_t *lookup;
708  s4 i;
710  verifier_slot_t *dst;
711  verifier_state state;
712  basicblock *tbptr;
713  exception_entry *ex;
714  typedescriptor_t exstack;
715  s4 skip = 0;
716 
717  DOLOG( show_method(jd, SHOW_PARSE); );
718 
719  /* initialize verifier state */
720 
721  state.jd = jd;
722  state.m = jd->m;
723  state.cd = jd->cd;
724  state.basicblocks = jd->basicblocks;
725  state.basicblockcount = jd->basicblockcount;
726  state.topjsr = NULL;
727 # define STATE (&state)
728 
729  /* check that the basicblock numbers are valid */
730 
731 #if !defined(NDEBUG)
733 #endif
734 
735  /* check if this method is an instance initializer method */
736 
737  state.initmethod = (state.m->name == utf8::init);
738 
739  /* allocate parameter descriptors if necessary */
740 
741  state.m->parseddesc->params_from_paramtypes(state.m->flags);
742 
743  /* allocate the stack buffers */
744 
745  stackfloor = (verifier_slot_t*) DumpMemory::allocate(sizeof(verifier_slot_t) * (state.m->maxstack + 1));
746  state.stackceiling = stackfloor + state.m->maxstack;
747  stack = stackfloor - 1;
748  state.indepth = (s4*) DumpMemory::allocate(sizeof(s4) * state.basicblockcount);
750 
751  /* allocate the local variables buffers */
752 
753  state.numlocals = state.m->maxlocals;
754  state.validlocals = state.m->maxlocals;
755  if (state.initmethod)
756  state.numlocals++; /* extra marker variable */
757 
760 
761  /* allocate the buffer of active exception handlers */
762 
764 
765  /* initialize instack of exception handlers */
766 
767  exstack.type = TYPE_ADR;
768  exstack.typeinfo.init_class(class_java_lang_Throwable); /* changed later */
769 
770  OLD_LOG("Exception handler stacks set.\n");
771 
772  /* initialize jsr info buffer */
773 
776 
777  /* initialize stack of first block */
778 
779  state.indepth[0] = 0;
780 
781  /* initialize locals of first block */
782 
783  /* if this is an instance method initialize the "this" ref type */
784 
785  if (!(state.m->flags & ACC_STATIC)) {
786  if (state.validlocals < 1)
787  VERIFY_ERROR("Not enough local variables for method arguments");
788  dst = state.startlocals;
789  dst->type = TYPE_ADR;
790  if (state.initmethod)
791  dst->typeinfo.init_newobject(NULL);
792  else
793  dst->typeinfo.init_class(state.m->clazz);
794 
795  skip = 1;
796  }
797 
798  OLD_LOG("'this' argument set.\n");
799 
801  state.m->parseddesc,
802  state.validlocals, true, skip, &state.returntype);
803  if (len < 0)
804  return false;
805 
806  /* set remaining locals to void */
807 
808  for (i = skip + len; i<state.numlocals; ++i)
809  state.startlocals[i].type = TYPE_VOID;
810 
811  /* initialize block flags */
812 
814 
815  /* iterate until fixpoint reached */
816 
817  do {
818 
819  state.repeat = false;
820 
821  /* iterate over the basic blocks */
822 
823  for (state.bptr = state.basicblocks; state.bptr != NULL; state.bptr = state.bptr->next) {
824 
826  continue;
827 
828  DOLOG( show_basicblock(jd, state.bptr, SHOW_PARSE); );
829 
830  /* mark this block as analysed */
831 
833 
834  /* determine the active exception handlers for this block */
835  /* XXX could use a faster algorithm with sorted lists or */
836  /* something? */
837  /* XXX reuse code from variables based verifer? */
838  len = 0;
839  for (ex = STATE->jd->exceptiontable; ex ; ex = ex->down) {
840  if ((ex->start->nr <= STATE->bptr->nr) && (ex->end->nr > STATE->bptr->nr)) {
841  OLD_LOG1("\tactive handler L%03d", ex->handler->nr);
842  STATE->handlers[len++] = ex;
843  }
844  }
845  STATE->handlers[len] = NULL;
846 
847  /* initialize the locals */
848 
849  MCOPY(state.locals,
850  state.startlocals + (state.bptr->nr * state.numlocals),
851  verifier_slot_t, state.numlocals);
852 
853  /* initialize the stack */
854 
855  len = state.indepth[state.bptr->nr];
856 
857  MCOPY(stackfloor,
858  state.startstack + (state.bptr->nr * state.m->maxstack),
859  verifier_slot_t, len);
860 
861  stack = stackfloor + (len - 1);
862 
863  /* iterate over the instructions in this block */
864 
865  state.iptr = state.bptr->iinstr;
866  len = state.bptr->icount;
867 
868  superblockend = false;
869 
870  for (; len--; state.iptr++) {
871 
872  maythrow = false;
873 
874  OLD_LOGNL;
875  DOLOG( typecheck_stackbased_show_state(&state, stack, stackfloor, true); );
876 
877  switch (state.iptr->opc) {
878 #define TYPECHECK_STACKBASED 1
879 #define STATE (&state)
880 #define IPTR state.iptr
881 #define BPTR state.bptr
882 #define METHOD state.m
883 #define LOCAL_SLOT(index) (state.locals + (index))
884 #define EXCEPTION \
885  do { \
886  OLD_LOG("EXCEPTION THROWN!\n"); \
887  return false; \
888  } while (0)
889 
890 #include <typecheck-stackbased-gen.inc>
891 #undef TYPECHECK_STACKBASED
892  }
893 
894  /* reach exception handlers for this instruction */
895 
896  if (maythrow) {
897  TYPECHECK_COUNT(stat_ins_maythrow);
898  TYPECHECK_MARK(STATE->stat_maythrow);
899  OLD_LOG("\treaching exception handlers");
900  i = 0;
901  while (STATE->handlers[i]) {
902  TYPECHECK_COUNT(stat_handlers_reached);
903  if (STATE->handlers[i]->catchtype.any)
904  exstack.typeinfo.typeclass = STATE->handlers[i]->catchtype;
905  else
908  STATE,
909  STATE->handlers[i]->handler,
910  &exstack, 1))
911  EXCEPTION;
912  i++;
913  }
914  }
915  }
916 
917  /* propagate types to the following block */
918 
919  if (!superblockend) {
920  if (!typecheck_stackbased_reach(&state, state.bptr->next,
921  stack, stack - stackfloor + 1))
922  EXCEPTION;
923  }
924  } /* end loop over blocks */
925 
926  while (!state.repeat && state.topjsr) {
927  OLD_LOG1("done analysing subroutine L%03d", state.topjsr->start->nr);
928 
929  /* propagate down used locals */
930 
931  if (state.topjsr->next) {
932  for (i=0; i<state.numlocals; ++i)
933  state.topjsr->next->usedlocals[i] |= state.topjsr->usedlocals[i];
934  }
935 
936  /* restore REACHED flags */
937 
938  for (tbptr = state.basicblocks; tbptr != NULL; tbptr = tbptr->next) {
939  assert(tbptr->state != basicblock::TYPECHECK_REACHED);
940  if (state.topjsr->blockflags[tbptr->nr] == basicblock::TYPECHECK_REACHED) {
942  state.repeat = true;
943  }
944  }
945 
946  /* dactivate the subroutine */
947 
948  state.topjsr->active = false;
949  state.topjsr = state.topjsr->next;
950  }
951  } while (state.repeat);
952 
953  /* reset block flags */
954 
955  typecheck_reset_state(&state);
956 
957  OLD_LOG("typecheck_stackbased successful");
958 
959  return true;
960 
961 throw_stack_underflow:
962  OLD_LOG("STACK UNDERFLOW!");
963  exceptions_throw_verifyerror(state.m, "Unable to pop operand off an empty stack");
964  return false;
965 
966 throw_stack_overflow:
967  OLD_LOG("STACK OVERFLOW!");
968  exceptions_throw_verifyerror(state.m, "Stack size too large");
969  return false;
970 
971 throw_stack_type_error:
972  OLD_LOG("STACK TYPE ERROR!");
973  exceptions_throw_verifyerror(state.m, "Mismatched stack types");
974  return false;
975 
976 throw_local_type_error:
977  OLD_LOG("LOCAL TYPE ERROR!");
978  exceptions_throw_verifyerror(state.m, "Local variable type mismatch");
979  return false;
980 
981 throw_stack_category_error:
982  OLD_LOG("STACK CATEGORY ERROR!");
983  exceptions_throw_verifyerror(state.m, "Attempt to split long or double on the stack");
984  return false;
985 }
986 
987 
988 #if defined(TYPECHECK_VERBOSE)
989 static void typecheck_stackbased_show_state(verifier_state *state,
991  typedescriptor_t *stackfloor,
992  bool showins)
993 {
995  s4 i;
996 
997  OLD_LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
998  for (sp=stackfloor; sp <= stack; sp++) {
999  OLD_LOGSTR(" ");
1000  DOLOG( typedescriptor_print(stdout, sp); );
1001  }
1002  OLD_LOGSTR(" ] locals [");
1003  for (i=0; i<state->numlocals; ++i) {
1004  OLD_LOGSTR(" ");
1005  DOLOG( typedescriptor_print(stdout, state->locals + i); );
1006  }
1007  OLD_LOGSTR(" ]");
1008  OLD_LOGNL;
1009  if (showins && state->iptr < (state->bptr->iinstr + state->bptr->icount)) {
1010  OLD_LOGSTR("\t");
1011  DOLOG( show_icmd(state->jd, state->iptr, false, SHOW_PARSE); );
1012  OLD_LOGNL;
1013  }
1014 }
1015 #endif
1016 
1017 
1018 #endif /* defined(ENABLE_VERIFIER) */
1019 
1020 
1021 /*
1022  * These are local overrides for various environment variables in Emacs.
1023  * Please do not remove this and leave it at the end of the file, where
1024  * Emacs will automagically detect them.
1025  * ---------------------------------------------------------------------
1026  * Local variables:
1027  * mode: c++
1028  * indent-tabs-mode: t
1029  * c-basic-offset: 4
1030  * tab-width: 4
1031  * End:
1032  * vim:noexpandtab:sw=4:ts=4:
1033  */
void exceptions_throw_verifyerror(methodinfo *m, const char *message,...)
Definition: exceptions.cpp:973
Utf8String name
Definition: method.hpp:71
s4 exceptiontablelength
Definition: jit.hpp:167
static bool typecheck_stackbased_multianewarray(verifier_state *state, typedescriptor_t *stack, typedescriptor_t *stackfloor)
#define OLD_LOG(str)
typeinfo_t typeinfo
Definition: typeinfo.hpp:382
#define TYPECHECK_COUNT(cnt)
void init_class(classinfo *c)
Initialize object type.
Definition: typeinfo.cpp:790
exception_entry ** handlers
void init_newobject(instruction *instr)
Definition: typeinfo.hpp:339
#define EXCEPTION
basicblock * basicblocks
Definition: jit.hpp:141
Definition: jit.hpp:126
#define TYPECHECK_MARK(var)
typedescriptor_t * startstack
State state
Definition: jit.hpp:313
basicblock * next
Definition: jit.hpp:337
typecheck_jsr_t ** jsrinfos
int typedescriptors_init_from_methoddesc(typedescriptor_t *td, methoddesc *desc, int buflen, bool twoword, int startindex, typedescriptor_t *returntype)
Definition: typeinfo.cpp:1088
static bool typecheck_stackbased_ret(verifier_state *state, typedescriptor_t *stack, typedescriptor_t *stackfloor)
int32_t argcount
Definition: instruction.hpp:64
#define SHOW_PARSE
Definition: show.hpp:40
bool typecheck_stackbased(jitdata *jd)
#define show_method(...)
Definition: ssa2.cpp:41
void typecheck_init_state(verifier_state *state, basicblock::State minstate)
codegendata * cd
Definition: jit.hpp:129
int32_t varindex
Definition: instruction.hpp:63
typedescriptor_t * retlocals
#define STATE
basicblock * retblock
typedescriptor_t * locals
#define OLD_LOGSTR1(str, a)
static typecheck_result typecheck_stackbased_merge(verifier_state *state, basicblock *destblock, typedescriptor_t *stack, s4 stackdepth)
static bool typecheck_stackbased_reach(verifier_state *state, basicblock *destblock, typedescriptor_t *stack, s4 stackdepth)
#define OLD_LOG1(str, a)
basicblock * basicblocks
instruction * iinstr
Definition: jit.hpp:319
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
s4 icount
Definition: jit.hpp:318
#define MZERO(ptr, type, num)
Definition: memory.hpp:105
typecheck_result merge(methodinfo *m, const typeinfo_t *t)
functions for merging types
Definition: typeinfo.cpp:1672
void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
Definition: show.cpp:449
codegendata * cd
#define VERIFY_ERROR(msg)
#define OLD_LOGNL
void init_returnaddress(void *adr)
Definition: typeinfo.hpp:298
classinfo * clazz
Definition: method.hpp:80
basicblock * start
Definition: jit.hpp:234
alloc::list< PassInfo::IDTy >::type & stack
basicblock * handler
Definition: jit.hpp:236
static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m, typedescriptor_t *dst, typedescriptor_t *y, int size)
void typecheck_reset_state(verifier_state *state)
typecheck_jsr_caller_t * next
#define TYPECHECK_VERIFYERROR_bool(msg)
s4 maxstack
Definition: method.hpp:83
static bool typecheck_stackbased_verify_invocation(verifier_state *state, typedescriptor_t *stack, typedescriptor_t *stackfloor)
void * returnaddress() const
Definition: typeinfo.hpp:248
MIIterator i
typedescriptor_t verifier_slot_t
bool is_primitive() const
Definition: typeinfo.hpp:242
int32_t s4
Definition: types.hpp:45
s4 maxlocals
Definition: method.hpp:84
typedescriptor_t * startlocals
union instruction::@12 sx
exception_entry * down
Definition: jit.hpp:240
void params_from_paramtypes(s4 mflags)
Definition: descriptor.cpp:877
typedescriptor_t * retstack
arraydescriptor * arraydesc
Definition: vftbl.hpp:101
#define INSTRUCTION_GET_METHODDESC(iptr, md)
#define DOLOG(code)
Definition: inline.cpp:116
s1_operand_t s1
classref_or_classinfo typeclass
Definition: typeinfo.hpp:236
vftbl_t * vftbl
Definition: class.hpp:121
static bool typecheck_stackbased_verify_builtin(verifier_state *state, typedescriptor_t *stack, typedescriptor_t *stackfloor)
byte_iterator begin() const
Definition: utf8.hpp:106
void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
Definition: show.cpp:917
methoddesc * parseddesc
Definition: method.hpp:78
#define sp
Definition: md-asm.hpp:81
typecheck_jsr_t * next
instruction * iptr
methodinfo * m
Definition: jit.hpp:127
basicblock * end
Definition: jit.hpp:235
#define OLD_LOGSTR(str)
static typedescriptor_t * typecheck_stackbased_verify_fieldaccess(verifier_state *state, typedescriptor_t *instance, typedescriptor_t *value, typedescriptor_t *stack)
#define TYPECHECK_COUNTIF(cond, cnt)
static void * allocate(size_t size)
Definition: dumpmemory.hpp:251
typedescriptor_t returntype
s4 nr
Definition: jit.hpp:312
s4 basicblockcount
Definition: jit.hpp:144
bool is_returnaddress() const
Definition: typeinfo.hpp:385
void typedescriptor_print(FILE *file, const typedescriptor_t *td)
Definition: typeinfo.cpp:2283
struct instruction::@12::@13 s23
static typedescriptor_t * typecheck_stackbased_jsr(verifier_state *state, typedescriptor_t *stack, typedescriptor_t *stackfloor)
void jit_check_basicblock_numbers(jitdata *jd)
Definition: jit.cpp:1177
typedescriptor_t * stackceiling
#define INSTRUCTION_IS_RESOLVED(iptr)
Definition: jit.hpp:233
#define MCOPY(dest, src, type, num)
Definition: memory.hpp:103
typecheck_jsr_t * topjsr
s4 flags
Definition: method.hpp:70
void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
const Utf8String name
Definition: references.hpp:48
classinfo * class_java_lang_Throwable
Definition: globals.cpp:43
typecheck_jsr_caller_t * callers
typecheck_result
Definition: typeinfo.hpp:81
static void typecheck_stackbased_add_jsr_caller(typecheck_jsr_t *jsr, basicblock *bptr)