001 /*
002 * This file is part of the Jikes RVM project (http://jikesrvm.org).
003 *
004 * This file is licensed to You under the Eclipse Public License (EPL);
005 * You may not use this file except in compliance with the License. You
006 * may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/eclipse-1.0.php
009 *
010 * See the COPYRIGHT.txt file distributed with this work for information
011 * regarding copyright ownership.
012 */
013 package org.jikesrvm.osr;
014
015 import org.jikesrvm.VM;
016 import org.jikesrvm.classloader.BytecodeConstants;
017 import org.jikesrvm.classloader.BytecodeStream;
018 import org.jikesrvm.classloader.ClassLoaderConstants;
019 import org.jikesrvm.classloader.RVMClass;
020 import org.jikesrvm.classloader.ExceptionHandlerMap;
021 import org.jikesrvm.classloader.FieldReference;
022 import org.jikesrvm.classloader.RVMMethod;
023 import org.jikesrvm.classloader.MethodReference;
024 import org.jikesrvm.classloader.NormalMethod;
025 import org.jikesrvm.classloader.TypeReference;
026 import org.jikesrvm.compilers.common.CompiledMethods;
027 import org.jikesrvm.osr.bytecodes.InvokeStatic;
028
029 /**
030 * BytecodeTraverser does depth first search on a bytecode
031 * array, determines the type information of locals and stacks at
032 * insteresting point.
033 *
034 * This class only intends to provide type information for on-stack
035 * replacement, which needs to know the type of a value. This class
036 * can only tells basic type information such as : REFERENCE, LONG,
037 * DOUBLE, FLOAT, INT, and ReturnAddress. Not like GCMap which tells
038 * GC a value is REFERENCE or NON-REFERENCE we also want to know it
039 * is INT or DOUBLE, and takes two words value or one word.
040 *
041 * The produced type information has to be adjusted by consulting
042 * GC maps because two different types may merge at one program point
043 * (REF and non-REF types). Bytecode verifier will make the type info
044 * undefined in that case. But this class won't know. So the caller
045 * should check the GC map to validate a REF type variable.
046 *
047 * More or less, this class needs to do the same work as a bytecode
048 * verifier, which tells the type and size of each locals and stacks.
049 * The JSR/RET instructions pose the difficulty to our case. However,
050 * we can assume the bytecode is verified. We use following assumptions:
051 * 1. After JSR, the stack was not changed, only local variable
052 * type needs to merge with FINALLY clause.
053 * 2. We need program-point specific stack type, but only need
054 * the summary of local types. Thus, after analysis, local
055 * types are same for all PCs.
056 */
057 public class BytecodeTraverser implements BytecodeConstants, ClassLoaderConstants, OSRConstants {
058
059 /////// COMMON
060 /* to handle ret address which is not produced by JSR, we need a
061 * separate array to track that.
062 */
063 private int[] retaddr;
064 private int addr;
065
066 private byte[] visitedpc;
067 private boolean TRACE = false;
068
069 // when computing infor for partial bytecodes
070 // donot following bytecodes out of range
071 private boolean ignoreGotos = false;
072 private BytecodeStream bytecodes;
073
074 /////// COMPUTING_TYPE_INFO
075 /* type information of local variables and stack slots */
076 private byte[] ltypes;
077 private byte[] stypes;
078
079 ///////////////////////////
080 // COMPUTE TYPE INFORMATION
081 //////////////////////////
082 /**
083 * Computes types of local variable and stack slots at an interesting point
084 * for future querying. Computing type info and retrieval should not be
085 * reentered. The type info of local variable is not accurate about reference
086 * types, see JVM SPEC (2nd edition) p 146. The caller can consult GC map
087 * to verify if a local is a reference or not.
088 *
089 * @param method whose bytecode to be queried
090 * @param bcpoint the bytecode index which is the interesting point
091 * at the mean time, we only support one PC.
092 * @return whether the pc is a valid program point of the method
093 */
094 public boolean computeLocalStackTypes(NormalMethod method, int bcpoint) {
095 if (VM.TraceOnStackReplacement) {
096 VM.sysWrite("computing local and stack types of " + method + "\n");
097 }
098
099 int localsize = method.getLocalWords();
100 ltypes = new byte[localsize];
101
102 if (VM.TraceOnStackReplacement) {
103 VM.sysWrite("local size : ");
104 VM.sysWrite(localsize);
105 VM.sysWrite("\n");
106 }
107
108 retaddr = new int[localsize];
109 for (int i = 0; i < localsize; i++) {
110 retaddr[i] = -1;
111 }
112 addr = -1;
113
114 int stacksize = method.getOperandWords();
115 stypes = new byte[stacksize];
116
117 /* set marks for each byte code. */
118 // always operate on original method
119 this.bytecodes = method.getBytecodes();
120
121 visitedpc = new byte[bytecodes.length()];
122
123 /* then we initialize all stack and local type as void. */
124 for (int i = 0, n = ltypes.length; i < n; i++) {
125 ltypes[i] = VoidTypeCode;
126 }
127
128 TypeStack simstacks = new TypeStack(stacksize, VoidTypeCode);
129
130 /* initialize local types from method signature.*/
131 {
132 TypeReference[] ptypes = method.getParameterTypes();
133 int lidx = 0;
134 if (!method.isStatic()) {
135 ltypes[lidx++] = ClassTypeCode;
136 }
137 for (int i = 0, n = ptypes.length; i < n; i++) {
138 byte tcode = ptypes[i].getName().parseForTypeCode();
139 ltypes[lidx++] = tcode;
140 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
141 ltypes[lidx++] = VoidTypeCode;
142 }
143 }
144 }
145
146 /* scan start from method entry */
147 boolean found = scanBlocks(method, bytecodes, true, bcpoint, ltypes, stypes, 0, simstacks, null);
148 /* scan for exception handler. */
149 if (!found) {
150 ExceptionHandlerMap ehmap = method.getExceptionHandlerMap();
151 if (ehmap != null) {
152 int[] handlerPCs = ehmap.getHandlerPC();
153 for (int i = 0, n = handlerPCs.length; i < n; i++) {
154 simstacks.clear();
155 simstacks.push(ClassTypeCode);
156 int startpc = handlerPCs[i];
157 found = scanBlocks(method, bytecodes, true, bcpoint, ltypes, stypes, startpc, simstacks, null);
158 if (found) {
159 break;
160 }
161 }
162 }
163 }
164 visitedpc = null;
165
166 return true;
167 }
168
169 /**
170 * Returns an array of type information of locals at the registered
171 * program point. The size of array is fixed by MAX_LOCALS, the type
172 * descriptor can be found in "ClassLoadConstants.java".
173 *
174 * @return an array of type information, or null
175 */
176 public byte[] getLocalTypes() {
177 return ltypes;
178 }
179
180 /**
181 * Returns an array of type information of stacks at a program
182 * point. The size of array is fixed by MAX_STACKS, the type
183 * descriptor can be found in "ClassLoadConstants.java".
184 *
185 * @return an array of type information, or null
186 */
187 public byte[] getStackTypes() {
188 return stypes;
189 }
190
191 //////////////////////////
192 // COMPUTE STACK HEIGHTS
193 //////////////////////////
194 public void computeStackHeights(NormalMethod method, BytecodeStream bcodes, int[] stackHeights,
195 boolean adjustExptable) {
196 if (VM.TraceOnStackReplacement) {
197 VM.sysWriteln("computing stack heights of method " + method.toString());
198 }
199
200 /* set marks for each byte code. */
201 // this may be the specialized method
202 bytecodes = bcodes;
203 visitedpc = new byte[bytecodes.length()];
204
205 int localsize = method.getLocalWords();
206 retaddr = new int[localsize];
207 for (int i = 0; i < localsize; i++) {
208 retaddr[i] = -1;
209 }
210 addr = -1;
211
212 int stacksize = method.getOperandWords();
213 TypeStack simstacks = new TypeStack(stacksize, VoidTypeCode);
214
215 /* scan start from method entry */
216 {
217 int startpc = 0;
218 scanBlocks(method, bytecodes, false, -1, null, null, startpc, simstacks, stackHeights);
219 }
220 /* scan for exception handler. */
221 {
222 ExceptionHandlerMap ehmap = method.getExceptionHandlerMap();
223 if (ehmap != null) {
224 int[] handlerPCs = ehmap.getHandlerPC();
225
226 for (int i = 0, n = handlerPCs.length; i < n; i++) {
227 int startpc = handlerPCs[i];
228
229 /* for baseline compilation, the SpecialCompiler
230 * didnot adjust exception table, we has to adjust it
231 * here.
232 */
233 if (adjustExptable && method.isForOsrSpecialization()) {
234 startpc += method.getOsrPrologueLength();
235 }
236
237 simstacks.clear();
238 simstacks.push(ClassTypeCode);
239 scanBlocks(method, bytecodes, false, -1, null, null, startpc, simstacks, stackHeights);
240 }
241 }
242 }
243 visitedpc = null;
244 }
245
246 /**
247 * Compute stack heights of bytecode stream (used for osr prologue)
248 */
249 public void prologueStackHeights(NormalMethod method, BytecodeStream bcodes, int[] stackHeights) {
250 if (VM.TraceOnStackReplacement) {
251 VM.sysWriteln("computing stack heights of method " + method.toString());
252 }
253
254 /* set marks for each byte code. */
255 // this may be the specialized method
256 bytecodes = bcodes;
257 visitedpc = new byte[bytecodes.length()];
258
259 ignoreGotos = true;
260
261 int localsize = method.getLocalWords();
262 retaddr = new int[localsize];
263 for (int i = 0; i < localsize; i++) {
264 retaddr[i] = -1;
265 }
266 addr = -1;
267
268 int stacksize = method.getOperandWords();
269 TypeStack simstacks = new TypeStack(stacksize, VoidTypeCode);
270
271 /* scan start from method entry */
272 {
273 int startpc = 0;
274 scanBlocks(method, bytecodes, false, -1, null, null, startpc, simstacks, stackHeights);
275 }
276 visitedpc = null;
277 }
278
279 /* returns type code of the return type from the signature.
280 * SEE also : Atom.parseForReturnType
281 */
282 @SuppressWarnings("unused")
283 private byte getReturnCodeFromSignature(String sig) {
284 byte[] val = sig.getBytes();
285
286 int i = 0;
287 while (val[i++] != ')') ;
288 return (val[i]);
289 }
290
291 ////////////////////////////
292 // IMPLEMENTATION
293 ///////////////////////////
294
295 /* return true --> hit the bytecode pointed by PC */
296
297 private boolean scanBlocks(NormalMethod method, // which method
298 BytecodeStream bytecodes, // the bytecodes
299 boolean doDFS, // do a DFS or one-pass scan
300 int pcs, // the target pcs, if doDFS
301 byte[] ltypes, // the local types if doDFS
302 byte[] stypes, // the stack types if doDFS
303 int startpc, // start pc
304 TypeStack S, // stack
305 int[] stackHeights) { // the stack height if not doDFS
306
307 int localsize = method.getLocalWords() - 1;
308 RVMClass declaringClass = method.getDeclaringClass();
309 bytecodes.reset(startpc);
310
311 boolean found = false;
312
313 while (bytecodes.hasMoreBytecodes()) {
314 int pc = bytecodes.index(); // get current pc
315 if (visitedpc[pc] == 1) {
316 return false;
317 } else {
318 visitedpc[pc] = 1;
319 }
320
321 if (doDFS && (pc == pcs)) {
322 /* make a copy of stack frame and put into stypes. */
323 byte[] stack = S.snapshot();
324 System.arraycopy(stack, 0, stypes, 0, stack.length);
325 return true;
326 }
327
328 if (!doDFS) {
329 // record stack heights
330 stackHeights[pc] = localsize + S.depth();
331 }
332
333 /* let's continue */
334 int bcode = bytecodes.nextInstruction();
335
336 if (TRACE) {
337 if (bcode <= JBC_jsr_w) {
338 VM.sysWriteln(pc + " : " + S.depth() + " : " + JBC_name[bcode]);
339 } else {
340 VM.sysWriteln(pc + " : " + S.depth() + " : impdep1");
341 }
342 }
343
344 switch (bcode) {
345 case JBC_nop:
346 break;
347 case JBC_aconst_null:
348 S.push(ClassTypeCode);
349 break;
350 case JBC_iconst_m1:
351 case JBC_iconst_0:
352 case JBC_iconst_1:
353 case JBC_iconst_2:
354 case JBC_iconst_3:
355 case JBC_iconst_4:
356 case JBC_iconst_5:
357 S.push(IntTypeCode);
358 break;
359 case JBC_lconst_0:
360 case JBC_lconst_1:
361 /* we should do the save order as opt compiler */
362 S.push(VoidTypeCode);
363 S.push(LongTypeCode);
364 break;
365 case JBC_fconst_0:
366 case JBC_fconst_1:
367 case JBC_fconst_2:
368 S.push(FloatTypeCode);
369 break;
370 case JBC_dconst_0:
371 case JBC_dconst_1:
372 S.push(VoidTypeCode);
373 S.push(DoubleTypeCode);
374 break;
375 case JBC_bipush:
376 bytecodes.getByteValue();
377 S.push(IntTypeCode);
378 break;
379 case JBC_sipush:
380 bytecodes.getShortValue();
381 S.push(IntTypeCode);
382 break;
383 case JBC_ldc:
384 case JBC_ldc_w: {
385 int cpoolidx = (bcode == JBC_ldc) ? bytecodes.getConstantIndex() : bytecodes.getWideConstantIndex();
386 byte tdesc = declaringClass.getLiteralDescription(cpoolidx);
387 switch (tdesc) {
388 case CP_INT:
389 S.push(IntTypeCode);
390 break;
391 case CP_FLOAT:
392 S.push(FloatTypeCode);
393 break;
394 case CP_STRING:
395 S.push(ClassTypeCode);
396 break;
397 case CP_CLASS:
398 S.push(ClassTypeCode);
399 break;
400 default:
401 if (VM.TraceOnStackReplacement) VM.sysWriteln("ldc unknown type " + tdesc);
402 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
403 break;
404 } // end of switch
405 }
406 break;
407 case JBC_ldc2_w: {
408 int cpoolidx = bytecodes.getWideConstantIndex();
409 byte tdesc = declaringClass.getLiteralDescription(cpoolidx);
410 S.push(VoidTypeCode);
411 switch (tdesc) {
412 case CP_LONG:
413 S.push(LongTypeCode);
414 break;
415 case CP_DOUBLE:
416 S.push(DoubleTypeCode);
417 break;
418 default:
419 if (VM.TraceOnStackReplacement) VM.sysWriteln("ldc2_w unknown type " + tdesc);
420 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
421 break;
422 } // end of switch
423 }
424 break;
425 case JBC_iload:
426 bytecodes.getLocalNumber(); // skip local
427 S.push(IntTypeCode);
428 break;
429 case JBC_lload:
430 bytecodes.getLocalNumber(); // skip local
431 S.push(VoidTypeCode);
432 S.push(LongTypeCode);
433 break;
434 case JBC_fload:
435 bytecodes.getLocalNumber(); // skip local
436 S.push(FloatTypeCode);
437 break;
438 case JBC_dload:
439 bytecodes.getLocalNumber();
440 S.push(VoidTypeCode);
441 S.push(DoubleTypeCode);
442 break;
443 case JBC_aload:
444 bytecodes.getLocalNumber();
445 S.push(ClassTypeCode);
446 break;
447 case JBC_iload_0:
448 case JBC_iload_1:
449 case JBC_iload_2:
450 case JBC_iload_3:
451 S.push(IntTypeCode);
452 break;
453 case JBC_lload_0:
454 case JBC_lload_1:
455 case JBC_lload_2:
456 case JBC_lload_3:
457 S.push(VoidTypeCode);
458 S.push(LongTypeCode);
459 break;
460 case JBC_fload_0:
461 case JBC_fload_1:
462 case JBC_fload_2:
463 case JBC_fload_3:
464 S.push(FloatTypeCode);
465 break;
466 case JBC_dload_0:
467 case JBC_dload_1:
468 case JBC_dload_2:
469 case JBC_dload_3:
470 S.push(VoidTypeCode);
471 S.push(DoubleTypeCode);
472 break;
473 case JBC_aload_0:
474 case JBC_aload_1:
475 case JBC_aload_2:
476 case JBC_aload_3:
477 S.push(ClassTypeCode);
478 break;
479 case JBC_iaload:
480 case JBC_baload:
481 case JBC_caload:
482 case JBC_saload:
483 S.pop();
484 S.pop();
485 S.push(IntTypeCode);
486 break;
487 case JBC_laload:
488 S.pop();
489 S.pop();
490 S.push(VoidTypeCode);
491 S.push(LongTypeCode);
492 break;
493 case JBC_faload:
494 S.pop();
495 S.pop();
496 S.push(FloatTypeCode);
497 break;
498 case JBC_daload:
499 S.pop();
500 S.pop();
501 S.push(VoidTypeCode);
502 S.push(DoubleTypeCode);
503 break;
504 case JBC_aaload:
505 S.pop();
506 S.pop();
507 S.push(ClassTypeCode);
508 break;
509 case JBC_istore: {
510 S.pop();
511 int index = bytecodes.getLocalNumber();
512 if (doDFS) ltypes[index] = IntTypeCode;
513 }
514 break;
515 case JBC_istore_0:
516 case JBC_istore_1:
517 case JBC_istore_2:
518 case JBC_istore_3: {
519 S.pop();
520 int index = bcode - JBC_istore_0;
521 if (doDFS) ltypes[index] = IntTypeCode;
522 }
523 break;
524 case JBC_lstore: {
525 S.pop();
526 S.pop();
527 int index = bytecodes.getLocalNumber();
528 if (doDFS) {
529 ltypes[index] = LongTypeCode;
530 ltypes[index + 1] = VoidTypeCode;
531 }
532 }
533 break;
534 case JBC_lstore_0:
535 case JBC_lstore_1:
536 case JBC_lstore_2:
537 case JBC_lstore_3: {
538 S.pop();
539 S.pop();
540 int index = bcode - JBC_lstore_0;
541 if (doDFS) {
542 ltypes[index] = LongTypeCode;
543 ltypes[index + 1] = VoidTypeCode;
544 }
545 }
546 break;
547 case JBC_fstore: {
548 S.pop();
549 int index = bytecodes.getLocalNumber();
550 if (doDFS) ltypes[index] = FloatTypeCode;
551 }
552 break;
553 case JBC_fstore_0:
554 case JBC_fstore_1:
555 case JBC_fstore_2:
556 case JBC_fstore_3: {
557 S.pop();
558 int index = bcode - JBC_fstore_0;
559 if (doDFS) ltypes[index] = FloatTypeCode;
560 }
561 break;
562 case JBC_dstore: {
563 S.pop();
564 S.pop();
565 int index = bytecodes.getLocalNumber();
566 if (doDFS) {
567 ltypes[index] = DoubleTypeCode;
568 ltypes[index + 1] = VoidTypeCode;
569 }
570 }
571 break;
572 case JBC_dstore_0:
573 case JBC_dstore_1:
574 case JBC_dstore_2:
575 case JBC_dstore_3: {
576 S.pop();
577 S.pop();
578 int index = bcode - JBC_dstore_0;
579 if (doDFS) {
580 ltypes[index] = DoubleTypeCode;
581 ltypes[index + 1] = VoidTypeCode;
582 }
583 }
584 break;
585 case JBC_astore: {
586 // caution: astore may save return address type
587 int index = bytecodes.getLocalNumber();
588 byte tcode = S.pop();
589
590 if (doDFS) ltypes[index] = tcode;
591
592 // for ret address.
593 if (tcode == ReturnAddressTypeCode) {
594 retaddr[index] = addr;
595 addr = -1;
596 }
597 }
598 break;
599 case JBC_astore_0:
600 case JBC_astore_1:
601 case JBC_astore_2:
602 case JBC_astore_3: {
603 // caution: astore may save return address type
604 int index = bcode - JBC_astore_0;
605 byte tcode = S.pop();
606
607 if (doDFS) ltypes[index] = tcode;
608
609 // for ret address.
610 if (tcode == ReturnAddressTypeCode) {
611 retaddr[index] = addr;
612 addr = -1;
613 }
614 }
615 break;
616 case JBC_iastore:
617 case JBC_bastore:
618 case JBC_castore:
619 case JBC_sastore:
620 S.pop(3);
621 break;
622 case JBC_lastore:
623 S.pop(4);
624 break;
625 case JBC_fastore:
626 S.pop(3);
627 break;
628 case JBC_dastore:
629 S.pop(4);
630 break;
631 case JBC_aastore:
632 S.pop(3);
633 break;
634 case JBC_pop:
635 S.pop();
636 break;
637 case JBC_pop2:
638 S.pop(2);
639 break;
640 case JBC_dup: {
641 byte v1 = S.peek();
642 S.push(v1);
643 }
644 break;
645 case JBC_dup_x1: {
646 byte v1 = S.peek();
647 S.pop();
648 byte v2 = S.peek();
649 S.pop();
650 S.push(v1);
651 S.push(v2);
652 S.push(v1);
653 }
654 break;
655 case JBC_dup_x2: {
656 byte v1 = S.peek();
657 S.pop();
658 byte v2 = S.peek();
659 S.pop();
660 byte v3 = S.peek();
661 S.pop();
662 S.push(v1);
663 S.push(v3);
664 S.push(v2);
665 S.push(v1);
666 }
667 break;
668 case JBC_dup2: {
669 byte v1 = S.peek();
670 S.pop();
671 byte v2 = S.peek();
672 S.push(v1);
673 S.push(v2);
674 S.push(v1);
675 }
676 break;
677 case JBC_dup2_x1: {
678 byte v1 = S.peek();
679 S.pop();
680 byte v2 = S.peek();
681 S.pop();
682 byte v3 = S.peek();
683 S.pop();
684 S.push(v2);
685 S.push(v1);
686 S.push(v3);
687 S.push(v2);
688 S.push(v1);
689 }
690 break;
691 case JBC_dup2_x2: {
692 byte v1 = S.peek();
693 S.pop();
694 byte v2 = S.peek();
695 S.pop();
696 byte v3 = S.peek();
697 S.pop();
698 byte v4 = S.peek();
699 S.pop();
700 S.push(v2);
701 S.push(v1);
702 S.push(v4);
703 S.push(v3);
704 S.push(v2);
705 S.push(v1);
706 }
707 break;
708 case JBC_swap: {
709 byte v1 = S.peek();
710 S.pop();
711 byte v2 = S.peek();
712 S.pop();
713 S.push(v1);
714 S.push(v2);
715 }
716 break;
717 case JBC_iadd:
718 case JBC_isub:
719 case JBC_imul:
720 case JBC_idiv:
721 case JBC_irem:
722 case JBC_iand:
723 case JBC_ior:
724 case JBC_ixor:
725 case JBC_ishl:
726 case JBC_ishr:
727 case JBC_iushr:
728 S.pop();
729 break;
730 case JBC_ladd:
731 case JBC_lsub:
732 case JBC_lmul:
733 case JBC_ldiv:
734 case JBC_lrem:
735 case JBC_land:
736 case JBC_lor:
737 case JBC_lxor:
738 S.pop(2);
739 break;
740 case JBC_lshl:
741 case JBC_lshr:
742 case JBC_lushr:
743 S.pop();
744 break;
745 case JBC_fadd:
746 case JBC_fsub:
747 case JBC_fmul:
748 case JBC_fdiv:
749 case JBC_frem:
750 S.pop();
751 break;
752 case JBC_dadd:
753 case JBC_dsub:
754 case JBC_dmul:
755 case JBC_ddiv:
756 case JBC_drem:
757 S.pop(2);
758 break;
759 case JBC_ineg:
760 case JBC_lneg:
761 case JBC_fneg:
762 case JBC_dneg:
763 break;
764 case JBC_iinc: {
765 int index = bytecodes.getLocalNumber();
766 /* int value = */
767 bytecodes.getIncrement();
768 if (doDFS) ltypes[index] = IntTypeCode;
769 }
770 break;
771 case JBC_i2l:
772 S.pop();
773 S.push(VoidTypeCode);
774 S.push(LongTypeCode);
775 break;
776 case JBC_i2f:
777 S.pop();
778 S.push(FloatTypeCode);
779 break;
780 case JBC_i2d:
781 S.pop();
782 S.push(VoidTypeCode);
783 S.push(DoubleTypeCode);
784 break;
785 case JBC_l2i:
786 S.pop(2);
787 S.push(IntTypeCode);
788 break;
789 case JBC_l2f:
790 S.pop(2);
791 S.push(FloatTypeCode);
792 break;
793 case JBC_l2d:
794 S.pop(2);
795 S.push(VoidTypeCode);
796 S.push(DoubleTypeCode);
797 break;
798 case JBC_f2i:
799 S.pop();
800 S.push(IntTypeCode);
801 break;
802 case JBC_f2l:
803 S.pop();
804 S.push(VoidTypeCode);
805 S.push(LongTypeCode);
806 break;
807 case JBC_f2d:
808 S.pop();
809 S.push(VoidTypeCode);
810 S.push(DoubleTypeCode);
811 break;
812 case JBC_d2i:
813 S.pop(2);
814 S.push(IntTypeCode);
815 break;
816 case JBC_d2l:
817 S.pop(2);
818 S.push(VoidTypeCode);
819 S.push(LongTypeCode);
820 break;
821 case JBC_d2f:
822 S.pop(2);
823 S.push(FloatTypeCode);
824 break;
825 case JBC_int2byte:
826 case JBC_int2char:
827 case JBC_int2short:
828 break;
829 case JBC_lcmp:
830 S.pop(4);
831 S.push(IntTypeCode);
832 break;
833 case JBC_fcmpl:
834 case JBC_fcmpg:
835 S.pop(2);
836 S.push(IntTypeCode);
837 break;
838 case JBC_dcmpl:
839 case JBC_dcmpg:
840 S.pop(4);
841 S.push(IntTypeCode);
842 break;
843 case JBC_ifeq:
844 case JBC_ifne:
845 case JBC_iflt:
846 case JBC_ifge:
847 case JBC_ifgt:
848 case JBC_ifle:
849 case JBC_ifnull:
850 case JBC_ifnonnull: {
851 S.pop();
852
853 // flowthrough first
854 int nextpc = pc + 3;
855 int target = pc + bytecodes.getBranchOffset();
856 if (doDFS) {
857 // make a copy of ltypes, stypes to pass in
858 byte[] newltypes = new byte[ltypes.length];
859 byte[] newstypes = new byte[stypes.length];
860 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
861 System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
862 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
863 if (found) {
864 // copy back the ltypes and stypes
865 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
866 System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
867
868 return true;
869 }
870 } else {
871 found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
872 }
873 bytecodes.reset(target);
874 }
875 break;
876 case JBC_if_icmpeq:
877 case JBC_if_icmpne:
878 case JBC_if_icmplt:
879 case JBC_if_icmpge:
880 case JBC_if_icmpgt:
881 case JBC_if_icmple:
882 case JBC_if_acmpeq:
883 case JBC_if_acmpne: {
884 S.pop(2);
885
886 // flowthrough first
887 int nextpc = pc + 3;
888 int target = pc + bytecodes.getBranchOffset();
889
890 if (doDFS) {
891 // make a copy of ltypes, stypes to pass in
892 byte[] newltypes = new byte[ltypes.length];
893 byte[] newstypes = new byte[stypes.length];
894 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
895 System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
896 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
897 if (found) {
898 // copy back the ltypes and stypes
899 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
900 System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
901
902 return true;
903 }
904 } else {
905 found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
906 }
907
908 bytecodes.reset(target);
909 }
910 break;
911 case JBC_goto: {
912 int offset = bytecodes.getBranchOffset();
913 if (!ignoreGotos) {
914 bytecodes.reset(pc + offset);
915 }
916 }
917 break;
918 case JBC_goto_w: {
919 int offset = bytecodes.getWideBranchOffset();
920 if (!ignoreGotos) {
921 bytecodes.reset(pc + offset);
922 }
923 }
924 break;
925 case JBC_jsr:
926 case JBC_jsr_w: {
927 // flow through firs
928 int nextpc = pc + ((bcode == JBC_jsr) ? 3 : 5);
929 int target = pc + ((bcode == JBC_jsr) ? bytecodes.getBranchOffset() : bytecodes.getWideBranchOffset());
930
931 if (doDFS) {
932 // make a copy of ltypes, stypes to pass in
933 byte[] newltypes = new byte[ltypes.length];
934 byte[] newstypes = new byte[stypes.length];
935 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
936 System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
937 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
938 if (found) {
939 // copy back the ltypes and stypes
940 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
941 System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
942
943 return true;
944 }
945 } else {
946 found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
947 }
948
949 // branch to jsr subroutine
950 // remember return address for ret.
951 addr = pc + ((bcode == JBC_jsr) ? 3 : 5);
952 S.push(ReturnAddressTypeCode);
953 bytecodes.reset(target);
954 }
955 break;
956 case JBC_ret: {
957 // the OPT compiler set local to null after _ret instruction,
958 // then we should clean it here also, otherwise it will
959 // throw a null pointer exception.
960 // HOWEVER, it is not part of JVM spec.
961 int index = bytecodes.getLocalNumber();
962
963 if (doDFS) ltypes[index] = VoidTypeCode;
964
965 /* the ret address may be saved by a PSEUDO_LoadRetAddrConstant
966 */
967 if (retaddr[index] != -1) {
968 bytecodes.reset(retaddr[index]);
969 retaddr[index] = -1;
970 } else {
971 // now we hit ret, return out
972 return false;
973 }
974 }
975 break;
976 case JBC_tableswitch: {
977 S.pop();
978 bytecodes.alignSwitch();
979 int defaultval = bytecodes.getDefaultSwitchOffset();
980 int low = bytecodes.getLowSwitchValue();
981 int high = bytecodes.getHighSwitchValue();
982
983 // write down a list of targets
984 int npairs = high - low + 1;
985 int[] offsets = new int[npairs];
986 for (int i = 0; i < npairs; i++) {
987 offsets[i] = bytecodes.getTableSwitchOffset(i);
988 }
989
990 for (int i = 0; i < npairs; i++) {
991 int tgtpc = pc + offsets[i];
992
993 if (doDFS) {
994 // make a copy of ltypes, stypes to pass in
995 byte[] newltypes = new byte[ltypes.length];
996 byte[] newstypes = new byte[stypes.length];
997
998 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
999 System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
1000 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
1001 if (found) {
1002 // copy back the ltypes and stypes
1003 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
1004 System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
1005
1006 return true;
1007 }
1008 } else {
1009 found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
1010 }
1011 }
1012
1013 // default
1014 {
1015 int tgtpc = pc + defaultval;
1016
1017 if (doDFS) {
1018 // make a copy of ltypes, stypes to pass in
1019 byte[] newltypes = new byte[ltypes.length];
1020 byte[] newstypes = new byte[stypes.length];
1021 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
1022 System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
1023 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
1024 if (found) {
1025 // copy back the ltypes and stypes
1026 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
1027 System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
1028 }
1029 } else {
1030 found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
1031 }
1032 return found;
1033 }
1034 }
1035 case JBC_lookupswitch: {
1036 S.pop(); // pop the key
1037 bytecodes.alignSwitch();
1038 int defaultval = bytecodes.getDefaultSwitchOffset();
1039 int npairs = bytecodes.getSwitchLength();
1040
1041 int[] matches = new int[npairs];
1042 int[] offsets = new int[npairs];
1043 for (int i = 0; i < npairs; i++) {
1044 matches[i] = bytecodes.getLookupSwitchValue(i);
1045 offsets[i] = bytecodes.getLookupSwitchOffset(i);
1046 }
1047
1048 for (int i = 0; i < npairs; i++) {
1049 //int match = matches[i];
1050 int offset = offsets[i];
1051
1052 int tgtpc = pc + offset;
1053
1054 if (doDFS) {
1055 // make a copy of ltypes, stypes to pass in
1056 byte[] newltypes = new byte[ltypes.length];
1057 byte[] newstypes = new byte[stypes.length];
1058
1059 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
1060 System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
1061 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
1062 if (found) {
1063 // copy back the ltypes and stypes
1064 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
1065 System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
1066
1067 return true;
1068 }
1069 } else {
1070 found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
1071 }
1072 }
1073
1074 // default
1075 {
1076 int tgtpc = pc + defaultval;
1077
1078 if (doDFS) {
1079 // make a copy of ltypes, stypes to pass in
1080 byte[] newltypes = new byte[ltypes.length];
1081 byte[] newstypes = new byte[stypes.length];
1082
1083 System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
1084 System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
1085 found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
1086 if (found) {
1087 // copy back the ltypes and stypes
1088 System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
1089 System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
1090 }
1091 } else {
1092 found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
1093 }
1094 }
1095 }
1096 return found;
1097 case JBC_ireturn:
1098 S.pop();
1099 return false;
1100 case JBC_lreturn:
1101 S.pop(2);
1102 return false;
1103 case JBC_freturn:
1104 S.pop();
1105 return false;
1106 case JBC_dreturn:
1107 S.pop(2);
1108 return false;
1109 case JBC_areturn:
1110 S.pop();
1111 return false;
1112 case JBC_return:
1113 return false;
1114 case JBC_getfield:
1115 S.pop();
1116 case JBC_getstatic: {
1117 FieldReference fieldRef = bytecodes.getFieldReference();
1118 TypeReference ftype = fieldRef.getFieldContentsType();
1119 byte tcode = ftype.getName().parseForTypeCode();
1120 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
1121 S.push(VoidTypeCode);
1122 }
1123 S.push(tcode);
1124 }
1125 break;
1126 case JBC_putstatic: {
1127 FieldReference fieldRef = bytecodes.getFieldReference();
1128 TypeReference ftype = fieldRef.getFieldContentsType();
1129 byte tcode = ftype.getName().parseForTypeCode();
1130 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
1131 S.pop(2);
1132 } else {
1133 S.pop();
1134 }
1135 }
1136 break;
1137 case JBC_putfield: {
1138 FieldReference fieldRef = bytecodes.getFieldReference();
1139 TypeReference ftype = fieldRef.getFieldContentsType();
1140 byte tcode = ftype.getName().parseForTypeCode();
1141 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
1142 S.pop(2);
1143 } else {
1144 S.pop();
1145 }
1146 }
1147 S.pop();
1148 break;
1149 case JBC_invokevirtual:
1150 case JBC_invokespecial:
1151 case JBC_invokestatic:
1152 case JBC_invokeinterface: {
1153 MethodReference callee = bytecodes.getMethodReference();
1154
1155 int psize = callee.getParameterWords();
1156
1157 S.pop(psize);
1158
1159 if (bcode != JBC_invokestatic) {
1160 S.pop(); // pop the object reference
1161 }
1162
1163 TypeReference rtype = callee.getReturnType();
1164 byte tcode = rtype.getName().parseForTypeCode();
1165
1166 if (tcode == VoidTypeCode) {
1167 // nothing to do with void return type
1168 } else {
1169 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
1170 S.push(VoidTypeCode);
1171 }
1172 S.push(tcode);
1173 }
1174
1175 if (bcode == JBC_invokeinterface) {
1176 bytecodes.alignInvokeInterface();
1177 }
1178 }
1179 break;
1180 case JBC_xxxunusedxxx:
1181 break;
1182
1183 case JBC_new:
1184 bytecodes.getTypeReference(); // skip cpi of type
1185 S.push(ClassTypeCode);
1186 break;
1187 case JBC_newarray:
1188 S.pop();
1189 S.push(ArrayTypeCode);
1190 bytecodes.getArrayElementType(); // skip cpi of element type
1191 break;
1192 case JBC_anewarray:
1193 S.pop();
1194 S.push(ArrayTypeCode);
1195 bytecodes.getTypeReference(); // skip cpi of reference type
1196 break;
1197 case JBC_arraylength:
1198 S.pop();
1199 S.push(IntTypeCode);
1200 break;
1201 case JBC_athrow:
1202 S.clear();
1203 S.push(ClassTypeCode);
1204 return false;
1205 case JBC_checkcast:
1206 bytecodes.getTypeReference(); // skip cpi of reference type
1207 break;
1208 case JBC_instanceof:
1209 S.pop();
1210 S.push(IntTypeCode);
1211 bytecodes.getTypeReference(); // skip cpi of reference type
1212 break;
1213 case JBC_monitorenter:
1214 case JBC_monitorexit:
1215 S.pop();
1216 break;
1217 case JBC_wide: {
1218 int widecode = bytecodes.getWideOpcode();
1219 int index = bytecodes.getWideLocalNumber();
1220 switch (widecode) {
1221 case JBC_iload:
1222 S.push(IntTypeCode);
1223 break;
1224 case JBC_lload:
1225 S.push(LongTypeCode);
1226 break;
1227 case JBC_fload:
1228 S.push(FloatTypeCode);
1229 break;
1230 case JBC_dload:
1231 S.push(DoubleTypeCode);
1232 break;
1233 case JBC_aload:
1234 S.push(ClassTypeCode);
1235 break;
1236 case JBC_istore:
1237 S.pop();
1238 if (doDFS) ltypes[index] = IntTypeCode;
1239 break;
1240 case JBC_lstore:
1241 S.pop();
1242 if (doDFS) ltypes[index] = LongTypeCode;
1243 break;
1244 case JBC_fstore:
1245 S.pop();
1246 if (doDFS) ltypes[index] = FloatTypeCode;
1247 break;
1248 case JBC_dstore:
1249 S.pop();
1250 if (doDFS) ltypes[index] = DoubleTypeCode;
1251 break;
1252 case JBC_astore: {
1253 byte tcode = S.pop();
1254 if (doDFS) ltypes[index] = tcode;
1255
1256 // for ret address.
1257 if (tcode == ReturnAddressTypeCode) {
1258 retaddr[index] = addr;
1259 addr = -1;
1260 }
1261 }
1262 break;
1263 case JBC_iinc: {
1264 bytecodes.getWideIncrement(); // skip increment
1265 if (doDFS) ltypes[index] = IntTypeCode;
1266 }
1267 break;
1268 case JBC_ret:
1269 if (doDFS) ltypes[index] = VoidTypeCode;
1270
1271 if (retaddr[index] != -1) {
1272 bytecodes.reset(retaddr[index]);
1273 retaddr[index] = -1;
1274 } else {
1275 // now we hit ret, return out
1276 return false;
1277 }
1278 break;
1279 default:
1280 if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
1281 break;
1282 }
1283 break;
1284 }
1285 case JBC_multianewarray: {
1286 bytecodes.getTypeReference(); // skip type reference
1287 int dims = bytecodes.getArrayDimension();
1288 S.pop(dims);
1289 S.push(ArrayTypeCode);
1290 }
1291 break;
1292 case JBC_impdep1: {
1293 int pseudo_opcode = bytecodes.nextPseudoInstruction();
1294 switch (pseudo_opcode) {
1295 case PSEUDO_LoadIntConst:
1296 bytecodes.readIntConst(); // skip value
1297 S.push(IntTypeCode);
1298 break;
1299 case PSEUDO_LoadLongConst:
1300 bytecodes.readLongConst(); // skip value
1301 S.push(VoidTypeCode);
1302 S.push(LongTypeCode);
1303 break;
1304 case PSEUDO_LoadWordConst:
1305 if (VM.BuildFor32Addr) {
1306 bytecodes.readIntConst();
1307 } else {
1308 bytecodes.readLongConst(); // skip value
1309 }
1310 S.push(WordTypeCode);
1311 break;
1312 case PSEUDO_LoadFloatConst:
1313 bytecodes.readIntConst(); // skip value
1314 S.push(FloatTypeCode);
1315 break;
1316 case PSEUDO_LoadDoubleConst:
1317 bytecodes.readLongConst(); // skip value
1318 S.push(VoidTypeCode);
1319 S.push(DoubleTypeCode);
1320 break;
1321 case PSEUDO_LoadRetAddrConst:
1322 // remember the address for ret.
1323 addr = bytecodes.readIntConst(); // get address
1324 S.push(ReturnAddressTypeCode);
1325 break;
1326 case PSEUDO_InvokeStatic: {
1327 int mid = bytecodes.readIntConst(); // get METHIDX
1328 RVMMethod callee = InvokeStatic.targetMethod(mid);
1329
1330 int psize = callee.getParameterWords();
1331 S.pop(psize);
1332
1333 TypeReference rtype = callee.getReturnType();
1334 byte tcode = rtype.getName().parseForTypeCode();
1335
1336 if (tcode == VoidTypeCode) {
1337 // nothing to do with void return type
1338 } else {
1339 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
1340 S.push(VoidTypeCode);
1341 }
1342 S.push(tcode);
1343 }
1344 break;
1345 }
1346 /*
1347 case PSEUDO_CheckCast:
1348 bytecodes.readIntConst(); // skip type id
1349 break;
1350 */
1351 case PSEUDO_InvokeCompiledMethod:
1352 int cmid = bytecodes.readIntConst(); // cmid
1353 bytecodes.readIntConst(); // skip bcindex
1354
1355 RVMMethod callee = CompiledMethods.getCompiledMethod(cmid).getMethod();
1356 int psize = callee.getParameterWords();
1357
1358 S.pop(psize);
1359
1360 if (!callee.isStatic()) {
1361 S.pop(); // pop receiver
1362 }
1363
1364 TypeReference rtype = callee.getReturnType();
1365 byte tcode = rtype.getName().parseForTypeCode();
1366
1367 if (tcode == VoidTypeCode) {
1368 // nothing to do with void return type
1369 } else {
1370 if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
1371 S.push(VoidTypeCode);
1372 }
1373 S.push(tcode);
1374 }
1375 break;
1376 case PSEUDO_ParamInitEnd:
1377 break;
1378 default:
1379 if (VM.VerifyAssertions) {
1380 VM.sysWrite(" Error, no such pseudo code : " + pseudo_opcode + "\n");
1381 VM._assert(VM.NOT_REACHED);
1382 }
1383 return false;
1384 }
1385 break;
1386 }
1387 default:
1388 VM.sysWrite("Unknown bytecode : " + bcode + "\n");
1389 return false;
1390 }
1391 }
1392
1393 /* did not found the PC. */
1394 return false;
1395 }
1396 }
1397