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