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