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