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