Line data Source code
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 6325 : TYPECHECK_COUNT(stat_ins_stack);
81 650172 : COPYTYPE(IPTR->s1, IPTR->dst);
82 643847 : 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 413174 : VERIFY_ERROR("illegal instruction: ALOAD loading non-reference");
95 0 : }
96 : #endif
97 : DST->typeinfo = OP1->typeinfo;
98 : break;
99 413174 :
100 : /****************************************/
101 : /* STORING ADDRESS TO VARIABLE */
102 :
103 : case ICMD_ASTORE: /* {ALL} */
104 62611 : 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 21280 : VERIFY_ERROR("illegal instruction: AALOAD on non-reference array");
114 0 : #endif
115 :
116 : if (!DST->typeinfo.init_component(OP1->typeinfo))
117 : EXCEPTION;
118 21280 : break;
119 0 :
120 : /****************************************/
121 : /* FIELD ACCESS */
122 :
123 : case ICMD_PUTFIELD: /* {STACKBASED} */
124 0 : CHECK_STACK_DEPTH(2);
125 0 : if (!IS_CAT1(stack[0])) {
126 0 : CHECK_STACK_DEPTH(3);
127 0 : stack -= 1;
128 : }
129 0 : CHECK_STACK_TYPE(stack[-1], TYPE_ADR);
130 0 : stack = typecheck_stackbased_verify_fieldaccess(STATE, stack-1, stack, stack-2);
131 0 : if (stack == NULL)
132 0 : EXCEPTION;
133 : break;
134 :
135 : case ICMD_PUTSTATIC: /* {STACKBASED} */
136 0 : CHECK_STACK_DEPTH(1);
137 0 : if (!IS_CAT1(stack[0])) {
138 : /* (stack depth >= 2 is guaranteed) */
139 0 : stack -= 1;
140 : }
141 0 : stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, stack, stack-1);
142 0 : if (stack == NULL)
143 0 : EXCEPTION;
144 : break;
145 :
146 : case ICMD_GETFIELD: /* {STACKBASED} */
147 0 : CHECK_STACK_TYPE(stack[0], TYPE_ADR);
148 0 : stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
149 0 : if (stack == NULL)
150 0 : EXCEPTION;
151 : break;
152 :
153 : case ICMD_GETSTATIC: /* {STACKBASED} */
154 0 : stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
155 0 : if (stack == NULL)
156 0 : EXCEPTION;
157 : break;
158 :
159 : case ICMD_PUTFIELD: /* {VARIABLESBASED} */
160 40170 : if (!handle_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
161 0 : return false;
162 40170 : maythrow = true;
163 : break;
164 :
165 : case ICMD_PUTSTATIC: /* {VARIABLESBASED} */
166 21810 : if (!handle_fieldaccess(state, NULL, VAROP(iptr->s1)))
167 0 : return false;
168 21810 : maythrow = true;
169 : break;
170 :
171 : case ICMD_PUTFIELDCONST: /* {VARIABLESBASED} */
172 : /* XXX this mess will go away with const operands */
173 12233 : INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
174 12233 : constvalue.type = fieldref->parseddesc.fd->type;
175 12233 : if (IS_ADR_TYPE(constvalue.type)) {
176 3807 : if (state->iptr->sx.val.anyptr) {
177 : classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
178 339 : ? class_java_lang_Class : class_java_lang_String;
179 339 : assert(cc);
180 339 : assert(cc->state & CLASS_LINKED);
181 339 : constvalue.typeinfo.init_class(cc);
182 : }
183 : else {
184 3468 : constvalue.typeinfo.init_nulltype();
185 : }
186 : }
187 12233 : if (!handle_fieldaccess(state, VAROP(iptr->s1), &constvalue))
188 0 : return false;
189 12233 : maythrow = true;
190 : break;
191 :
192 : case ICMD_PUTSTATICCONST: /* {VARIABLESBASED} */
193 : /* XXX this mess will go away with const operands */
194 814 : INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
195 814 : constvalue.type = fieldref->parseddesc.fd->type;
196 814 : if (IS_ADR_TYPE(constvalue.type)) {
197 290 : if (state->iptr->sx.val.anyptr) {
198 : classinfo *cc = (state->iptr->flags.bits & INS_FLAG_CLASS)
199 1 : ? class_java_lang_Class : class_java_lang_String;
200 1 : assert(cc);
201 1 : assert(cc->state & CLASS_LINKED);
202 1 : constvalue.typeinfo.init_class(cc);
203 : }
204 : else {
205 289 : constvalue.typeinfo.init_nulltype();
206 : }
207 : }
208 814 : if (!handle_fieldaccess(state, NULL, &constvalue))
209 0 : return false;
210 814 : maythrow = true;
211 : break;
212 :
213 : case ICMD_GETFIELD: /* {VARIABLESBASED,TYPEINFERER} */
214 101999 : if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
215 0 : return false;
216 101999 : maythrow = true;
217 : break;
218 :
219 : case ICMD_GETSTATIC: /* {VARIABLESBASED,TYPEINFERER} */
220 48519 : if (!handle_fieldaccess(state, NULL, NULL))
221 0 : return false;
222 48519 : maythrow = true;
223 : break;
224 :
225 : /****************************************/
226 : /* PRIMITIVE ARRAY ACCESS */
227 :
228 : case ICMD_ARRAYLENGTH:
229 9830 : if (!OP1->typeinfo.maybe_array() && OP1->typeinfo.typeclass.cls != pseudo_class_Arraystub)
230 0 : VERIFY_ERROR("illegal instruction: ARRAYLENGTH on non-array");
231 : break;
232 :
233 : case ICMD_BALOAD:
234 160 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BOOLEAN)
235 : && !OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BYTE))
236 0 : VERIFY_ERROR("Array type mismatch");
237 : break;
238 :
239 : case ICMD_CALOAD:
240 3610 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_CHAR))
241 0 : VERIFY_ERROR("Array type mismatch");
242 : break;
243 :
244 : case ICMD_DALOAD:
245 3 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_DOUBLE))
246 0 : VERIFY_ERROR("Array type mismatch");
247 : break;
248 :
249 : case ICMD_FALOAD:
250 3 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_FLOAT))
251 0 : VERIFY_ERROR("Array type mismatch");
252 : break;
253 :
254 : case ICMD_IALOAD:
255 301 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_INT))
256 0 : VERIFY_ERROR("Array type mismatch");
257 : break;
258 :
259 : case ICMD_SALOAD:
260 59 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_SHORT))
261 0 : VERIFY_ERROR("Array type mismatch");
262 : break;
263 :
264 : case ICMD_LALOAD:
265 21 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_LONG))
266 0 : VERIFY_ERROR("Array type mismatch");
267 : break;
268 :
269 : case ICMD_BASTORE:
270 360 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BOOLEAN)
271 : && !OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BYTE))
272 0 : VERIFY_ERROR("Array type mismatch");
273 : break;
274 :
275 : case ICMD_CASTORE:
276 1032 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_CHAR))
277 0 : VERIFY_ERROR("Array type mismatch");
278 : break;
279 :
280 : case ICMD_DASTORE:
281 4 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_DOUBLE))
282 0 : VERIFY_ERROR("Array type mismatch");
283 : break;
284 :
285 : case ICMD_FASTORE:
286 6 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_FLOAT))
287 0 : VERIFY_ERROR("Array type mismatch");
288 : break;
289 :
290 : case ICMD_IASTORE:
291 86 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_INT))
292 0 : VERIFY_ERROR("Array type mismatch");
293 : break;
294 :
295 : case ICMD_SASTORE:
296 52 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_SHORT))
297 0 : VERIFY_ERROR("Array type mismatch");
298 : break;
299 :
300 : case ICMD_LASTORE:
301 10 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_LONG))
302 0 : 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 64570 : if (!OP1->typeinfo.maybe_array_of_refs())
311 0 : VERIFY_ERROR("illegal instruction: AASTORE to non-reference array");
312 : break;
313 :
314 : case ICMD_IASTORECONST:
315 4735 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_INT))
316 0 : VERIFY_ERROR("Array type mismatch");
317 : break;
318 :
319 : case ICMD_LASTORECONST:
320 6 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_LONG))
321 0 : VERIFY_ERROR("Array type mismatch");
322 : break;
323 :
324 : case ICMD_BASTORECONST:
325 725 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BOOLEAN)
326 : && !OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_BYTE))
327 0 : VERIFY_ERROR("Array type mismatch");
328 : break;
329 :
330 : case ICMD_CASTORECONST:
331 508614 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_CHAR))
332 0 : VERIFY_ERROR("Array type mismatch");
333 : break;
334 :
335 : case ICMD_SASTORECONST:
336 4 : if (!OP1->typeinfo.maybe_primitive_array(ARRAYTYPE_SHORT))
337 0 : VERIFY_ERROR("Array type mismatch");
338 : break;
339 :
340 : /****************************************/
341 : /* ADDRESS CONSTANTS */
342 :
343 : case ICMD_ACONST: /* {ALL} */
344 168685 : if (IPTR->flags.bits & INS_FLAG_CLASS) {
345 : /* a java.lang.Class reference */
346 64184 : DST->typeinfo.init_java_lang_class(IPTR->sx.val.c);
347 : }
348 : else {
349 104501 : if (IPTR->sx.val.anyptr == NULL)
350 13152 : DST->typeinfo.init_nulltype();
351 : else {
352 : /* string constant (or constant for builtin function) */
353 91349 : 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 9506 : VERIFY_ERROR("Illegal instruction: CHECKCAST on non-reference");
366 0 : #endif
367 :
368 : /* XXX only if narrower */
369 : if (!DST->typeinfo.init_class(IPTR->sx.s23.s3.c))
370 : EXCEPTION;
371 9506 : break;
372 0 :
373 : case ICMD_INSTANCEOF:
374 : /* returnAddress is not allowed */
375 1339 : if (!OP1->typeinfo.is_reference())
376 0 : 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 36379 : case ICMD_IFLT: /* {ALL} */
390 0 : case ICMD_IFGE: /* {ALL} */
391 : case ICMD_IFGT: /* {ALL} */
392 0 : 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 0 : 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 0 : case ICMD_IF_LLT: /* {ALL} */
405 : case ICMD_IF_LGE: /* {ALL} */
406 : case ICMD_IF_LGT: /* {ALL} */
407 110068 : 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 80 : table = IPTR->dst.table;
430 : i = IPTR->sx.s23.s3.tablehigh
431 80 : - IPTR->sx.s23.s2.tablelow + 1 + 1; /* plus default */
432 :
433 1336 : while (--i >= 0) {
434 1176 : REACH(*table);
435 1176 : 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 78 : lookup = IPTR->dst.lookup;
446 78 : i = IPTR->sx.s23.s2.lookupcount;
447 78 : REACH(IPTR->sx.s23.s3.lookupdefault);
448 :
449 780 : while (--i >= 0) {
450 624 : REACH(lookup->target);
451 624 : 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 19130 : r = OP1->typeinfo.is_assignable_to_class(to_classref_or_classinfo(class_java_lang_Throwable));
464 19130 : if (r == typecheck_FALSE)
465 1 : VERIFY_ERROR("illegal instruction: ATHROW on non-Throwable");
466 19129 : if (r == typecheck_FAIL)
467 0 : EXCEPTION;
468 19129 : 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 15328 : &OP1->typeinfo);
477 15328 : IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
478 : }
479 : break;
480 :
481 : case ICMD_ARETURN:
482 : TYPECHECK_COUNT(stat_ins_areturn);
483 39056 : if (!OP1->typeinfo.is_reference())
484 0 : VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
485 :
486 39056 : if (STATE->returntype.type != TYPE_ADR
487 : || (r = OP1->typeinfo.is_assignable_to(&(STATE->returntype.typeinfo)))
488 : == typecheck_FALSE)
489 0 : VERIFY_ERROR("Return type mismatch");
490 39056 : if (r == typecheck_FAIL)
491 0 : EXCEPTION;
492 39056 : 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 3305 : &OP1->typeinfo);
499 3305 : IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
500 : }
501 : goto return_tail;
502 :
503 : /****************************************/
504 : /* PRIMITIVE RETURNS */
505 :
506 : case ICMD_IRETURN:
507 19769 : if (STATE->returntype.type != TYPE_INT)
508 1 : VERIFY_ERROR("Return type mismatch");
509 : goto return_tail;
510 :
511 : case ICMD_LRETURN:
512 246 : if (STATE->returntype.type != TYPE_LNG)
513 0 : VERIFY_ERROR("Return type mismatch");
514 : goto return_tail;
515 :
516 : case ICMD_FRETURN:
517 154 : if (STATE->returntype.type != TYPE_FLT)
518 0 : VERIFY_ERROR("Return type mismatch");
519 : goto return_tail;
520 :
521 : case ICMD_DRETURN:
522 9 : if (STATE->returntype.type != TYPE_DBL)
523 0 : VERIFY_ERROR("Return type mismatch");
524 : goto return_tail;
525 :
526 : case ICMD_RETURN:
527 44351 : if (STATE->returntype.type != TYPE_VOID)
528 0 : VERIFY_ERROR("Return type mismatch");
529 :
530 : return_tail:
531 : TYPECHECK_COUNT(stat_ins_primitive_return);
532 :
533 103584 : 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 25389 : #else
539 : if (STATE->locals[STATE->numlocals-1].type != TYPE_INT)
540 : #endif
541 0 : VERIFY_ERROR("<init> method does not initialize 'this'");
542 : }
543 : break;
544 0 :
545 : /****************************************/
546 : /* SUBROUTINE INSTRUCTIONS */
547 :
548 : case ICMD_JSR: /* {VARIABLESBASED,TYPEINFERER} */
549 18 : DST->typeinfo.init_returnaddress(BPTR->next);
550 18 : REACH(IPTR->sx.s23.s3.jsrtarget);
551 : break;
552 :
553 : case ICMD_JSR: /* {STACKBASED} */
554 : /* {RESULTNOW} */
555 0 : tbptr = IPTR->sx.s23.s3.jsrtarget.block;
556 :
557 0 : stack[0].typeinfo.init_returnaddress(tbptr);
558 0 : REACH_BLOCK(tbptr);
559 :
560 0 : stack = typecheck_stackbased_jsr(STATE, stack, stackfloor);
561 0 : if (stack == NULL)
562 0 : 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 15 : VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
570 0 : #endif
571 : REACH(IPTR->dst);
572 : break;
573 15 :
574 : case ICMD_RET: /* {STACKBASED} */
575 : /* {RESULTNOW} */
576 0 : CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_RET);
577 0 : if (!STATE->locals[IPTR->s1.varindex].typeinfo.is_primitive())
578 0 : VERIFY_ERROR("illegal instruction: RET using non-returnAddress variable");
579 :
580 0 : if (!typecheck_stackbased_ret(STATE, stack, stackfloor))
581 0 : EXCEPTION;
582 : break;
583 :
584 : /****************************************/
585 : /* INVOKATIONS */
586 :
587 : case ICMD_INVOKEVIRTUAL: /* {VARIABLESBASED,TYPEINFERER} */
588 : case ICMD_INVOKESPECIAL: /* {VARIABLESBASED,TYPEINFERER} */
589 289993 : case ICMD_INVOKESTATIC: /* {VARIABLESBASED,TYPEINFERER} */
590 5 : 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 0 : case ICMD_INVOKEINTERFACE: /* {STACKBASED} */
601 0 : TYPECHECK_COUNT(stat_ins_invoke);
602 :
603 0 : INSTRUCTION_GET_METHODDESC(IPTR, md);
604 0 : CHECK_STACK_DEPTH(md->paramslots);
605 :
606 0 : if (!typecheck_stackbased_verify_invocation(STATE, stack, stackfloor))
607 : EXCEPTION;
608 0 :
609 0 : stack -= md->paramslots;
610 0 :
611 0 : if (md->returntype.type != TYPE_VOID) {
612 0 : if (IS_2_WORD_TYPE(md->returntype.type)) {
613 0 : CHECK_STACK_SPACE(2);
614 : stack += 2;
615 : stack[0].type = TYPE_VOID;
616 0 : stack[-1].type = md->returntype.type;
617 0 : }
618 0 : else {
619 : CHECK_STACK_SPACE(1);
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} */
631 15 : if (!handle_multianewarray(STATE))
632 0 : EXCEPTION;
633 : break;
634 :
635 : case ICMD_MULTIANEWARRAY: /* {STACKBASED} */
636 0 : if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
637 0 : EXCEPTION;
638 0 : stack -= (IPTR->s1.argcount - 1);
639 0 : 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 79492 : if (!handle_builtin(state))
648 0 : EXCEPTION;
649 : break;
650 :
651 : case ICMD_BUILTIN: /* {STACKBASED} */
652 : TYPECHECK_COUNT(stat_ins_builtin);
653 0 : if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
654 0 : EXCEPTION;
655 :
656 : /* pop operands and push return value */
657 : {
658 0 : u1 rtype = IPTR->sx.s23.s3.bte->md->returntype.type;
659 0 : stack -= IPTR->sx.s23.s3.bte->md->paramslots;
660 0 : if (rtype != TYPE_VOID) {
661 0 : if (IS_2_WORD_TYPE(rtype))
662 0 : stack += 2;
663 : else
664 0 : 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 0 : CHECK_CAT1(stack[0]);
674 : break;
675 :
676 : case ICMD_POP2: /* {STACKBASED} */
677 : /* we pop either 11 or 2 */
678 0 : if (IS_CAT1(stack[0]))
679 0 : CHECK_CAT1(stack[-1]);
680 : break;
681 :
682 : case ICMD_SWAP: /* {STACKBASED} */
683 0 : CHECK_CAT1(stack[0]);
684 0 : CHECK_CAT1(stack[-1]);
685 :
686 0 : COPY_SLOT(stack[ 0], temp );
687 0 : COPY_SLOT(stack[-1], stack[ 0]);
688 0 : COPY_SLOT(temp , stack[-1]);
689 : break;
690 :
691 : case ICMD_DUP: /* {STACKBASED} */
692 : /* we dup 1 */
693 0 : CHECK_CAT1(stack[0]);
694 :
695 0 : COPY_SLOT(stack[ 0], stack[ 1]);
696 : break;
697 :
698 : case ICMD_DUP_X1: /* {STACKBASED} */
699 : /* we dup 1 */
700 0 : CHECK_CAT1(stack[0]);
701 : /* we skip 1 */
702 0 : CHECK_CAT1(stack[-1]);
703 :
704 0 : COPY_SLOT(stack[ 0], stack[ 1]);
705 0 : COPY_SLOT(stack[-1], stack[ 0]);
706 0 : COPY_SLOT(stack[ 1], stack[-1]);
707 : break;
708 :
709 : case ICMD_DUP_X2: /* {STACKBASED} */
710 : /* we dup 1 */
711 0 : CHECK_CAT1(stack[0]);
712 : /* we skip either 11 or 2 */
713 0 : if (IS_CAT1(stack[-1]))
714 0 : CHECK_CAT1(stack[-2]);
715 :
716 0 : COPY_SLOT(stack[ 0], stack[ 1]);
717 0 : COPY_SLOT(stack[-1], stack[ 0]);
718 0 : COPY_SLOT(stack[-2], stack[-1]);
719 0 : COPY_SLOT(stack[ 1], stack[-2]);
720 : break;
721 :
722 : case ICMD_DUP2: /* {STACKBASED} */
723 : /* we dup either 11 or 2 */
724 0 : if (IS_CAT1(stack[0]))
725 0 : CHECK_CAT1(stack[-1]);
726 :
727 0 : COPY_SLOT(stack[ 0], stack[ 2]);
728 0 : COPY_SLOT(stack[-1], stack[ 1]);
729 : break;
730 :
731 : case ICMD_DUP2_X1: /* {STACKBASED} */
732 : /* we dup either 11 or 2 */
733 0 : if (IS_CAT1(stack[0]))
734 0 : CHECK_CAT1(stack[-1]);
735 : /* we skip 1 */
736 0 : CHECK_CAT1(stack[-2]);
737 :
738 0 : COPY_SLOT(stack[ 0], stack[ 2]);
739 0 : COPY_SLOT(stack[-1], stack[ 1]);
740 0 : COPY_SLOT(stack[-2], stack[ 0]);
741 0 : COPY_SLOT(stack[ 2], stack[-1]);
742 0 : COPY_SLOT(stack[ 1], stack[-2]);
743 : break;
744 :
745 : case ICMD_DUP2_X2: /* {STACKBASED} */
746 : /* we dup either 11 or 2 */
747 0 : if (IS_CAT1(stack[0]))
748 0 : CHECK_CAT1(stack[-1]);
749 : /* we skip either 11 or 2 */
750 0 : if (IS_CAT1(stack[-2]))
751 0 : CHECK_CAT1(stack[-3]);
752 :
753 0 : COPY_SLOT(stack[ 0], stack[ 2]);
754 0 : COPY_SLOT(stack[-1], stack[ 1]);
755 0 : COPY_SLOT(stack[-2], stack[ 0]);
756 0 : COPY_SLOT(stack[-3], stack[-1]);
757 0 : COPY_SLOT(stack[ 2], stack[-2]);
758 0 : 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 : */
|