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