* src/vm/jit/jit.h (INS_FLAG_CLASS): Comment that this flag is also
[cacao.git] / src / vm / jit / verify / icmds.c
1 /* src/vm/jit/verify/icmds.c - ICMD-specific type checking code
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 /* this marker is needed by generate.pl: */
36 /* {START_OF_CODE} */
37
38         /****************************************/
39         /* MOVE/COPY                            */
40
41         /* We just need to copy the typeinfo */
42         /* for slots containing addresses.   */
43
44         /* (These are only used by the variables based verifier.) */
45
46 case ICMD_MOVE: /* {VARIABLESBASED} */
47 case ICMD_COPY: /* {VARIABLESBASED} */
48         TYPECHECK_COUNT(stat_ins_stack);
49         COPYTYPE(IPTR->s1, IPTR->dst);
50         DST->type = OP1->type;
51         break;
52
53         /****************************************/
54         /* LOADING ADDRESS FROM VARIABLE        */
55
56 case ICMD_ALOAD:
57         TYPECHECK_COUNT(stat_ins_aload);
58
59         /* loading a returnAddress is not allowed */
60         if (!TYPEDESC_IS_REFERENCE(*OP1)) {
61                 VERIFY_ERROR("illegal instruction: ALOAD loading non-reference");
62         }
63         TYPEINFO_COPY(OP1->typeinfo,DST->typeinfo);
64         break;
65
66         /****************************************/
67         /* STORING ADDRESS TO VARIABLE          */
68
69 case ICMD_ASTORE:
70         TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
71         break;
72
73         /****************************************/
74         /* LOADING ADDRESS FROM ARRAY           */
75
76 case ICMD_AALOAD:
77         if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
78                 VERIFY_ERROR("illegal instruction: AALOAD on non-reference array");
79
80         if (!typeinfo_init_component(&OP1->typeinfo,&DST->typeinfo))
81                 EXCEPTION;
82         break;
83
84         /****************************************/
85         /* FIELD ACCESS                         */
86
87 case ICMD_PUTFIELD: /* {STACKBASED} */
88         CHECK_STACK_DEPTH(2);
89         if (!IS_CAT1(stack[0])) {
90                 CHECK_STACK_DEPTH(3);
91                 stack -= 1;
92         }
93         CHECK_STACK_TYPE(stack[-1], TYPE_ADR);
94         stack = typecheck_stackbased_verify_fieldaccess(STATE, stack-1, stack, stack-2);
95         if (stack == NULL)
96                 EXCEPTION;
97         break;
98
99 case ICMD_PUTSTATIC: /* {STACKBASED} */
100         CHECK_STACK_DEPTH(1);
101         if (!IS_CAT1(stack[0])) {
102                 /* (stack depth >= 2 is guaranteed) */
103                 stack -= 1;
104         }
105         stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, stack, stack-1);
106         if (stack == NULL)
107                 EXCEPTION;
108         break;
109
110 case ICMD_GETFIELD: /* {STACKBASED} */
111         CHECK_STACK_TYPE(stack[0], TYPE_ADR);
112         stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
113         if (stack == NULL)
114                 EXCEPTION;
115         break;
116
117 case ICMD_GETSTATIC:      /* {STACKBASED} */
118         stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
119         if (stack == NULL)
120                 EXCEPTION;
121         break;
122
123 case ICMD_PUTFIELD:       /* {VARIABLESBASED} */
124         if (!verify_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
125                 return false;
126         maythrow = true;
127         break;
128
129 case ICMD_PUTSTATIC:      /* {VARIABLESBASED} */
130         if (!verify_fieldaccess(state, NULL, VAROP(iptr->s1)))
131                 return false;
132         maythrow = true;
133         break;
134
135 case ICMD_PUTFIELDCONST:  /* {VARIABLESBASED} */
136         /* XXX this mess will go away with const operands */
137         INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
138         constvalue.type = fieldref->parseddesc.fd->type;
139         if (IS_ADR_TYPE(constvalue.type)) {
140                 if (state->iptr->sx.val.anyptr) {
141                         classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
142                                 ? class_java_lang_Class : class_java_lang_String;
143                         assert(cc);
144                         assert(cc->state & CLASS_LINKED);
145                         typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
146                 }
147                 else {
148                         TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
149                 }
150         }
151         if (!verify_fieldaccess(state, VAROP(iptr->s1), &constvalue))
152                 return false;
153         maythrow = true;
154         break;
155
156 case ICMD_PUTSTATICCONST: /* {VARIABLESBASED} */
157         /* XXX this mess will go away with const operands */
158         INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
159         constvalue.type = fieldref->parseddesc.fd->type;
160         if (IS_ADR_TYPE(constvalue.type)) {
161                 if (state->iptr->sx.val.anyptr) {
162                         classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
163                                 ? class_java_lang_Class : class_java_lang_String;
164                         assert(cc);
165                         assert(cc->state & CLASS_LINKED);
166                         typeinfo_init_classinfo(&(constvalue.typeinfo), cc);
167                 }
168                 else {
169                         TYPEINFO_INIT_NULLTYPE(constvalue.typeinfo);
170                 }
171         }
172         if (!verify_fieldaccess(state, NULL, &constvalue))
173                 return false;
174         maythrow = true;
175         break;
176
177 case ICMD_GETFIELD:       /* {VARIABLESBASED} */
178         if (!verify_fieldaccess(state, VAROP(iptr->s1), NULL))
179                 return false;
180         maythrow = true;
181         break;
182
183 case ICMD_GETSTATIC:      /* {VARIABLESBASED} */
184         if (!verify_fieldaccess(state, NULL, NULL))
185                 return false;
186         maythrow = true;
187         break;
188
189         /****************************************/
190         /* PRIMITIVE ARRAY ACCESS               */
191
192 case ICMD_ARRAYLENGTH:
193         if (!TYPEINFO_MAYBE_ARRAY(OP1->typeinfo)
194                         && OP1->typeinfo.typeclass.cls != pseudo_class_Arraystub)
195                 VERIFY_ERROR("illegal instruction: ARRAYLENGTH on non-array");
196         break;
197
198 case ICMD_BALOAD:
199         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
200                         && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
201                 VERIFY_ERROR("Array type mismatch");
202         break;
203
204 case ICMD_CALOAD:
205         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
206                 VERIFY_ERROR("Array type mismatch");
207         break;
208
209 case ICMD_DALOAD:
210         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
211                 VERIFY_ERROR("Array type mismatch");
212         break;
213
214 case ICMD_FALOAD:
215         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
216                 VERIFY_ERROR("Array type mismatch");
217         break;
218
219 case ICMD_IALOAD:
220         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
221                 VERIFY_ERROR("Array type mismatch");
222         break;
223
224 case ICMD_SALOAD:
225         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
226                 VERIFY_ERROR("Array type mismatch");
227         break;
228
229 case ICMD_LALOAD:
230         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
231                 VERIFY_ERROR("Array type mismatch");
232         break;
233
234 case ICMD_BASTORE:
235         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
236                         && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
237                 VERIFY_ERROR("Array type mismatch");
238         break;
239
240 case ICMD_CASTORE:
241         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
242                 VERIFY_ERROR("Array type mismatch");
243         break;
244
245 case ICMD_DASTORE:
246         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
247                 VERIFY_ERROR("Array type mismatch");
248         break;
249
250 case ICMD_FASTORE:
251         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
252                 VERIFY_ERROR("Array type mismatch");
253         break;
254
255 case ICMD_IASTORE:
256         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
257                 VERIFY_ERROR("Array type mismatch");
258         break;
259
260 case ICMD_SASTORE:
261         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
262                 VERIFY_ERROR("Array type mismatch");
263         break;
264
265 case ICMD_LASTORE:
266         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
267                 VERIFY_ERROR("Array type mismatch");
268         break;
269
270 case ICMD_AASTORE:
271         /* we just check the basic input types and that the           */
272         /* destination is an array of references. Assignability to    */
273         /* the actual array must be checked at runtime, each time the */
274         /* instruction is performed. (See builtin_canstore.)          */
275         if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
276                 VERIFY_ERROR("illegal instruction: AASTORE to non-reference array");
277         break;
278
279 case ICMD_IASTORECONST:
280         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_INT))
281                 VERIFY_ERROR("Array type mismatch");
282         break;
283
284 case ICMD_LASTORECONST:
285         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_LONG))
286                 VERIFY_ERROR("Array type mismatch");
287         break;
288
289 case ICMD_BASTORECONST:
290         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BOOLEAN)
291                         && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BYTE))
292                 VERIFY_ERROR("Array type mismatch");
293         break;
294
295 case ICMD_CASTORECONST:
296         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_CHAR))
297                 VERIFY_ERROR("Array type mismatch");
298         break;
299
300 case ICMD_SASTORECONST:
301         if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_SHORT))
302                 VERIFY_ERROR("Array type mismatch");
303         break;
304
305         /****************************************/
306         /* ADDRESS CONSTANTS                    */
307
308 case ICMD_ACONST:
309         if (IPTR->flags.bits & INS_FLAG_CLASS) {
310                 /* a java.lang.Class reference */
311                 TYPEINFO_INIT_JAVA_LANG_CLASS(DST->typeinfo,IPTR->sx.val.c);
312         }
313         else {
314                 if (IPTR->sx.val.anyptr == NULL)
315                         TYPEINFO_INIT_NULLTYPE(DST->typeinfo);
316                 else {
317                         /* string constant (or constant for builtin function) */
318                         typeinfo_init_classinfo(&(DST->typeinfo),class_java_lang_String);
319                 }
320         }
321         break;
322
323         /****************************************/
324         /* CHECKCAST AND INSTANCEOF             */
325
326 case ICMD_CHECKCAST:
327         /* returnAddress is not allowed */
328         if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
329                 VERIFY_ERROR("Illegal instruction: CHECKCAST on non-reference");
330
331         if (!typeinfo_init_class(&(DST->typeinfo),IPTR->sx.s23.s3.c))
332                 EXCEPTION;
333         break;
334
335 case ICMD_INSTANCEOF:
336         /* returnAddress is not allowed */
337         if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
338                 VERIFY_ERROR("Illegal instruction: INSTANCEOF on non-reference");
339         break;
340
341         /****************************************/
342         /* BRANCH INSTRUCTIONS                  */
343
344 case ICMD_GOTO:
345 case ICMD_IFNULL:
346 case ICMD_IFNONNULL:
347 case ICMD_IFEQ:
348 case ICMD_IFNE:
349 case ICMD_IFLT:
350 case ICMD_IFGE:
351 case ICMD_IFGT:
352 case ICMD_IFLE:
353 case ICMD_IF_ICMPEQ:
354 case ICMD_IF_ICMPNE:
355 case ICMD_IF_ICMPLT:
356 case ICMD_IF_ICMPGE:
357 case ICMD_IF_ICMPGT:
358 case ICMD_IF_ICMPLE:
359 case ICMD_IF_ACMPEQ:
360 case ICMD_IF_ACMPNE:
361
362 case ICMD_IF_LEQ:
363 case ICMD_IF_LNE:
364 case ICMD_IF_LLT:
365 case ICMD_IF_LGE:
366 case ICMD_IF_LGT:
367 case ICMD_IF_LLE:
368
369 case ICMD_IF_LCMPEQ:
370 case ICMD_IF_LCMPNE:
371 case ICMD_IF_LCMPLT:
372 case ICMD_IF_LCMPGE:
373 case ICMD_IF_LCMPGT:
374 case ICMD_IF_LCMPLE:
375
376 case ICMD_IF_FCMPEQ:
377 case ICMD_IF_FCMPNE:
378
379 case ICMD_IF_FCMPL_LT:
380 case ICMD_IF_FCMPL_GE:
381 case ICMD_IF_FCMPL_GT:
382 case ICMD_IF_FCMPL_LE:
383
384 case ICMD_IF_FCMPG_LT:
385 case ICMD_IF_FCMPG_GE:
386 case ICMD_IF_FCMPG_GT:
387 case ICMD_IF_FCMPG_LE:
388
389 case ICMD_IF_DCMPEQ:
390 case ICMD_IF_DCMPNE:
391
392 case ICMD_IF_DCMPL_LT:
393 case ICMD_IF_DCMPL_GE:
394 case ICMD_IF_DCMPL_GT:
395 case ICMD_IF_DCMPL_LE:
396
397 case ICMD_IF_DCMPG_LT:
398 case ICMD_IF_DCMPG_GE:
399 case ICMD_IF_DCMPG_GT:
400 case ICMD_IF_DCMPG_LE:
401         /* {RESULTNOW} */
402         TYPECHECK_COUNT(stat_ins_branch);
403
404         /* propagate stack and variables to the target block */
405         REACH(IPTR->dst);
406         break;
407
408         /****************************************/
409         /* SWITCHES                             */
410
411 case ICMD_TABLESWITCH:
412         /* {RESULTNOW} */
413         TYPECHECK_COUNT(stat_ins_switch);
414
415         table = IPTR->dst.table;
416         i = IPTR->sx.s23.s3.tablehigh
417         - IPTR->sx.s23.s2.tablelow + 1 + 1; /* plus default */
418
419         while (--i >= 0) {
420                 REACH(*table);
421                 table++;
422         }
423
424         LOG("switch done");
425         break;
426
427 case ICMD_LOOKUPSWITCH:
428         /* {RESULTNOW} */
429         TYPECHECK_COUNT(stat_ins_switch);
430
431         lookup = IPTR->dst.lookup;
432         i = IPTR->sx.s23.s2.lookupcount;
433         REACH(IPTR->sx.s23.s3.lookupdefault);
434
435         while (--i >= 0) {
436                 REACH(lookup->target);
437                 lookup++;
438         }
439
440         LOG("switch done");
441         break;
442
443
444         /****************************************/
445         /* ADDRESS RETURNS AND THROW            */
446
447 case ICMD_ATHROW:
448         TYPECHECK_COUNT(stat_ins_athrow);
449         r = typeinfo_is_assignable_to_class(&OP1->typeinfo,
450                         CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
451         if (r == typecheck_FALSE)
452                 VERIFY_ERROR("illegal instruction: ATHROW on non-Throwable");
453         if (r == typecheck_FAIL)
454                 EXCEPTION;
455         if (r == typecheck_MAYBE) {
456                 /* the check has to be postponed. we need a patcher */
457                 TYPECHECK_COUNT(stat_ins_athrow_unresolved);
458                 IPTR->sx.s23.s2.uc = create_unresolved_class(
459                                 METHOD,
460                                 /* XXX make this more efficient, use class_java_lang_Throwable
461                                  * directly */
462                                 class_get_classref(METHOD->class,utf_java_lang_Throwable),
463                                 &OP1->typeinfo);
464                 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
465         }
466         break;
467
468 case ICMD_ARETURN:
469         TYPECHECK_COUNT(stat_ins_areturn);
470         if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
471                 VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
472
473         if (STATE->returntype.type != TYPE_ADR
474                         || (r = typeinfo_is_assignable(&OP1->typeinfo,&(STATE->returntype.typeinfo)))
475                         == typecheck_FALSE)
476                 VERIFY_ERROR("Return type mismatch");
477         if (r == typecheck_FAIL)
478                 EXCEPTION;
479         if (r == typecheck_MAYBE) {
480                 /* the check has to be postponed, we need a patcher */
481                 TYPECHECK_COUNT(stat_ins_areturn_unresolved);
482                 IPTR->sx.s23.s2.uc = create_unresolved_class(
483                                 METHOD,
484                                 METHOD->parseddesc->returntype.classref,
485                                 &OP1->typeinfo);
486                 IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
487         }
488         goto return_tail;
489
490         /****************************************/
491         /* PRIMITIVE RETURNS                    */
492
493 case ICMD_IRETURN:
494         if (STATE->returntype.type != TYPE_INT)
495                 VERIFY_ERROR("Return type mismatch");
496         goto return_tail;
497
498 case ICMD_LRETURN:
499         if (STATE->returntype.type != TYPE_LNG)
500                 VERIFY_ERROR("Return type mismatch");
501         goto return_tail;
502
503 case ICMD_FRETURN:
504         if (STATE->returntype.type != TYPE_FLT)
505                 VERIFY_ERROR("Return type mismatch");
506         goto return_tail;
507
508 case ICMD_DRETURN:
509         if (STATE->returntype.type != TYPE_DBL)
510                 VERIFY_ERROR("Return type mismatch");
511         goto return_tail;
512
513 case ICMD_RETURN:
514         if (STATE->returntype.type != TYPE_VOID)
515                 VERIFY_ERROR("Return type mismatch");
516
517 return_tail:
518         TYPECHECK_COUNT(stat_ins_primitive_return);
519
520         if (STATE->initmethod && METHOD->class != class_java_lang_Object) {
521                 /* Check if the 'this' instance has been initialized. */
522                 LOG("Checking <init> marker");
523 #if defined(TYPECHECK_VARIABLESBASED)
524                 if (!typevector_checktype(jd->var,STATE->numlocals-1,TYPE_INT))
525 #else
526                 if (STATE->locals[STATE->numlocals-1].type != TYPE_INT)
527 #endif
528                         VERIFY_ERROR("<init> method does not initialize 'this'");
529         }
530         break;
531
532         /****************************************/
533         /* SUBROUTINE INSTRUCTIONS              */
534
535 case ICMD_JSR: /* {VARIABLESBASED} */
536         TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
537         REACH(IPTR->sx.s23.s3.jsrtarget);
538         break;
539
540 case ICMD_JSR: /* {STACKBASED} */
541         /* {RESULTNOW} */
542         tbptr = BLOCK_OF(IPTR->sx.s23.s3.jsrtarget.insindex);
543
544         TYPEINFO_INIT_RETURNADDRESS(stack[0].typeinfo, tbptr);
545         REACH_BLOCK(tbptr);
546
547         stack = typecheck_stackbased_jsr(STATE, stack, stackfloor);
548         if (stack == NULL)
549                 EXCEPTION;
550         break;
551
552 case ICMD_RET: /* {VARIABLESBASED} */
553         /* check returnAddress variable */
554         if (!typevector_checkretaddr(jd->var,IPTR->s1.varindex))
555                 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
556         REACH(IPTR->dst);
557         break;
558
559 case ICMD_RET: /* {STACKBASED} */
560         /* {RESULTNOW} */
561         CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_ADR);
562         if (!TYPEINFO_IS_PRIMITIVE(STATE->locals[IPTR->s1.varindex].typeinfo))
563                 VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
564
565         if (!typecheck_stackbased_ret(STATE, stack, stackfloor))
566                 EXCEPTION;
567         break;
568
569         /****************************************/
570         /* INVOKATIONS                          */
571
572 case ICMD_INVOKEVIRTUAL:   /* {VARIABLESBASED} */
573 case ICMD_INVOKESPECIAL:   /* {VARIABLESBASED} */
574 case ICMD_INVOKESTATIC:    /* {VARIABLESBASED} */
575 case ICMD_INVOKEINTERFACE: /* {VARIABLESBASED} */
576         TYPECHECK_COUNT(stat_ins_invoke);
577         if (!verify_invocation(state))
578                 EXCEPTION;
579         TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
580         break;
581
582 case ICMD_INVOKEVIRTUAL:   /* {STACKBASED} */
583 case ICMD_INVOKESPECIAL:   /* {STACKBASED} */
584 case ICMD_INVOKESTATIC:    /* {STACKBASED} */
585 case ICMD_INVOKEINTERFACE: /* {STACKBASED} */
586         TYPECHECK_COUNT(stat_ins_invoke);
587
588         INSTRUCTION_GET_METHODDESC(IPTR, md);
589         CHECK_STACK_DEPTH(md->paramslots);
590
591         if (!typecheck_stackbased_verify_invocation(STATE, stack, stackfloor))
592                 EXCEPTION;
593
594         stack -= md->paramslots;
595
596         if (md->returntype.type != TYPE_VOID) {
597                 if (IS_2_WORD_TYPE(md->returntype.type)) {
598                         CHECK_STACK_SPACE(2);
599                         stack += 2;
600                         stack[0].type = TYPE_VOID;
601                         stack[-1].type = md->returntype.type;
602                 }
603                 else {
604                         CHECK_STACK_SPACE(1);
605                         stack += 1;
606                         stack[0].type = md->returntype.type;
607                 }
608         }
609         TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(IPTR), stat_ins_invoke_unresolved);
610         break;
611
612         /****************************************/
613         /* MULTIANEWARRAY                       */
614
615 case ICMD_MULTIANEWARRAY: /* {VARIABLESBASED} */
616         if (!verify_multianewarray(STATE))
617                 EXCEPTION;
618         break;
619
620 case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
621         if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
622                 EXCEPTION;
623         stack -= (IPTR->s1.argcount - 1);
624         stack[0].type = TYPE_ADR;
625         break;
626
627         /****************************************/
628         /* BUILTINS                             */
629
630 case ICMD_BUILTIN: /* {VARIABLESBASED} */
631         TYPECHECK_COUNT(stat_ins_builtin);
632         if (!verify_builtin(state))
633                 EXCEPTION;
634         break;
635
636 case ICMD_BUILTIN: /* {STACKBASED} */
637         TYPECHECK_COUNT(stat_ins_builtin);
638         if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
639                 EXCEPTION;
640
641         /* pop operands and push return value */
642         {
643                 u1 rtype = IPTR->sx.s23.s3.bte->md->returntype.type;
644                 stack -=  IPTR->sx.s23.s3.bte->md->paramslots;
645                 if (rtype != TYPE_VOID) {
646                         if (IS_2_WORD_TYPE(rtype))
647                                 stack += 2;
648                         else
649                                 stack += 1;
650                 }
651         }
652         break;
653
654 /* the following code is only used by the stackbased verifier */
655
656 case ICMD_POP: /* {STACKBASED} */
657         /* we pop 1 */
658         CHECK_CAT1(stack[0]);
659         break;
660
661 case ICMD_POP2: /* {STACKBASED} */
662         /* we pop either 11 or 2 */
663         if (IS_CAT1(stack[0]))
664                 CHECK_CAT1(stack[-1]);
665         break;
666
667 case ICMD_SWAP:
668         CHECK_CAT1(stack[0]);
669         CHECK_CAT1(stack[-1]);
670
671         COPY_SLOT(stack[ 0], temp     );
672         COPY_SLOT(stack[-1], stack[ 0]);
673         COPY_SLOT(temp     , stack[-1]);
674         break;
675
676 case ICMD_DUP:
677         /* we dup 1 */
678         CHECK_CAT1(stack[0]);
679
680         COPY_SLOT(stack[ 0], stack[ 1]);
681         break;
682
683 case ICMD_DUP_X1:
684         /* we dup 1 */
685         CHECK_CAT1(stack[0]);
686         /* we skip 1 */
687         CHECK_CAT1(stack[-1]);
688
689         COPY_SLOT(stack[ 0], stack[ 1]);
690         COPY_SLOT(stack[-1], stack[ 0]);
691         COPY_SLOT(stack[ 1], stack[-1]);
692         break;
693
694 case ICMD_DUP_X2:
695         /* we dup 1 */
696         CHECK_CAT1(stack[0]);
697         /* we skip either 11 or 2 */
698         if (IS_CAT1(stack[-1]))
699                 CHECK_CAT1(stack[-2]);
700
701         COPY_SLOT(stack[ 0], stack[ 1]);
702         COPY_SLOT(stack[-1], stack[ 0]);
703         COPY_SLOT(stack[-2], stack[-1]);
704         COPY_SLOT(stack[ 1], stack[-2]);
705         break;
706
707 case ICMD_DUP2:
708         /* we dup either 11 or 2 */
709         if (IS_CAT1(stack[0]))
710                 CHECK_CAT1(stack[-1]);
711
712         COPY_SLOT(stack[ 0], stack[ 2]);
713         COPY_SLOT(stack[-1], stack[ 1]);
714         break;
715
716 case ICMD_DUP2_X1:
717         /* we dup either 11 or 2 */
718         if (IS_CAT1(stack[0]))
719                 CHECK_CAT1(stack[-1]);
720         /* we skip 1 */
721         CHECK_CAT1(stack[-2]);
722
723         COPY_SLOT(stack[ 0], stack[ 2]);
724         COPY_SLOT(stack[-1], stack[ 1]);
725         COPY_SLOT(stack[-2], stack[ 0]);
726         COPY_SLOT(stack[ 2], stack[-1]);
727         COPY_SLOT(stack[ 1], stack[-2]);
728         break;
729
730 case ICMD_DUP2_X2:
731         /* we dup either 11 or 2 */
732         if (IS_CAT1(stack[0]))
733                 CHECK_CAT1(stack[-1]);
734         /* we skip either 11 or 2 */
735         if (IS_CAT1(stack[-2]))
736                 CHECK_CAT1(stack[-3]);
737
738         COPY_SLOT(stack[ 0], stack[ 2]);
739         COPY_SLOT(stack[-1], stack[ 1]);
740         COPY_SLOT(stack[-2], stack[ 0]);
741         COPY_SLOT(stack[-3], stack[-1]);
742         COPY_SLOT(stack[ 2], stack[-2]);
743         COPY_SLOT(stack[ 1], stack[-3]);
744         break;
745
746
747 /* this marker is needed by generate.pl: */
748 /* {END_OF_CODE} */
749
750 /*
751  * These are local overrides for various environment variables in Emacs.
752  * Please do not remove this and leave it at the end of the file, where
753  * Emacs will automagically detect them.
754  * ---------------------------------------------------------------------
755  * Local variables:
756  * mode: c
757  * indent-tabs-mode: t
758  * c-basic-offset: 4
759  * tab-width: 4
760  * End:
761  * vim:noexpandtab:sw=4:ts=4:
762  */