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 */
013package org.jikesrvm.compilers.baseline;
014
015import static org.jikesrvm.classloader.BytecodeConstants.*;
016import static org.jikesrvm.classloader.ClassLoaderConstants.CP_CLASS;
017import static org.jikesrvm.classloader.ClassLoaderConstants.CP_STRING;
018import static org.jikesrvm.compilers.baseline.BBConstants.ADDRESS_TYPE;
019import static org.jikesrvm.compilers.baseline.BBConstants.DOUBLE_TYPE;
020import static org.jikesrvm.compilers.baseline.BBConstants.FLOAT_TYPE;
021import static org.jikesrvm.compilers.baseline.BBConstants.INT_TYPE;
022import static org.jikesrvm.compilers.baseline.BBConstants.LONG_TYPE;
023
024import org.jikesrvm.VM;
025import org.jikesrvm.classloader.BytecodeStream;
026import org.jikesrvm.classloader.ExceptionHandlerMap;
027import org.jikesrvm.classloader.MethodReference;
028import org.jikesrvm.classloader.NormalMethod;
029import org.jikesrvm.classloader.TypeReference;
030
031/**
032 * This class builds the reference and non-reference maps for a given method.
033 * The maps are recorded with ReferenceMaps. This class works with the baseline
034 * compiler, calculating the maps for local variables (including parameters),
035 * and the java operand stack. Given the basic blocks mapped out by BuildBB
036 * determine for each GC point (call sites and new's, etc) what the stack and
037 * variable maps are. Note that this class deals with reference maps (the term
038 * "stack maps" was not used as it is too ambiguous - does "stack" refer to the
039 * java operand stack or a C-like stack?; when processing java bytecodes it
040 * seemed best to use "stack" for java operand stack.)
041 */
042final class BuildReferenceMaps {
043
044  /**
045   * The entry in the reference map contains a value that is not a reference.
046   */
047  static final byte NON_REFERENCE = 0;
048  /**
049   * The entry in the reference map contains a value that is a reference.
050   */
051  static final byte REFERENCE = 1;
052  /**
053   * The entry in the reference map contains a JSR return address.
054   */
055  static final byte RETURN_ADDRESS = 2;
056  /**
057   * The entry in the reference map is not set in a JSR body.
058   */
059  static final byte NOT_SET = 0;
060  /**
061   * The entry in the reference map is set to a value that is a reference within a JSR body.
062   */
063  static final byte SET_TO_REFERENCE = 1;
064  /**
065   * The entry in the reference map is set to a value that is not a reference within a JSR body.
066   */
067  static final byte SET_TO_NONREFERENCE = 3;
068
069  private enum PrimitiveSize {
070    ONEWORD, DOUBLEWORD
071  };
072
073  // These two variables are used and updated by more than one method in this class,
074  // therefore they need to be instance variables;
075  int workStkTop;
076  int JSRSubNext;
077
078  /**
079   * After the analysis of the blocks of a method, examine the byte codes again, to
080   * determine the reference maps for the gc points. Record the maps with
081   * referenceMaps.
082   *
083   * @param method the method whose bytecodes are to be examined again
084   * @param stackHeights height of the expression stack at each bytecode
085   * @param localTypes the types that the locals can take
086   * @param referenceMaps the reference map. NB: the map's constructor is still running
087   *  while this method is called!
088   * @param buildBB the buildBB instance that contains the results from the
089   *  previous analysis
090   *
091   * @see BaselineCompiler#localTypes
092   * @see TemplateCompilerFramework#stackHeights
093   */
094  public void buildReferenceMaps(NormalMethod method, int[] stackHeights, byte[] localTypes,
095                                 ReferenceMaps referenceMaps, BuildBB buildBB) {
096    //****************************************************************//
097    // These were calculated by BuildBB.determineTheBasicBlocks    //
098    //****************************************************************//
099    int gcPointCount = buildBB.gcPointCount;
100    short[] byteToBlockMap = buildBB.byteToBlockMap;
101    BasicBlock[] basicBlocks = buildBB.basicBlocks;
102    int jsrCount = buildBB.numJsrs;
103
104    byte[][] bbMaps;            // The starting map for each block, a block is not
105    // processed until it has a starting map.
106    int[] blockStkTop;           // For each block, track where its current stack top is.
107
108    int currBBNum;             // Block number of block currently being processed
109    byte[] currBBMap;           // The current map, used during processing thru a block
110    int currBBStkTop;          // Stack top for the current map
111
112    final int currBBStkEmpty;  // Level when stack is empty - value depends on number of locals
113    int paramCount;            // Number of parameters to the method being processed
114
115    // Variables for processing JSR instructions, RET instructions and JSR subroutines
116    PendingRETInfo[] bbPendingRETs = null;
117    PendingRETInfo currPendingRET;
118    JSRSubroutineInfo[] JSRSubs = null;
119
120    // Blocks that need to be processed are put on the workStk
121    short[] workStk;
122
123    // Track whether a block has already been seen once. Any recording of maps done
124    // within such a block will be processed as a "rerecording" instead of a new map.
125    //
126    boolean[] blockSeen;
127
128    // blocks that represent "catch" blocks need special processing. Catch blocks
129    // also referred to as handlers
130    //
131    ExceptionHandlerMap exceptions;                // exception table class for method being processed
132    int[] tryStartPC;              // array of try start indicesinto byte code table
133    int[] tryEndPC;                // array of try end indices into byte code table
134    int[] tryHandlerPC;            // array of try handlers start indices into bytecode
135    int tryHandlerLength;          // length of try handlers array
136    int[] reachableHandlerBBNums;  // array of reachable handlers from a given try block
137    int reachableHandlersCount;    // Number of reachable handlers
138    boolean[] handlerProcessed;        // Handler blocks are processed after the normal flow. As
139    // they may be nested, they need to be handled
140    // individually. This array is used to track which
141    // have been processed.
142    boolean handlersAllDone;
143
144    // Other local variables
145    //
146    BytecodeStream bcodes;                // byte codes for the method
147    short brBBNum;               // For processing branches, need block number of target
148
149    final boolean debug = false;
150
151    // Note that the mapping done here is "double mapping" of parameters.
152    // Double mapping is when the parameters for a method are included in the map of
153    // the method as well as in the map of the caller of the method. The original
154    // intent was that with double mapping call sites that are tricks
155    // (e.g. Magic.callFunctionReturnVoid ) would at least be correctly mapped on one
156    // of the two sides. However with more recent changes to the runtime stack frame
157    // layout, the parameters specified on the caller side occupy different
158    // locations than the parameters on the callee side for the baseline compiler.
159    // Thus both need to be described.
160
161    //
162    //  Initialization
163    //
164
165    // Determine what stack empty looks like
166    paramCount = method.getParameterWords();
167    if (!method.isStatic()) paramCount++;
168
169    currBBStkEmpty = TemplateCompilerFramework.stackHeightForEmptyBasicBlock(method);
170
171    if (debug) VM.sysWrite("getLocalWords() : " + method.getLocalWords() + "\n");
172
173    // Get information from the method being processed
174    bcodes = method.getBytecodes();
175
176    // Set up the array of maps per block; block 0 is not used
177    int numBB = buildBB.bbf.getNumberofBlocks();
178    bbMaps = new byte[numBB + 1][];
179    blockStkTop = new int[bbMaps.length];
180    blockSeen = new boolean[bbMaps.length];
181
182    // Try Handler processing initialization
183
184    exceptions = method.getExceptionHandlerMap();
185    if (exceptions != null) {
186      tryStartPC = exceptions.getStartPC();
187      tryEndPC = exceptions.getEndPC();
188      tryHandlerPC = exceptions.getHandlerPC();
189      tryHandlerLength = tryHandlerPC.length;
190
191      reachableHandlerBBNums = new int[tryStartPC.length];
192      handlerProcessed = new boolean[tryStartPC.length];
193      if (jsrCount > 0) {
194        JSRSubs = new JSRSubroutineInfo[jsrCount];
195        JSRSubNext = 0;
196        bbPendingRETs = new PendingRETInfo[bbMaps.length];
197      }
198      handlersAllDone = (tryHandlerLength == 0);
199
200      // write poison values to help distinguish different errors
201      for (int ii = 0; ii < reachableHandlerBBNums.length; ii++) {
202        reachableHandlerBBNums[ii] = -1;
203      }
204    } else {
205      tryHandlerLength = 0;
206      handlersAllDone = true;
207      tryStartPC = null;
208      tryEndPC = null;
209      tryHandlerPC = null;
210      reachableHandlerBBNums = null;
211      handlerProcessed = null;
212    }
213    reachableHandlersCount = 0;
214
215    // Start a new set of maps with the reference Map class.
216    // 3rd argument is parameter count included with the maps
217    referenceMaps.startNewMaps(gcPointCount, jsrCount, paramCount);
218
219    // Set up the Work stack
220    workStk = new short[10 + tryHandlerLength];
221
222    // Start by putting the first block on the work stack
223    workStkTop = 0;
224    workStk[workStkTop] = byteToBlockMap[0];
225    currBBMap = new byte[method.getOperandWords() + currBBStkEmpty + 1];
226
227    //
228    // Need to include the parameters of this method in the map
229    //
230    TypeReference[] parameterTypes = method.getParameterTypes();
231    int paramStart;
232    if (!method.isStatic()) {
233      currBBMap[0] = REFERENCE; // implicit "this" object
234      localTypes[0] = ADDRESS_TYPE;
235      paramStart = 1;
236    } else {
237      paramStart = 0;
238    }
239
240    for (int i = 0; i < parameterTypes.length; i++, paramStart++) {
241      TypeReference parameterType = parameterTypes[i];
242      if (parameterType.isReferenceType()) {
243        localTypes[paramStart] = ADDRESS_TYPE;
244        currBBMap[paramStart] = REFERENCE;
245      } else {
246        currBBMap[paramStart] = NON_REFERENCE;
247
248        if (parameterType.getStackWords() == 2) {
249          if (parameterType.isLongType()) {
250            localTypes[paramStart] = LONG_TYPE;
251          } else {
252            localTypes[paramStart] = DOUBLE_TYPE;
253          }
254          paramStart++;
255        } else if (parameterType.isFloatType()) {
256          localTypes[paramStart] = FLOAT_TYPE;
257        } else if (parameterType.isIntLikeType()) {
258          localTypes[paramStart] = INT_TYPE;
259        } else {
260          localTypes[paramStart] = ADDRESS_TYPE;
261        }
262      }
263    }
264
265    // The map for the start of the first block, is stack empty, with none
266    // of the locals set yet
267    //
268    currBBStkTop = currBBStkEmpty;
269    bbMaps[byteToBlockMap[0]] = currBBMap;
270    blockStkTop[byteToBlockMap[0]] = currBBStkTop;
271
272    // For all methods, record a map at the start of the method for the corresponding
273    // conditional call to "yield".
274
275    referenceMaps.recordStkMap(0, currBBMap, currBBStkTop, false);
276
277    currBBMap = new byte[currBBMap.length];
278
279    //----------------------------------------------------------
280    //
281    //  Keep looping until the Work Stack is empty
282    //
283    //----------------------------------------------------------
284    while (workStkTop > -1) {
285
286      // Get the next item off the work stack
287      currBBNum = workStk[workStkTop];
288      workStkTop--;
289
290      boolean inJSRSub = false;
291      if (bbMaps[currBBNum] != null) {
292        currBBStkTop = blockStkTop[currBBNum];
293        for (int k = 0; k <= currBBStkTop; k++) {
294          currBBMap[k] = bbMaps[currBBNum][k];
295        }
296
297        if (jsrCount > 0 && basicBlocks[currBBNum].isInJSR()) {
298          inJSRSub = true;
299        }
300      } else {
301        VM.sysWrite("BuildReferenceMaps, error: found a block on work stack with");
302        VM.sysWrite(" no starting map. The block number is ");
303        VM.sysWrite(basicBlocks[currBBNum].getBlockNumber());
304        VM.sysWrite("\n");
305        VM.sysFail("BuildReferenceMaps work stack failure");
306      }
307
308      int start = basicBlocks[currBBNum].getStart();
309      int end = basicBlocks[currBBNum].getEnd();
310
311      if (jsrCount > 0 && inJSRSub) {
312        currPendingRET = bbPendingRETs[currBBNum];
313        if (basicBlocks[currBBNum].isTryStart()) {
314          for (int k = 0; k < tryHandlerLength; k++) {
315            if (tryStartPC[k] == start) {
316              int handlerBBNum = byteToBlockMap[tryHandlerPC[k]];
317              bbPendingRETs[handlerBBNum] = new PendingRETInfo(currPendingRET);
318            }
319          }
320        }
321        if (currPendingRET == null) {
322          int[] preds = basicBlocks[currBBNum].getPredecessors();
323          for (int i = 0; i < preds.length; i++) {
324            int predBB = preds[i];
325            if (bbPendingRETs[predBB] != null) {
326              currPendingRET = bbPendingRETs[predBB];
327              break;
328            }
329          }
330        }
331        if (VM.VerifyAssertions) {
332          if (currPendingRET == null) {
333            String msg = "No pending return found in block " + currBBNum;
334            VM._assert(VM.NOT_REACHED, msg);
335          }
336        }
337      } else {
338        currPendingRET = null;
339      }
340
341      boolean inTryBlock;
342      if (basicBlocks[currBBNum].isTryBlock()) {
343        inTryBlock = true;
344        reachableHandlersCount = 0;
345        for (int i = 0; i < tryHandlerLength; i++) {
346          if (start <= tryEndPC[i] && end >= tryStartPC[i]) {
347            reachableHandlerBBNums[reachableHandlersCount] = byteToBlockMap[tryHandlerPC[i]];
348            reachableHandlersCount++;
349            int handlerBBNum = byteToBlockMap[tryHandlerPC[i]];
350            if (bbMaps[handlerBBNum] == null) {
351              bbMaps[handlerBBNum] = new byte[currBBMap.length];
352              for (int k = 0; k <= currBBStkEmpty; k++) {
353                bbMaps[handlerBBNum][k] = currBBMap[k];
354              }
355              bbMaps[handlerBBNum][currBBStkEmpty + 1] = REFERENCE;
356              blockStkTop[handlerBBNum] = currBBStkEmpty + 1;
357            } else  {
358              if (inJSRSub && basicBlocks[handlerBBNum].isInJSR()) {
359                // In JSR and handler within the same JSR.
360                // Ensure SET_TO_NONREFERENCE is carried across
361                for (int k = 0; k <= currBBStkEmpty; k++) {
362                  if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != SET_TO_NONREFERENCE) {
363                    handlerProcessed[i] = false;
364                    bbMaps[handlerBBNum][k] = SET_TO_NONREFERENCE;
365                  }
366                }
367              } else if (inJSRSub) {
368                // In JSR but handler is shared by JSR and non JSR
369                // realise JSR and SET_TO_NONREFERENCE becomes NON_REFERENCE
370                for (int k = 0; k <= currBBStkEmpty; k++) {
371                  if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) {
372                    handlerProcessed[i] = false;
373                    bbMaps[handlerBBNum][k] = NON_REFERENCE;
374                  }
375                }
376              } else {
377                // No JSRs involved, simply ensure NON_REFERENCE is carried over
378                for (int k = 0; k <= currBBStkEmpty; k++) {
379                  if (currBBMap[k] == NON_REFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) {
380                    handlerProcessed[i] = false;
381                    bbMaps[handlerBBNum][k] = NON_REFERENCE;
382                  }
383                }
384              }
385            }
386          }
387        }
388      } else {
389        inTryBlock = false;
390      }
391
392      boolean processNextBlock = true;
393
394      bcodes.reset(start);
395      while (bcodes.index() <= end) {
396        int biStart = bcodes.index();
397        int opcode = bcodes.nextInstruction();
398        if (stackHeights != null) {
399          if (VM.VerifyAssertions) {
400            if (currBBStkTop < currBBStkEmpty) {
401              String msg = "Stack height for current basic block is " +
402                  currBBStkTop + " which is less than the stack height for " +
403                  "an empty block (" + currBBStkEmpty + ").";
404              VM._assert(VM.NOT_REACHED, msg);
405            }
406          }
407          stackHeights[biStart] = currBBStkTop;
408        }
409
410        if (debug) {
411          VM.sysWrite("opcode : " + opcode + "\n");
412          VM.sysWrite("current map: ");
413          for (int j = 0; j <= currBBStkTop; j++) {
414            VM.sysWrite(currBBMap[j]);
415          }
416          VM.sysWrite("\n");
417        }
418
419        switch (opcode) {
420          case JBC_nop: {
421            break;
422          }
423          case JBC_aconst_null: {
424            currBBStkTop++;
425            currBBMap[currBBStkTop] = REFERENCE;
426            break;
427          }
428          case JBC_aload_0: {
429            int localNumber = 0;
430            currBBStkTop++;
431            currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
432            break;
433          }
434          case JBC_aload_1: {
435            int localNumber = 1;
436            currBBStkTop++;
437            currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
438            break;
439          }
440          case JBC_aload_2: {
441            int localNumber = 2;
442            currBBStkTop++;
443            currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
444            break;
445          }
446          case JBC_aload_3: {
447            int localNumber = 3;
448            currBBStkTop++;
449            currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
450            break;
451          }
452          case JBC_aload: {
453            int localNumber = bcodes.getLocalNumber();
454            currBBStkTop++;
455            currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
456            break;
457          }
458
459          case JBC_iconst_m1:
460          case JBC_iconst_0:
461          case JBC_iconst_1:
462          case JBC_iconst_2:
463          case JBC_iconst_3:
464          case JBC_iconst_4:
465          case JBC_iconst_5:
466          case JBC_fconst_0:
467          case JBC_fconst_1:
468          case JBC_fconst_2:
469          case JBC_iload_0:
470          case JBC_iload_1:
471          case JBC_iload_2:
472          case JBC_iload_3:
473          case JBC_fload_0:
474          case JBC_fload_1:
475          case JBC_fload_2:
476          case JBC_fload_3:
477          case JBC_bipush:
478          case JBC_iload:
479          case JBC_fload:
480          case JBC_sipush:
481          case JBC_i2l:
482          case JBC_i2d:
483          case JBC_f2l:
484          case JBC_f2d: {
485            currBBStkTop++;
486            currBBMap[currBBStkTop] = NON_REFERENCE;
487            bcodes.skipInstruction(); // contains mix of 1,2,3 byte bytecodes
488            break;
489          }
490
491          case JBC_lconst_0:
492          case JBC_lconst_1:
493          case JBC_dconst_0:
494          case JBC_dconst_1:
495          case JBC_lload_0:
496          case JBC_lload_1:
497          case JBC_lload_2:
498          case JBC_lload_3:
499          case JBC_dload_0:
500          case JBC_dload_1:
501          case JBC_dload_2:
502          case JBC_dload_3:
503          case JBC_ldc2_w:
504          case JBC_lload:
505          case JBC_dload: {
506            currBBStkTop++;
507            currBBMap[currBBStkTop] = NON_REFERENCE;
508            currBBStkTop++;
509            currBBMap[currBBStkTop] = NON_REFERENCE;
510            bcodes.skipInstruction(); // mix of 1, 2, and 3 byte bytecodes
511            break;
512          }
513
514          case JBC_ldc: {
515            currBBStkTop++;
516            int cpi = bcodes.getConstantIndex();
517            int type = bcodes.getConstantType(cpi);
518            if (type == CP_STRING || type == CP_CLASS) {
519              currBBMap[currBBStkTop] = REFERENCE;
520            } else {
521              currBBMap[currBBStkTop] = NON_REFERENCE;
522            }
523            break;
524          }
525          case JBC_ldc_w: {
526            currBBStkTop++;
527            int cpi = bcodes.getWideConstantIndex();
528            int type = bcodes.getConstantType(cpi);
529            if (type == CP_STRING || type == CP_CLASS) {
530              currBBMap[currBBStkTop] = REFERENCE;
531            } else {
532              currBBMap[currBBStkTop] = NON_REFERENCE;
533            }
534            break;
535          }
536
537          case JBC_istore: {
538            int index = bcodes.getLocalNumber();
539            if (!inJSRSub) {
540              currBBMap[index] = NON_REFERENCE;
541            } else {
542              currBBMap[index] = SET_TO_NONREFERENCE;
543            }
544            if (inTryBlock) {
545              setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
546            }
547            currBBStkTop--;
548            localTypes[index] |= INT_TYPE;
549            break;
550          }
551
552          case JBC_fstore: {
553            int index = bcodes.getLocalNumber();
554            if (!inJSRSub) {
555              currBBMap[index] = NON_REFERENCE;
556            } else {
557              currBBMap[index] = SET_TO_NONREFERENCE;
558            }
559            if (inTryBlock) {
560              setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
561            }
562            currBBStkTop--;
563            localTypes[index] |= FLOAT_TYPE;
564            break;
565          }
566
567          case JBC_lstore: {
568            int index = bcodes.getLocalNumber();
569            if (!inJSRSub) {
570              currBBMap[index] = NON_REFERENCE;
571              currBBMap[index + 1] = NON_REFERENCE;
572            } else {
573              currBBMap[index] = SET_TO_NONREFERENCE;
574              currBBMap[index + 1] = SET_TO_NONREFERENCE;
575            }
576
577            if (inTryBlock) {
578              setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD,
579                reachableHandlerBBNums, reachableHandlersCount, inJSRSub,
580                bbMaps);
581            }
582            currBBStkTop = currBBStkTop - 2;
583            localTypes[index] |= LONG_TYPE;
584            break;
585          }
586
587          case JBC_dstore: {
588            int index = bcodes.getLocalNumber();
589            if (!inJSRSub) {
590              currBBMap[index] = NON_REFERENCE;
591              currBBMap[index + 1] = NON_REFERENCE;
592            } else {
593              currBBMap[index] = SET_TO_NONREFERENCE;
594              currBBMap[index + 1] = SET_TO_NONREFERENCE;
595            }
596
597            if (inTryBlock) {
598              setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD,
599                reachableHandlerBBNums, reachableHandlersCount, inJSRSub,
600                bbMaps);
601            }
602            currBBStkTop = currBBStkTop - 2;
603            localTypes[index] |= DOUBLE_TYPE;
604            break;
605          }
606
607          case JBC_astore: {
608            int index = bcodes.getLocalNumber();
609            currBBMap[index] = currBBMap[currBBStkTop];// may be a reference or a return address
610            if (inJSRSub) {
611              if (currBBMap[index] == RETURN_ADDRESS) {
612                currPendingRET.updateReturnAddressLocation(index);
613              }
614              if (inTryBlock) {
615                if (currBBMap[index] == REFERENCE) {
616                  setHandlersMapsRef(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
617                } else {
618                  setHandlersMapsReturnAddress(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
619                }
620              }
621            }
622            currBBStkTop--;
623            localTypes[index] |= ADDRESS_TYPE;
624            break;
625          }
626
627          case JBC_istore_0: {
628            if (!inJSRSub) {
629              currBBMap[0] = NON_REFERENCE;
630            } else {
631              currBBMap[0] = SET_TO_NONREFERENCE;
632            }
633            if (inTryBlock) {
634              setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
635            }
636            currBBStkTop--;
637            localTypes[0] |= INT_TYPE;
638            break;
639          }
640
641          case JBC_fstore_0: {
642            if (!inJSRSub) {
643              currBBMap[0] = NON_REFERENCE;
644            } else {
645              currBBMap[0] = SET_TO_NONREFERENCE;
646            }
647            if (inTryBlock) {
648              setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
649            }
650            currBBStkTop--;
651            localTypes[0] |= FLOAT_TYPE;
652            break;
653          }
654
655          case JBC_istore_1: {
656            if (!inJSRSub) {
657              currBBMap[1] = NON_REFERENCE;
658            } else {
659              currBBMap[1] = SET_TO_NONREFERENCE;
660            }
661            if (inTryBlock) {
662              setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
663            }
664            currBBStkTop--;
665            localTypes[1] |= INT_TYPE;
666            break;
667          }
668
669          case JBC_fstore_1: {
670            if (!inJSRSub) {
671              currBBMap[1] = NON_REFERENCE;
672            } else {
673              currBBMap[1] = SET_TO_NONREFERENCE;
674            }
675            if (inTryBlock) {
676              setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
677            }
678            currBBStkTop--;
679            localTypes[1] |= FLOAT_TYPE;
680            break;
681          }
682
683          case JBC_istore_2: {
684            if (!inJSRSub) {
685              currBBMap[2] = NON_REFERENCE;
686            } else {
687              currBBMap[2] = SET_TO_NONREFERENCE;
688            }
689            if (inTryBlock) {
690              setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
691            }
692            currBBStkTop--;
693            localTypes[2] |= INT_TYPE;
694            break;
695          }
696
697          case JBC_fstore_2: {
698            if (!inJSRSub) {
699              currBBMap[2] = NON_REFERENCE;
700            } else {
701              currBBMap[2] = SET_TO_NONREFERENCE;
702            }
703            if (inTryBlock) {
704              setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
705            }
706            currBBStkTop--;
707            localTypes[2] |= FLOAT_TYPE;
708            break;
709          }
710
711          case JBC_istore_3: {
712            if (!inJSRSub) {
713              currBBMap[3] = NON_REFERENCE;
714            } else {
715              currBBMap[3] = SET_TO_NONREFERENCE;
716            }
717            if (inTryBlock) {
718              setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
719            }
720            currBBStkTop--;
721            localTypes[3] |= INT_TYPE;
722            break;
723          }
724
725          case JBC_fstore_3: {
726            if (!inJSRSub) {
727              currBBMap[3] = NON_REFERENCE;
728            } else {
729              currBBMap[3] = SET_TO_NONREFERENCE;
730            }
731            if (inTryBlock) {
732              setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
733            }
734            currBBStkTop--;
735            localTypes[3] |= FLOAT_TYPE;
736            break;
737          }
738
739          case JBC_lstore_0: {
740            if (inJSRSub) {
741              currBBMap[0] = NON_REFERENCE;
742              currBBMap[1] = NON_REFERENCE;
743            } else {
744              currBBMap[0] = SET_TO_NONREFERENCE;
745              currBBMap[1] = SET_TO_NONREFERENCE;
746            }
747            if (inTryBlock) {
748              setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
749            }
750            currBBStkTop = currBBStkTop - 2;
751            localTypes[0] |= LONG_TYPE;
752            break;
753          }
754          case JBC_dstore_0: {
755            if (inJSRSub) {
756              currBBMap[0] = NON_REFERENCE;
757              currBBMap[1] = NON_REFERENCE;
758            } else {
759              currBBMap[0] = SET_TO_NONREFERENCE;
760              currBBMap[1] = SET_TO_NONREFERENCE;
761            }
762            if (inTryBlock) {
763              setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
764            }
765            currBBStkTop = currBBStkTop - 2;
766            localTypes[0] |= DOUBLE_TYPE;
767            break;
768          }
769
770          case JBC_lstore_1: {
771            if (!inJSRSub) {
772              currBBMap[1] = NON_REFERENCE;
773              currBBMap[2] = NON_REFERENCE;
774            } else {
775              currBBMap[1] = SET_TO_NONREFERENCE;
776              currBBMap[2] = SET_TO_NONREFERENCE;
777            }
778            if (inTryBlock) {
779              setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
780            }
781            currBBStkTop = currBBStkTop - 2;
782            localTypes[1] |= LONG_TYPE;
783            break;
784          }
785
786          case JBC_dstore_1: {
787            if (!inJSRSub) {
788              currBBMap[1] = NON_REFERENCE;
789              currBBMap[2] = NON_REFERENCE;
790            } else {
791              currBBMap[1] = SET_TO_NONREFERENCE;
792              currBBMap[2] = SET_TO_NONREFERENCE;
793            }
794            if (inTryBlock) {
795              setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
796            }
797            currBBStkTop = currBBStkTop - 2;
798            localTypes[1] |= DOUBLE_TYPE;
799            break;
800          }
801
802          case JBC_lstore_2: {
803            if (!inJSRSub) {
804              currBBMap[2] = NON_REFERENCE;
805              currBBMap[3] = NON_REFERENCE;
806            } else {
807              currBBMap[2] = SET_TO_NONREFERENCE;
808              currBBMap[3] = SET_TO_NONREFERENCE;
809            }
810            if (inTryBlock) {
811              setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
812            }
813            currBBStkTop = currBBStkTop - 2;
814            localTypes[2] |= LONG_TYPE;
815            break;
816          }
817
818          case JBC_dstore_2: {
819            if (!inJSRSub) {
820              currBBMap[2] = NON_REFERENCE;
821              currBBMap[3] = NON_REFERENCE;
822            } else {
823              currBBMap[2] = SET_TO_NONREFERENCE;
824              currBBMap[3] = SET_TO_NONREFERENCE;
825            }
826            if (inTryBlock) {
827              setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
828            }
829            currBBStkTop = currBBStkTop - 2;
830            localTypes[2] |= DOUBLE_TYPE;
831            break;
832          }
833
834          case JBC_lstore_3: {
835            if (!inJSRSub) {
836              currBBMap[3] = NON_REFERENCE;
837              currBBMap[4] = NON_REFERENCE;
838            } else {
839              currBBMap[3] = SET_TO_NONREFERENCE;
840              currBBMap[4] = SET_TO_NONREFERENCE;
841            }
842            if (inTryBlock) {
843              setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
844            }
845            currBBStkTop = currBBStkTop - 2;
846            localTypes[3] |= LONG_TYPE;
847            break;
848          }
849
850          case JBC_dstore_3: {
851            if (!inJSRSub) {
852              currBBMap[3] = NON_REFERENCE;
853              currBBMap[4] = NON_REFERENCE;
854            } else {
855              currBBMap[3] = SET_TO_NONREFERENCE;
856              currBBMap[4] = SET_TO_NONREFERENCE;
857            }
858            if (inTryBlock) {
859              setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
860            }
861            currBBStkTop = currBBStkTop - 2;
862            localTypes[3] |= DOUBLE_TYPE;
863            break;
864          }
865
866          case JBC_astore_0: {
867            currBBMap[0] = currBBMap[currBBStkTop];
868            if (inJSRSub) {
869              if (currBBMap[0] == RETURN_ADDRESS) {
870                currPendingRET.updateReturnAddressLocation(0);
871              }
872              if (inTryBlock) {
873                if (currBBMap[0] == REFERENCE) {
874                  setHandlersMapsRef(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
875                } else {
876                  setHandlersMapsReturnAddress(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
877                }
878              }
879            }
880            currBBStkTop--;
881            localTypes[0] |= ADDRESS_TYPE;
882            break;
883          }
884
885          case JBC_astore_1: {
886            currBBMap[1] = currBBMap[currBBStkTop];
887            if (inJSRSub) {
888              if (currBBMap[1] == RETURN_ADDRESS) {
889                currPendingRET.updateReturnAddressLocation(1);
890              }
891              if (inTryBlock) {
892                if (currBBMap[1] == REFERENCE) {
893                  setHandlersMapsRef(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
894                } else {
895                  setHandlersMapsReturnAddress(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
896                }
897              }
898            }
899            currBBStkTop--;
900            localTypes[1] |= ADDRESS_TYPE;
901            break;
902          }
903
904          case JBC_astore_2: {
905            currBBMap[2] = currBBMap[currBBStkTop];
906            if (inJSRSub) {
907              if (currBBMap[2] == RETURN_ADDRESS) {
908                currPendingRET.updateReturnAddressLocation(2);
909              }
910              if (inTryBlock) {
911                if (currBBMap[2] == REFERENCE) {
912                  setHandlersMapsRef(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
913                } else {
914                  setHandlersMapsReturnAddress(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
915                }
916              }
917            }
918            currBBStkTop--;
919            localTypes[2] |= ADDRESS_TYPE;
920            break;
921          }
922          case JBC_astore_3: {
923            currBBMap[3] = currBBMap[currBBStkTop];
924            if (inJSRSub) {
925              if (currBBMap[3] == RETURN_ADDRESS) {
926                currPendingRET.updateReturnAddressLocation(3);
927              }
928              if (inTryBlock) {
929                if (currBBMap[3] == REFERENCE) {
930                  setHandlersMapsRef(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
931                } else {
932                  setHandlersMapsReturnAddress(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
933                }
934              }
935            }
936            currBBStkTop--;
937            localTypes[3] |= ADDRESS_TYPE;
938            break;
939          }
940
941          case JBC_dup: {
942            currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
943            currBBStkTop++;
944            break;
945          }
946          case JBC_dup2: {
947            currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
948            currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
949            currBBStkTop = currBBStkTop + 2;
950            break;
951          }
952          case JBC_dup_x1: {
953            currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
954            currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
955            currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 1];
956            currBBStkTop++;
957            break;
958          }
959          case JBC_dup2_x1: {
960            currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
961            currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
962            currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2];
963            currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 2];
964            currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1];
965            currBBStkTop = currBBStkTop + 2;
966            break;
967          }
968          case JBC_dup_x2: {
969            currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
970            currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
971            currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 2];
972            currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1];
973            currBBStkTop++;
974            break;
975          }
976          case JBC_dup2_x2: {
977            currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
978            currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
979            currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2];
980            currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 3];
981            currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 2];
982            currBBMap[currBBStkTop - 3] = currBBMap[currBBStkTop + 1];
983            currBBStkTop = currBBStkTop + 2;
984            break;
985          }
986          case JBC_swap: {
987            byte temp;
988            temp = currBBMap[currBBStkTop];
989            currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
990            currBBMap[currBBStkTop - 1] = temp;
991            break;
992          }
993          case JBC_pop:
994          case JBC_iadd:
995          case JBC_fadd:
996          case JBC_isub:
997          case JBC_fsub:
998          case JBC_imul:
999          case JBC_fmul:
1000          case JBC_fdiv:
1001          case JBC_frem:
1002          case JBC_ishl:
1003          case JBC_ishr:
1004          case JBC_iushr:
1005          case JBC_lshl:      // long shifts that int shift value
1006          case JBC_lshr:
1007          case JBC_lushr:
1008          case JBC_iand:
1009          case JBC_ior:
1010          case JBC_ixor:
1011          case JBC_l2i:
1012          case JBC_l2f:
1013          case JBC_d2i:
1014          case JBC_d2f:
1015          case JBC_fcmpl:
1016          case JBC_fcmpg: {
1017            currBBStkTop--;
1018            bcodes.skipInstruction();
1019            break;
1020          }
1021
1022          case JBC_irem:
1023          case JBC_idiv: {
1024            currBBStkTop = currBBStkTop - 2; // record map after 2 integers popped off stack
1025            if (!inJSRSub) {
1026              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1027            } else {
1028              referenceMaps.recordJSRSubroutineMap(biStart,
1029                                                   currBBMap,
1030                                                   currBBStkTop,
1031                                                   currPendingRET.returnAddressLocation,
1032                                                   blockSeen[currBBNum]);
1033            }
1034            currBBStkTop++;
1035            break;
1036          }
1037          case JBC_ladd:
1038          case JBC_dadd:
1039          case JBC_lsub:
1040          case JBC_dsub:
1041          case JBC_lmul:
1042          case JBC_dmul:
1043          case JBC_ddiv:
1044          case JBC_drem:
1045          case JBC_land:
1046          case JBC_lor:
1047          case JBC_lxor:
1048          case JBC_pop2: {
1049            currBBStkTop = currBBStkTop - 2;
1050            break;
1051          }
1052          case JBC_lrem:
1053          case JBC_ldiv: {
1054            currBBStkTop = currBBStkTop - 4; // record map after 2 longs popped off stack
1055            if (!inJSRSub) {
1056              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1057            } else {
1058              referenceMaps.recordJSRSubroutineMap(biStart,
1059                                                   currBBMap,
1060                                                   currBBStkTop,
1061                                                   currPendingRET.returnAddressLocation,
1062                                                   blockSeen[currBBNum]);
1063            }
1064            currBBStkTop = currBBStkTop + 2;
1065            break;
1066          }
1067          case JBC_ineg:
1068          case JBC_lneg:
1069          case JBC_fneg:
1070          case JBC_dneg:
1071          case JBC_iinc:
1072          case JBC_i2f:
1073          case JBC_l2d:
1074          case JBC_f2i:
1075          case JBC_d2l:
1076          case JBC_int2byte:
1077          case JBC_int2char:
1078          case JBC_int2short: {
1079            bcodes.skipInstruction();
1080            break;
1081          }
1082
1083          case JBC_lcmp:
1084          case JBC_dcmpl:
1085          case JBC_dcmpg: {
1086            currBBStkTop = currBBStkTop - 3;
1087            break;
1088          }
1089
1090          case JBC_ifeq:
1091          case JBC_ifne:
1092          case JBC_iflt:
1093          case JBC_ifge:
1094          case JBC_ifgt:
1095          case JBC_ifle: {
1096            int offset = bcodes.getBranchOffset();
1097            if (offset <= 0) {
1098              // potential backward branch-generate reference map
1099              // Register the reference map
1100
1101              if (!inJSRSub) {
1102                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1103              } else {
1104                // in a jsr subroutine
1105                referenceMaps.recordJSRSubroutineMap(biStart,
1106                                                     currBBMap,
1107                                                     currBBStkTop,
1108                                                     currPendingRET.returnAddressLocation,
1109                                                     blockSeen[currBBNum]);
1110              }
1111            }
1112
1113            // process the basic block logic
1114            currBBStkTop--;
1115            if (offset <= 0) {
1116              short fallThruBBNum = byteToBlockMap[biStart + 3];
1117              workStk =
1118                  processBranchBB(fallThruBBNum,
1119                                  currBBStkTop,
1120                                  currBBMap,
1121                                  currBBStkEmpty,
1122                                  inJSRSub,
1123                                  bbMaps,
1124                                  blockStkTop,
1125                                  currPendingRET,
1126                                  bbPendingRETs,
1127                                  workStk);
1128              processNextBlock = false;
1129            }
1130            brBBNum = byteToBlockMap[biStart + offset];
1131            workStk =
1132                processBranchBB(brBBNum,
1133                                currBBStkTop,
1134                                currBBMap,
1135                                currBBStkEmpty,
1136                                inJSRSub,
1137                                bbMaps,
1138                                blockStkTop,
1139                                currPendingRET,
1140                                bbPendingRETs,
1141                                workStk);
1142            break;
1143          }
1144
1145          case JBC_if_icmpeq:
1146          case JBC_if_icmpne:
1147          case JBC_if_icmplt:
1148          case JBC_if_icmpge:
1149          case JBC_if_icmpgt:
1150          case JBC_if_icmple:
1151          case JBC_if_acmpeq:
1152          case JBC_if_acmpne: {
1153            int offset = bcodes.getBranchOffset();
1154            if (offset <= 0) {
1155              // possible backward branch-generate reference map
1156              // Register the reference map
1157
1158              if (!inJSRSub) {
1159                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1160              } else {
1161                // in a jsr subroutine
1162                referenceMaps.recordJSRSubroutineMap(biStart,
1163                                                     currBBMap,
1164                                                     currBBStkTop,
1165                                                     currPendingRET.returnAddressLocation,
1166                                                     blockSeen[currBBNum]);
1167              }
1168            }
1169
1170            //process the basic blocks
1171            currBBStkTop = currBBStkTop - 2;
1172            if (offset <= 0) {
1173              short fallThruBBNum = byteToBlockMap[biStart + 3];
1174              workStk =
1175                  processBranchBB(fallThruBBNum,
1176                                  currBBStkTop,
1177                                  currBBMap,
1178                                  currBBStkEmpty,
1179                                  inJSRSub,
1180                                  bbMaps,
1181                                  blockStkTop,
1182                                  currPendingRET,
1183                                  bbPendingRETs,
1184                                  workStk);
1185              processNextBlock = false;
1186            }
1187            brBBNum = byteToBlockMap[biStart + offset];
1188            workStk =
1189                processBranchBB(brBBNum,
1190                                currBBStkTop,
1191                                currBBMap,
1192                                currBBStkEmpty,
1193                                inJSRSub,
1194                                bbMaps,
1195                                blockStkTop,
1196                                currPendingRET,
1197                                bbPendingRETs,
1198                                workStk);
1199            break;
1200          }
1201
1202          case JBC_ifnull:
1203          case JBC_ifnonnull: {
1204            int offset = bcodes.getBranchOffset();
1205            if (offset <= 0) {
1206              // possible backward branch-generate reference map
1207              // Register the reference map
1208
1209              if (!inJSRSub) {
1210                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1211              } else {
1212                // in a jsr subroutine
1213                referenceMaps.recordJSRSubroutineMap(biStart,
1214                                                     currBBMap,
1215                                                     currBBStkTop,
1216                                                     currPendingRET.returnAddressLocation,
1217                                                     blockSeen[currBBNum]);
1218              }
1219            }
1220
1221            //process the basic block logic
1222            currBBStkTop--;
1223            if (offset <= 0) {
1224              short fallThruBBNum = byteToBlockMap[biStart + 3];
1225              workStk =
1226                  processBranchBB(fallThruBBNum,
1227                                  currBBStkTop,
1228                                  currBBMap,
1229                                  currBBStkEmpty,
1230                                  inJSRSub,
1231                                  bbMaps,
1232                                  blockStkTop,
1233                                  currPendingRET,
1234                                  bbPendingRETs,
1235                                  workStk);
1236              processNextBlock = false;
1237            }
1238            brBBNum = byteToBlockMap[biStart + offset];
1239            workStk =
1240                processBranchBB(brBBNum,
1241                                currBBStkTop,
1242                                currBBMap,
1243                                currBBStkEmpty,
1244                                inJSRSub,
1245                                bbMaps,
1246                                blockStkTop,
1247                                currPendingRET,
1248                                bbPendingRETs,
1249                                workStk);
1250            break;
1251          }
1252
1253          case JBC_goto: {
1254            int offset = bcodes.getBranchOffset();
1255            if (offset <= 0) {
1256              // backward branch-generate reference map
1257              // Register the reference map
1258              if (!inJSRSub) {
1259                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1260              } else {
1261                // in a jsr subroutine
1262                referenceMaps.recordJSRSubroutineMap(biStart,
1263                                                     currBBMap,
1264                                                     currBBStkTop,
1265                                                     currPendingRET.returnAddressLocation,
1266                                                     blockSeen[currBBNum]);
1267              }
1268            }
1269
1270            //  process the basic block logic
1271            brBBNum = byteToBlockMap[biStart + offset];
1272            workStk =
1273                processBranchBB(brBBNum,
1274                                currBBStkTop,
1275                                currBBMap,
1276                                currBBStkEmpty,
1277                                inJSRSub,
1278                                bbMaps,
1279                                blockStkTop,
1280                                currPendingRET,
1281                                bbPendingRETs,
1282                                workStk);
1283            processNextBlock = false;
1284            break;
1285          }
1286          case JBC_goto_w: {
1287            int offset = bcodes.getWideBranchOffset();
1288            if (offset <= 0) {
1289              // backward branch-generate reference map
1290              // Register the reference map
1291
1292              if (!inJSRSub) {
1293                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1294              } else {
1295                // in a jsr subroutine
1296                referenceMaps.recordJSRSubroutineMap(biStart,
1297                                                     currBBMap,
1298                                                     currBBStkTop,
1299                                                     currPendingRET.returnAddressLocation,
1300                                                     blockSeen[currBBNum]);
1301              }
1302            }
1303
1304            //process basic block structures
1305            brBBNum = byteToBlockMap[biStart + offset];
1306            workStk =
1307                processBranchBB(brBBNum,
1308                                currBBStkTop,
1309                                currBBMap,
1310                                currBBStkEmpty,
1311                                inJSRSub,
1312                                bbMaps,
1313                                blockStkTop,
1314                                currPendingRET,
1315                                bbPendingRETs,
1316                                workStk);
1317            processNextBlock = false;
1318            break;
1319          }
1320          case JBC_tableswitch: {
1321            currBBStkTop--;
1322            bcodes.alignSwitch();
1323            // get default offset and process branch to default branch point
1324            int def = bcodes.getDefaultSwitchOffset();
1325            workStk =
1326                processBranchBB(byteToBlockMap[biStart + def],
1327                                currBBStkTop,
1328                                currBBMap,
1329                                currBBStkEmpty,
1330                                inJSRSub,
1331                                bbMaps,
1332                                blockStkTop,
1333                                currPendingRET,
1334                                bbPendingRETs,
1335                                workStk);
1336
1337            int low = bcodes.getLowSwitchValue();
1338            int high = bcodes.getHighSwitchValue();
1339            int n = high - low + 1;
1340            // generate labels for offsets
1341            for (int k = 0; k < n; k++) {
1342              int offset = bcodes.getTableSwitchOffset(k);
1343              workStk =
1344                  processBranchBB(byteToBlockMap[biStart + offset],
1345                                  currBBStkTop,
1346                                  currBBMap,
1347                                  currBBStkEmpty,
1348                                  inJSRSub,
1349                                  bbMaps,
1350                                  blockStkTop,
1351                                  currPendingRET,
1352                                  bbPendingRETs,
1353                                  workStk);
1354            }
1355            bcodes.skipTableSwitchOffsets(n);
1356            processNextBlock = false;
1357            break;
1358          }
1359          case JBC_lookupswitch: {
1360            currBBStkTop--;
1361            bcodes.alignSwitch();
1362            // get default offset and process branch to default branch point
1363            int def = bcodes.getDefaultSwitchOffset();
1364            workStk =
1365                processBranchBB(byteToBlockMap[biStart + def],
1366                                currBBStkTop,
1367                                currBBMap,
1368                                currBBStkEmpty,
1369                                inJSRSub,
1370                                bbMaps,
1371                                blockStkTop,
1372                                currPendingRET,
1373                                bbPendingRETs,
1374                                workStk);
1375
1376            int npairs = bcodes.getSwitchLength();
1377
1378            // generate label for each offset in table
1379            for (int k = 0; k < npairs; k++) {
1380              int offset = bcodes.getLookupSwitchOffset(k);
1381              workStk =
1382                  processBranchBB(byteToBlockMap[biStart + offset],
1383                                  currBBStkTop,
1384                                  currBBMap,
1385                                  currBBStkEmpty,
1386                                  inJSRSub,
1387                                  bbMaps,
1388                                  blockStkTop,
1389                                  currPendingRET,
1390                                  bbPendingRETs,
1391                                  workStk);
1392            }
1393            bcodes.skipLookupSwitchPairs(npairs);
1394            processNextBlock = false;
1395            break;
1396          }
1397
1398          case JBC_jsr: {
1399            processNextBlock = false;
1400            int offset = bcodes.getBranchOffset();
1401            if (!inJSRSub) {
1402              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]);
1403            } else {
1404              referenceMaps.recordJSRSubroutineMap(biStart,
1405                                                   currBBMap,
1406                                                   currBBStkEmpty,
1407                                                   currPendingRET.returnAddressLocation,
1408                                                   blockSeen[currBBNum]);
1409            }
1410            currBBStkTop++;
1411            currBBMap[currBBStkTop] = RETURN_ADDRESS;
1412            workStk =
1413                processJSR(byteToBlockMap[biStart],
1414                           biStart + offset,
1415                           byteToBlockMap[biStart + offset],
1416                           byteToBlockMap[biStart + 3],
1417                           bbMaps,
1418                           currBBStkTop,
1419                           currBBMap,
1420                           currBBStkEmpty,
1421                           blockStkTop,
1422                           bbPendingRETs,
1423                           currPendingRET,
1424                           JSRSubs,
1425                           workStk);
1426            break;
1427          }
1428          case JBC_jsr_w: {
1429            processNextBlock = false;
1430            int offset = bcodes.getWideBranchOffset();
1431            if (!inJSRSub) {
1432              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]);
1433            } else {
1434              referenceMaps.recordJSRSubroutineMap(biStart,
1435                                                   currBBMap,
1436                                                   currBBStkEmpty,
1437                                                   currPendingRET.returnAddressLocation,
1438                                                   blockSeen[currBBNum]);
1439            }
1440            currBBStkTop++;
1441            currBBMap[currBBStkTop] = RETURN_ADDRESS;
1442            workStk =
1443                processJSR(byteToBlockMap[biStart],
1444                           biStart + offset,
1445                           byteToBlockMap[biStart + offset],
1446                           byteToBlockMap[biStart + 5],
1447                           bbMaps,
1448                           currBBStkTop,
1449                           currBBMap,
1450                           currBBStkEmpty,
1451                           blockStkTop,
1452                           bbPendingRETs,
1453                           currPendingRET,
1454                           JSRSubs,
1455                           workStk);
1456            break;
1457          }
1458          case JBC_ret: {
1459            int index = bcodes.getLocalNumber();
1460
1461            // Can not be used again as a return addr.
1462            //
1463            currBBMap[index] = SET_TO_NONREFERENCE;
1464            processNextBlock = false;
1465            int subStart = currPendingRET.JSRSubStartByteIndex;
1466            int k;
1467            for (k = 0; k < JSRSubNext; k++) {
1468              if (JSRSubs[k].subroutineByteCodeStart == subStart) {
1469                JSRSubs[k].newEndMaps(currBBMap, currBBStkTop);
1470                break;
1471              }
1472            }
1473
1474            boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null;
1475            workStk =
1476                computeJSRNextMaps(currPendingRET.JSRNextBBNum,
1477                                   currBBMap.length,
1478                                   k,
1479                                   JSRisinJSRSub,
1480                                   bbMaps,
1481                                   blockStkTop,
1482                                   JSRSubs,
1483                                   currBBStkEmpty,
1484                                   workStk);
1485            if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) {
1486              bbPendingRETs[currPendingRET.JSRNextBBNum] =
1487                  new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]);
1488            }
1489            break;
1490          }
1491          case JBC_invokevirtual:
1492          case JBC_invokespecial: {
1493            MethodReference target = bcodes.getMethodReference();
1494            currBBStkTop =
1495                processInvoke(target,
1496                              biStart,
1497                              currBBStkTop,
1498                              currBBMap,
1499                              false,
1500                              inJSRSub,
1501                              referenceMaps,
1502                              currPendingRET,
1503                              blockSeen[currBBNum],
1504                              currBBStkEmpty);
1505            break;
1506          }
1507          case JBC_invokeinterface: {
1508            MethodReference target = bcodes.getMethodReference();
1509            bcodes.alignInvokeInterface();
1510            currBBStkTop =
1511                processInvoke(target,
1512                              biStart,
1513                              currBBStkTop,
1514                              currBBMap,
1515                              false,
1516                              inJSRSub,
1517                              referenceMaps,
1518                              currPendingRET,
1519                              blockSeen[currBBNum],
1520                              currBBStkEmpty);
1521            break;
1522          }
1523          case JBC_invokestatic: {
1524            MethodReference target = bcodes.getMethodReference();
1525            currBBStkTop =
1526                processInvoke(target,
1527                              biStart,
1528                              currBBStkTop,
1529                              currBBMap,
1530                              true,
1531                              inJSRSub,
1532                              referenceMaps,
1533                              currPendingRET,
1534                              blockSeen[currBBNum],
1535                              currBBStkEmpty);
1536            break;
1537          }
1538
1539          case JBC_ireturn:
1540          case JBC_lreturn:
1541          case JBC_freturn:
1542          case JBC_dreturn:
1543          case JBC_areturn:
1544          case JBC_return: {
1545            if (VM.UseEpilogueYieldPoints || method.isSynchronized()) {
1546              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1547            }
1548            processNextBlock = false;
1549            break;
1550          }
1551
1552          case JBC_getstatic: {
1553            // Register the reference map (could cause dynamic linking)
1554            if (!inJSRSub) {
1555              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1556            } else {
1557              referenceMaps.recordJSRSubroutineMap(biStart,
1558                                                   currBBMap,
1559                                                   currBBStkTop,
1560                                                   currPendingRET.returnAddressLocation,
1561                                                   blockSeen[currBBNum]);
1562            }
1563
1564            TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
1565            currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE;
1566            if (fieldType.getStackWords() == 2) {
1567              currBBMap[++currBBStkTop] = NON_REFERENCE;
1568            }
1569            break;
1570          }
1571          case JBC_putstatic: {
1572            // Register the reference map (could cause dynamic linking)
1573            if (!inJSRSub) {
1574              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1575            } else {
1576              referenceMaps.recordJSRSubroutineMap(biStart,
1577                                                   currBBMap,
1578                                                   currBBStkTop,
1579                                                   currPendingRET.returnAddressLocation,
1580                                                   blockSeen[currBBNum]);
1581            }
1582            TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
1583            currBBStkTop--;
1584            if (fieldType.getStackWords() == 2) {
1585              currBBStkTop--;
1586            }
1587            break;
1588          }
1589          case JBC_getfield: {
1590            TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
1591            // Register the reference map (could cause dynamic linking..if so there will be a NPE, but the linking happens first.)
1592            if (!inJSRSub) {
1593              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1594            } else {
1595              referenceMaps.recordJSRSubroutineMap(biStart,
1596                                                   currBBMap,
1597                                                   currBBStkTop,
1598                                                   currPendingRET.returnAddressLocation,
1599                                                   blockSeen[currBBNum]);
1600            }
1601            currBBStkTop--;    // pop object pointer
1602            currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE;
1603            if (fieldType.getStackWords() == 2) {
1604              currBBMap[++currBBStkTop] = NON_REFERENCE;
1605            }
1606            break;
1607          }
1608          case JBC_putfield: {
1609            TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
1610            // Register the reference map with the values still on the stack
1611            //  note: putfield could result in a call to the classloader
1612            if (!inJSRSub) {
1613              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1614            } else {
1615              referenceMaps.recordJSRSubroutineMap(biStart,
1616                                                   currBBMap,
1617                                                   currBBStkTop,
1618                                                   currPendingRET.returnAddressLocation,
1619                                                   blockSeen[currBBNum]);
1620            }
1621            currBBStkTop -= 2;  // remove objectref and one value
1622            if (fieldType.getStackWords() == 2) {
1623              currBBStkTop--;
1624            }
1625            break;
1626          }
1627          case JBC_checkcast: {
1628            if (!inJSRSub) {
1629              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1630            } else {
1631              referenceMaps.recordJSRSubroutineMap(biStart,
1632                                                   currBBMap,
1633                                                   currBBStkTop,
1634                                                   currPendingRET.returnAddressLocation,
1635                                                   blockSeen[currBBNum]);
1636            }
1637            bcodes.skipInstruction();
1638            break;
1639          }
1640          case JBC_instanceof: {
1641            if (!inJSRSub) {
1642              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1643            } else {
1644              referenceMaps.recordJSRSubroutineMap(biStart,
1645                                                   currBBMap,
1646                                                   currBBStkTop,
1647                                                   currPendingRET.returnAddressLocation,
1648                                                   blockSeen[currBBNum]);
1649            }
1650            currBBMap[currBBStkTop] = NON_REFERENCE;
1651            bcodes.skipInstruction();
1652            break;
1653          }
1654          case JBC_new: {
1655            if (!inJSRSub) {
1656              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1657            } else {
1658              referenceMaps.recordJSRSubroutineMap(biStart,
1659                                                   currBBMap,
1660                                                   currBBStkTop,
1661                                                   currPendingRET.returnAddressLocation,
1662                                                   blockSeen[currBBNum]);
1663            }
1664            currBBStkTop++;
1665            currBBMap[currBBStkTop] = REFERENCE;
1666            bcodes.skipInstruction();
1667            break;
1668          }
1669
1670          // For the <x>aload instructions the map is needed in case GC occurs
1671          // while the array index check is taking place. Stack has not been
1672          // altered yet.
1673          case JBC_iaload:
1674          case JBC_faload:
1675          case JBC_baload:
1676          case JBC_caload:
1677          case JBC_saload: {
1678            if (!inJSRSub) {
1679              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1680            } else {
1681              referenceMaps.recordJSRSubroutineMap(biStart,
1682                                                   currBBMap,
1683                                                   currBBStkTop,
1684                                                   currPendingRET.returnAddressLocation,
1685                                                   blockSeen[currBBNum]);
1686            }
1687            currBBStkTop--;
1688            currBBMap[currBBStkTop] = NON_REFERENCE;
1689            break;
1690          }
1691          case JBC_laload:
1692          case JBC_daload: {
1693            if (!inJSRSub) {
1694              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1695            } else {
1696              referenceMaps.recordJSRSubroutineMap(biStart,
1697                                                   currBBMap,
1698                                                   currBBStkTop,
1699                                                   currPendingRET.returnAddressLocation,
1700                                                   blockSeen[currBBNum]);
1701            }
1702            currBBMap[currBBStkTop - 1] = NON_REFERENCE;
1703            break;
1704          }
1705
1706          case JBC_aaload: {
1707            if (!inJSRSub) {
1708              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1709            } else {
1710              referenceMaps.recordJSRSubroutineMap(biStart,
1711                                                   currBBMap,
1712                                                   currBBStkTop,
1713                                                   currPendingRET.returnAddressLocation,
1714                                                   blockSeen[currBBNum]);
1715            }
1716            currBBStkTop--;
1717            break;
1718          }
1719
1720          // For the <x>astore instructions the map recorded is in case GC occurs
1721          // during the array index bounds check or the arraystore check (for aastore).
1722          // Stack has not been modified at this point.
1723          case JBC_iastore:
1724          case JBC_fastore:
1725          case JBC_aastore:
1726          case JBC_bastore:
1727          case JBC_castore:
1728          case JBC_sastore: {
1729            if (!inJSRSub) {
1730              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1731            } else {
1732              referenceMaps.recordJSRSubroutineMap(biStart,
1733                                                   currBBMap,
1734                                                   currBBStkTop,
1735                                                   currPendingRET.returnAddressLocation,
1736                                                   blockSeen[currBBNum]);
1737            }
1738            currBBStkTop = currBBStkTop - 3;
1739            break;
1740          }
1741          case JBC_lastore:
1742          case JBC_dastore: {
1743            if (!inJSRSub) {
1744              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1745            } else {
1746              referenceMaps.recordJSRSubroutineMap(biStart,
1747                                                   currBBMap,
1748                                                   currBBStkTop,
1749                                                   currPendingRET.returnAddressLocation,
1750                                                   blockSeen[currBBNum]);
1751            }
1752            currBBStkTop = currBBStkTop - 4;
1753            break;
1754          }
1755
1756          case JBC_newarray:
1757          case JBC_anewarray: {
1758            if (!inJSRSub) {
1759              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1760            } else {
1761              referenceMaps.recordJSRSubroutineMap(biStart,
1762                                                   currBBMap,
1763                                                   currBBStkTop,
1764                                                   currPendingRET.returnAddressLocation,
1765                                                   blockSeen[currBBNum]);
1766            }
1767            currBBMap[currBBStkTop] = REFERENCE;
1768            bcodes.skipInstruction();
1769            break;
1770          }
1771
1772          case JBC_multianewarray: {
1773            bcodes.getTypeReference();
1774            int dim = bcodes.getArrayDimension();
1775            if (!inJSRSub) {
1776              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1777            } else {
1778              referenceMaps.recordJSRSubroutineMap(biStart,
1779                                                   currBBMap,
1780                                                   currBBStkTop,
1781                                                   currPendingRET.returnAddressLocation,
1782                                                   blockSeen[currBBNum]);
1783            }
1784            currBBStkTop = currBBStkTop - dim + 1;
1785            currBBMap[currBBStkTop] = REFERENCE;
1786            break;
1787          }
1788          case JBC_arraylength: {
1789            currBBMap[currBBStkTop] = NON_REFERENCE;
1790            break;
1791          }
1792          case JBC_athrow: {
1793            if (!inJSRSub) {
1794              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1795            } else {
1796              referenceMaps.recordJSRSubroutineMap(biStart,
1797                                                   currBBMap,
1798                                                   currBBStkTop,
1799                                                   currPendingRET.returnAddressLocation,
1800                                                   blockSeen[currBBNum]);
1801            }
1802            currBBStkTop = currBBStkEmpty + 1;
1803            currBBMap[currBBStkTop] = REFERENCE;
1804            processNextBlock = false;
1805            break;
1806          }
1807          case JBC_monitorenter:
1808          case JBC_monitorexit: {
1809            currBBStkTop--;
1810            if (!inJSRSub) {
1811              referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
1812            } else {
1813              referenceMaps.recordJSRSubroutineMap(biStart,
1814                                                   currBBMap,
1815                                                   currBBStkTop,
1816                                                   currPendingRET.returnAddressLocation,
1817                                                   blockSeen[currBBNum]);
1818            }
1819            break;
1820          }
1821
1822          case JBC_wide: {
1823            int widecode = bcodes.getWideOpcode();
1824            int index = bcodes.getWideLocalNumber();
1825            switch (widecode) {
1826              case JBC_iload:
1827              case JBC_fload: {
1828                currBBStkTop++;
1829                currBBMap[currBBStkTop] = NON_REFERENCE;
1830                break;
1831              }
1832
1833              case JBC_lload:
1834              case JBC_dload: {
1835                currBBStkTop++;
1836                currBBMap[currBBStkTop] = NON_REFERENCE;
1837                currBBStkTop++;
1838                currBBMap[currBBStkTop] = NON_REFERENCE;
1839                break;
1840              }
1841
1842              case JBC_aload: {
1843                currBBStkTop++;
1844                currBBMap[currBBStkTop] = currBBMap[index];
1845                break;
1846              }
1847
1848              case JBC_istore: {
1849                if (!inJSRSub) {
1850                  currBBMap[index] = NON_REFERENCE;
1851                } else {
1852                  currBBMap[index] = SET_TO_NONREFERENCE;
1853                }
1854                currBBStkTop--;
1855                localTypes[index] |= INT_TYPE;
1856                break;
1857              }
1858
1859              case JBC_fstore: {
1860                if (!inJSRSub) {
1861                  currBBMap[index] = NON_REFERENCE;
1862                } else {
1863                  currBBMap[index] = SET_TO_NONREFERENCE;
1864                }
1865                currBBStkTop--;
1866                localTypes[index] |= FLOAT_TYPE;
1867                break;
1868              }
1869
1870              case JBC_lstore: {
1871                if (!inJSRSub) {
1872                  currBBMap[index] = NON_REFERENCE;
1873                  currBBMap[index + 1] = NON_REFERENCE;
1874                } else {
1875                  currBBMap[index] = SET_TO_NONREFERENCE;
1876                  currBBMap[index + 1] = SET_TO_NONREFERENCE;
1877                }
1878                currBBStkTop = currBBStkTop - 2;
1879                localTypes[index] |= LONG_TYPE;
1880                break;
1881              }
1882
1883              case JBC_dstore: {
1884                if (!inJSRSub) {
1885                  currBBMap[index] = NON_REFERENCE;
1886                  currBBMap[index + 1] = NON_REFERENCE;
1887                } else {
1888                  currBBMap[index] = SET_TO_NONREFERENCE;
1889                  currBBMap[index + 1] = SET_TO_NONREFERENCE;
1890                }
1891                currBBStkTop = currBBStkTop - 2;
1892                localTypes[index] |= DOUBLE_TYPE;
1893                break;
1894              }
1895
1896              case JBC_astore: {
1897                currBBMap[index] = currBBMap[currBBStkTop];
1898                currBBStkTop--;
1899                localTypes[index] |= ADDRESS_TYPE;
1900                break;
1901              }
1902
1903              case JBC_iinc: {
1904                bcodes.getWideIncrement();
1905                break;
1906              }
1907              case JBC_ret: {
1908                // Can not be used again as a return addr.
1909                //
1910                currBBMap[index] = SET_TO_NONREFERENCE;
1911                processNextBlock = false;
1912                int subStart = currPendingRET.JSRSubStartByteIndex;
1913                int k;
1914                for (k = 0; k < JSRSubNext; k++) {
1915                  if (JSRSubs[k].subroutineByteCodeStart == subStart) {
1916                    JSRSubs[k].newEndMaps(currBBMap, currBBStkTop);
1917                    break;
1918                  }
1919                }
1920
1921                boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null;
1922                workStk =
1923                    computeJSRNextMaps(currPendingRET.JSRNextBBNum,
1924                                       currBBMap.length,
1925                                       k,
1926                                       JSRisinJSRSub,
1927                                       bbMaps,
1928                                       blockStkTop,
1929                                       JSRSubs,
1930                                       currBBStkEmpty,
1931                                       workStk);
1932                if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) {
1933                  bbPendingRETs[currPendingRET.JSRNextBBNum] =
1934                      new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]);
1935                }
1936                break;
1937              }
1938              default: // switch on widecode
1939                if (VM.VerifyAssertions) VM._assert(VM.NOT_REACHED);
1940            }
1941            break;
1942          }  // case JBC_wide:
1943
1944          default: {
1945            VM.sysFail("Unknown opcode:" + opcode);
1946          }
1947
1948        }  // end switch (opcode)
1949
1950      }  // for start to end
1951
1952      blockSeen[currBBNum] = true;
1953
1954      if (processNextBlock) {
1955        short fallThruBBNum = byteToBlockMap[bcodes.index()];
1956        workStk =
1957            processBranchBB(fallThruBBNum,
1958                            currBBStkTop,
1959                            currBBMap,
1960                            currBBStkEmpty,
1961                            inJSRSub,
1962                            bbMaps,
1963                            blockStkTop,
1964                            currPendingRET,
1965                            bbPendingRETs,
1966                            workStk);
1967
1968      }
1969
1970      // if the work stack is empty, we must have processed the whole program
1971      // we can now process the try handlers if there are any.
1972      // If a handler doesn't have a starting map already, then the associated try
1973      // has not been processed yet. The try and the handler must be in another
1974      // handler, so that handler must be processed first.
1975      // If one handler is in the try block associated with a second handler, then
1976      // the second handler must not be processed until the first handler has been.
1977      //
1978      if ((workStkTop == -1) && !handlersAllDone) {
1979        int i;
1980        for (i = 0; i < tryHandlerLength; i++) {
1981          // already processed this handler, or, haven't seen the
1982          // associated try block yet so no starting map is available,
1983          // the try block must be in one of the other handlers
1984          if (!handlerProcessed[i] && bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null) break;
1985        }
1986        if (i == tryHandlerLength) {
1987          handlersAllDone = true;
1988        } else {
1989          int considerIndex = i;
1990
1991          while (i != tryHandlerLength) {
1992            int tryStart = tryStartPC[considerIndex];
1993            int tryEnd = tryEndPC[considerIndex];
1994
1995            for (i = 0; i < tryHandlerLength; i++) {
1996              // If the handler handles itself, then make the wild assumption
1997              // that the local variables will be the same......is this reasonable??
1998              // This is a patch to deal with defect 3046.
1999              // I'm not entirely convinced this is right, but don't know what else we can do. --dave
2000              if (i == considerIndex) continue;
2001
2002              // For every handler that has not yet been processed,
2003              // but already has a known starting map,
2004              // make sure it is not in the try block part of the handler
2005              // we are considering working on.
2006              if (!handlerProcessed[i] &&
2007                  tryStart <= tryHandlerPC[i] &&
2008                  tryHandlerPC[i] < tryEnd &&
2009                  bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null) {
2010                break;
2011              }
2012            }
2013
2014            if (i != tryHandlerLength) {
2015              considerIndex = i;
2016            }
2017          }
2018
2019          short blockNum = byteToBlockMap[tryHandlerPC[considerIndex]];
2020          handlerProcessed[considerIndex] = true;
2021          workStk = addToWorkStk(blockNum, workStk);
2022        }
2023      }
2024
2025    }  // while workStk not empty
2026
2027    // Indicate that any temporaries can be freed
2028    referenceMaps.recordingComplete();
2029
2030  }
2031
2032  // -------------------- Private Instance Methods --------------------
2033
2034  private short[] addToWorkStk(short blockNum, short[] workStk) {
2035    workStkTop++;
2036    if (workStkTop >= workStk.length) {
2037      short[] biggerQ = new short[workStk.length + 20];
2038      for (int i = 0; i < workStk.length; i++) {
2039        biggerQ[i] = workStk[i];
2040      }
2041      workStk = biggerQ;
2042      biggerQ = null;
2043    }
2044    workStk[workStkTop] = blockNum;
2045    return workStk;
2046  }
2047
2048  private short[] addUniqueToWorkStk(short blockNum, short[] workStk) {
2049    if ((workStkTop + 1) >= workStk.length) {
2050      short[] biggerQ = new short[workStk.length + 20];
2051      boolean matchFound = false;
2052      for (int i = 0; i < workStk.length; i++) {
2053        biggerQ[i] = workStk[i];
2054        matchFound = (workStk[i] == blockNum);
2055      }
2056      workStk = biggerQ;
2057      biggerQ = null;
2058      if (matchFound) return workStk;
2059    } else {
2060      for (int i = 0; i <= workStkTop; i++) {
2061        if (workStk[i] == blockNum) {
2062          return workStk;
2063        }
2064      }
2065    }
2066    workStkTop++;
2067    workStk[workStkTop] = blockNum;
2068    return workStk;
2069  }
2070
2071  private short[] processBranchBB(short brBBNum, int currBBStkTop, byte[] currBBMap, int currBBStkEmpty,
2072                                  boolean inJSRSub, byte[][] bbMaps, int[] blockStkTop,
2073                                  PendingRETInfo currPendingRET, PendingRETInfo[] bbPendingRETs,
2074                                  short[] workStk) {
2075
2076    short[] newworkStk = workStk;
2077
2078    // If the destination block doesn't already have a map, then use this
2079    // map as its map and add it to the work stack
2080
2081    if (bbMaps[brBBNum] == null) {
2082      bbMaps[brBBNum] = new byte[currBBMap.length];
2083      for (int i = 0; i <= currBBStkTop; i++) {
2084        bbMaps[brBBNum][i] = currBBMap[i];
2085      }
2086      blockStkTop[brBBNum] = currBBStkTop;
2087      newworkStk = addToWorkStk(brBBNum, workStk);
2088      if (inJSRSub) {
2089        bbPendingRETs[brBBNum] = new PendingRETInfo(currPendingRET);
2090      }
2091
2092    } else {
2093      // If the destination block already has a map, then check if there are any
2094      // new NONReference values. Note that a new Reference value, will not change an
2095      // existing NONReference value to Reference, as there must be a valid path where
2096      // the variable is not a reference (and not "null" - which is treated as a
2097      // reference) so the variable is unusable.
2098      //
2099      int mismatchAt = -1;
2100      byte[] blockMap = bbMaps[brBBNum];
2101      for (int i = 0; i <= currBBStkEmpty; i++) {
2102        if ((currBBMap[i] != blockMap[i]) && (blockMap[i] != NON_REFERENCE)) {
2103          mismatchAt = i;
2104          break;
2105        }
2106      }
2107      if (mismatchAt == -1) {
2108        return newworkStk;  // no further work to be done
2109      } else {
2110        newworkStk = addUniqueToWorkStk(brBBNum, workStk);
2111        for (int i = mismatchAt; i <= currBBStkEmpty; i++) {
2112          if (!inJSRSub) {
2113            blockMap[i] = (blockMap[i] == currBBMap[i]) ? blockMap[i] : NON_REFERENCE;
2114          } else {
2115            blockMap[i] = (blockMap[i] == currBBMap[i]) ? blockMap[i] : SET_TO_NONREFERENCE;
2116          }
2117        }
2118      }
2119    }
2120    return newworkStk;
2121  }
2122
2123  private int processInvoke(MethodReference target, int byteindex, int currBBStkTop, byte[] currBBMap,
2124                            boolean isStatic, boolean inJSRSub, ReferenceMaps referenceMaps,
2125                            PendingRETInfo currPendingRET, boolean blockSeen, int currBBStkEmpty) {
2126    boolean skipRecordingReferenceMap = false;
2127    boolean popParams = true;
2128
2129    if (target.getType().isMagicType()) {
2130      boolean producesCall = BaselineCompiler.checkForActualCall(target);
2131      if (producesCall) {
2132        // register a map, but do NOT include any of the parameters to the call.
2133        // Chances are what appear to be parameters are not parameters to
2134        // the routine that is actually called.
2135        // In any case, the callee routine will map its parameters
2136        // and we don't have to double map because we are positive that this can't be
2137        // a dynamically linked call site.
2138        for (TypeReference parameterType : target.getParameterTypes()) {
2139          currBBStkTop -= parameterType.getStackWords();
2140        }
2141        if (!isStatic) currBBStkTop--; // pop implicit "this" object reference
2142        popParams = false;
2143      } else {
2144        skipRecordingReferenceMap = true;
2145      }
2146    }
2147
2148    if (!skipRecordingReferenceMap) {
2149      // Register the reference map, including the arguments on the stack for this call
2150      // (unless it is a magic call whose params we have popped above).
2151      if (!inJSRSub) {
2152        referenceMaps.recordStkMap(byteindex, currBBMap, currBBStkTop, blockSeen);
2153      } else {
2154        referenceMaps.recordJSRSubroutineMap(byteindex,
2155                                             currBBMap,
2156                                             currBBStkTop,
2157                                             currPendingRET.returnAddressLocation,
2158                                             blockSeen);
2159      }
2160    }
2161
2162    if (popParams) {
2163      TypeReference[] parameterTypes = target.getParameterTypes();
2164      int pTypesLength = parameterTypes.length;
2165
2166      // Pop the arguments for this call off the stack;
2167      for (int i = 0; i < pTypesLength; i++) {
2168        currBBStkTop -= parameterTypes[i].getStackWords();
2169      }
2170
2171      if (!isStatic) {
2172        currBBStkTop--; // pop implicit "this" object reference
2173      }
2174    }
2175
2176    // Add the return value to the stack
2177    TypeReference returnType = target.getReturnType();
2178    if (!returnType.isVoidType()) {
2179      // a non-void return value
2180      currBBMap[++currBBStkTop] = returnType.isReferenceType() ? REFERENCE : NON_REFERENCE;
2181      if (returnType.getStackWords() == 2) {
2182        currBBMap[++currBBStkTop] = NON_REFERENCE;
2183      }
2184    }
2185
2186    // Return updated stack top
2187    return currBBStkTop;
2188  }
2189
2190  private short[] processJSR(int JSRBBNum, int JSRSubStartIndex, short brBBNum, short nextBBNum, byte[][] bbMaps,
2191                             int currBBStkTop, byte[] currBBMap, int currBBStkEmpty, int[] blockStkTop,
2192                             PendingRETInfo[] bbPendingRETs, PendingRETInfo currPendingRET,
2193                             JSRSubroutineInfo[] JSRSubs, short[] workStk) {
2194    short[] newworkStk = workStk;
2195
2196    // If the destination block doesn't already have a map, then use this map to build
2197    // the stack portion of the reference map and add the block to the work stack.
2198    // The locals maps should be started with all zeros.
2199
2200    if (bbMaps[brBBNum] == null) {
2201      bbMaps[brBBNum] = new byte[currBBMap.length];
2202      for (int i = currBBStkEmpty + 1; i <= currBBStkTop; i++) {
2203        bbMaps[brBBNum][i] = currBBMap[i];
2204      }
2205      blockStkTop[brBBNum] = currBBStkTop;
2206      newworkStk = addToWorkStk(brBBNum, workStk);
2207
2208      bbPendingRETs[brBBNum] = new PendingRETInfo(JSRSubStartIndex, JSRBBNum, currBBStkTop, nextBBNum);
2209      JSRSubs[JSRSubNext++] = new JSRSubroutineInfo(JSRSubStartIndex, currBBMap, currBBStkEmpty);
2210    } else {
2211      // If the JSR subroutine block already has a map, then locate the ending map
2212      // and use that to determine the map of the next block. No need to reprocess
2213      // the JSR subroutine
2214      int matchingJSRStart;
2215      for (matchingJSRStart = 0; matchingJSRStart < JSRSubNext; matchingJSRStart++) {
2216        if (JSRSubs[matchingJSRStart].subroutineByteCodeStart == JSRSubStartIndex) {
2217          JSRSubs[matchingJSRStart].newStartMaps(currBBMap);
2218          break;
2219        }
2220      }
2221
2222      boolean JSRisinJSRSub = (currPendingRET != null);
2223      newworkStk =
2224          computeJSRNextMaps(nextBBNum,
2225                             currBBMap.length,
2226                             matchingJSRStart,
2227                             JSRisinJSRSub,
2228                             bbMaps,
2229                             blockStkTop,
2230                             JSRSubs,
2231                             currBBStkEmpty,
2232                             workStk);
2233      if (JSRisinJSRSub && bbPendingRETs[nextBBNum] == null) {
2234        bbPendingRETs[nextBBNum] = new PendingRETInfo(currPendingRET);
2235      }
2236    }
2237
2238    return newworkStk;
2239  }
2240
2241  private short[] computeJSRNextMaps(short nextBBNum, int maplength, int JSRSubIndex, boolean JSRisinJSRSub,
2242                                     byte[][] bbMaps, int[] blockStkTop, JSRSubroutineInfo[] JSRSubs,
2243                                     int currBBStkEmpty, short[] workStk) {
2244    short[] newworkStk = workStk;
2245
2246    // Calculate the new map for the block starting at the instruction after the
2247    // JSR instruction (this is the block nextBBNum)
2248    byte[] refMap;
2249
2250    refMap = JSRSubs[JSRSubIndex].computeResultingMaps(maplength);
2251
2252    // If no map is computed, then the JSR Subroutine must have ended in a return
2253    // Do NOT add the next block to the work Q.
2254    if (refMap == null) {
2255      return newworkStk;
2256    }
2257
2258    // If the block after the JSR instruction does not have a map, then the newly
2259    // computed map should be used and the block should be added to the workStk.
2260    if (bbMaps[nextBBNum] == null) {
2261      bbMaps[nextBBNum] = refMap;
2262      blockStkTop[nextBBNum] = JSRSubs[JSRSubIndex].endReferenceTop;
2263      newworkStk = addToWorkStk(nextBBNum, workStk);
2264    } else {
2265      // The block after the JSR instruction already has a reference map.
2266      // Check if the computed map matches the previous map. If so, no further
2267      // work needed.
2268      int mismatchAt = -1;
2269      byte[] blockMap = bbMaps[nextBBNum];
2270      for (int i = 0; i <= currBBStkEmpty; i++) {
2271        if ((refMap[i] != blockMap[i]) && (blockMap[i] != NON_REFERENCE)) {
2272          mismatchAt = i;
2273          break;
2274        }
2275      }
2276      if (mismatchAt == -1) {
2277        return newworkStk;  // no further work to be done
2278      } else {
2279        newworkStk = addUniqueToWorkStk(nextBBNum, workStk);
2280        for (int i = mismatchAt; i <= currBBStkEmpty; i++) {
2281          if (!JSRisinJSRSub) {
2282            blockMap[i] = (blockMap[i] == refMap[i]) ? blockMap[i] : NON_REFERENCE;
2283          } else {
2284            blockMap[i] = (blockMap[i] == refMap[i]) ? blockMap[i] : SET_TO_NONREFERENCE;
2285          }
2286        }
2287      }
2288    }
2289    return newworkStk;
2290  }
2291
2292  /**
2293   * For each of the reachable handlers (catch blocks) from the try block, track that
2294   * the local variable given by the index with 1 or 2 words, has been set to a
2295   * non reference value (eg int, float, etc)
2296   *
2297   * @param localVariable             Variable index in the map
2298   * @param wordCount                 2 for doubles and longs, 1 otherwise
2299   * @param reachableHandlerBBNums    The array with all the block numbers of
2300   *                                  reachable handlers
2301   * @param reachableHandlerCount     0 through <code>reachableHandlerCount
2302   *                                   - 1 </code> will all be valid
2303   *                                  array indices
2304   * @param inJSRSub                  TODO Document ME XXX
2305   * @param bbMaps                    TODO Document ME XXX
2306   */
2307  private void setHandlersMapsNonRef(int localVariable, PrimitiveSize wordCount, int[] reachableHandlerBBNums,
2308                                     int reachableHandlerCount, boolean inJSRSub, byte[][] bbMaps) {
2309    if (!inJSRSub) {
2310      for (int i = 0; i < reachableHandlerCount; i++) {
2311        bbMaps[reachableHandlerBBNums[i]][localVariable] = NON_REFERENCE;
2312        if (wordCount == PrimitiveSize.DOUBLEWORD) {
2313          bbMaps[reachableHandlerBBNums[i]][localVariable + 1] = NON_REFERENCE;
2314        }
2315      }
2316    } else {
2317      for (int i = 0; i < reachableHandlerCount; i++) {
2318        bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE;
2319        if (wordCount == PrimitiveSize.DOUBLEWORD) {
2320          bbMaps[reachableHandlerBBNums[i]][localVariable + 1] = SET_TO_NONREFERENCE;
2321        }
2322      }
2323    }
2324
2325  }
2326
2327  /**
2328   * For each of the reachable handlers (catch blocks) from the try block,
2329   * track that
2330   * the local variable given by the index,  has been set to a reference value.
2331   * Only call this method if the try block is in a JSR subroutine.
2332   * If a non-reference value becomes a reference value,
2333   * then it can not be used as
2334   * as reference value within the handler
2335   * (there is a path to the handler where the
2336   * value is not a reference) so mark the local variable as
2337   * a non-reference if we
2338   * are tracking the difference maps (for a JSR subroutine).
2339   *
2340   * @param localVariable             Variable index in the map
2341   * @param reachableHandlerBBNums    The array with all the block numbers of
2342   *                                  reachable handlers
2343   * @param reachableHandlerCount     0 through <code>reachableHandlerCount
2344   *                                   - 1 </code> will all be valid
2345   *                                  array indices
2346   * @param bbMaps                    TODO Document ME XXX
2347   */
2348  private void setHandlersMapsRef(int localVariable, int[] reachableHandlerBBNums, int reachableHandlerCount,
2349                                  byte[][] bbMaps) {
2350    for (int i = 0; i < reachableHandlerCount; i++) {
2351      if (bbMaps[reachableHandlerBBNums[i]][localVariable] != REFERENCE) {
2352        bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE;
2353      }
2354    }
2355  }
2356
2357  /**
2358   * For each of the reachable handlers (catch blocks)
2359   * from the try block, track that
2360   * the local variable given by the index,
2361   * has been set to a return address value.
2362   * Only call this routine within a JSR subroutine.
2363   * If a non-reference, or reference value becomes a return address value,
2364   * then it
2365   * cannot be used as any of these values within the handler
2366   * (there is a path to
2367   * the handler where the value is not an internal reference,
2368   * and a path where it
2369   * is an internal reference) so mark the local variable as a
2370   * non-reference if we
2371   * are tracking the difference maps (for a JSR subroutine).
2372   *
2373   * @param localVariable             variable index in the map
2374   * @param reachableHandlerBBNums     the array with all the block numbers of
2375   *                                  reachable handlers
2376   * @param reachableHandlerCount     0 through <code>reachableHandlerCount
2377   *                                   - 1 </code> will all be valid
2378   *                                  array indices
2379   * @param bbMaps                    TODO Document ME XXX
2380   */
2381  private void setHandlersMapsReturnAddress(int localVariable, int[] reachableHandlerBBNums, int reachableHandlerCount,
2382                                            byte[][] bbMaps) {
2383    for (int i = 0; i < reachableHandlerCount; i++) {
2384      if (bbMaps[reachableHandlerBBNums[i]][localVariable] != RETURN_ADDRESS) {
2385        bbMaps[reachableHandlerBBNums[i]][localVariable] = SET_TO_NONREFERENCE;
2386      }
2387    }
2388
2389  }
2390}