Search in sources :

Example 1 with MethodReference

use of org.jikesrvm.classloader.MethodReference in project JikesRVM by JikesRVM.

the class BuildReferenceMaps method buildReferenceMaps.

/**
 * After the analysis of the blocks of a method, examine the byte codes again, to
 * determine the reference maps for the gc points. Record the maps with
 * referenceMaps.
 *
 * @param method the method whose bytecodes are to be examined again
 * @param stackHeights height of the expression stack at each bytecode
 * @param localTypes the types that the locals can take
 * @param referenceMaps the reference map. NB: the map's constructor is still running
 *  while this method is called!
 * @param buildBB the buildBB instance that contains the results from the
 *  previous analysis
 *
 * @see BaselineCompiler#localTypes
 * @see TemplateCompilerFramework#stackHeights
 */
public void buildReferenceMaps(NormalMethod method, int[] stackHeights, byte[] localTypes, ReferenceMaps referenceMaps, BuildBB buildBB) {
    // ****************************************************************//
    // These were calculated by BuildBB.determineTheBasicBlocks    //
    // ****************************************************************//
    int gcPointCount = buildBB.gcPointCount;
    short[] byteToBlockMap = buildBB.byteToBlockMap;
    BasicBlock[] basicBlocks = buildBB.basicBlocks;
    int jsrCount = buildBB.numJsrs;
    // The starting map for each block, a block is not
    byte[][] bbMaps;
    // processed until it has a starting map.
    // For each block, track where its current stack top is.
    int[] blockStkTop;
    // Block number of block currently being processed
    int currBBNum;
    // The current map, used during processing thru a block
    byte[] currBBMap;
    // Stack top for the current map
    int currBBStkTop;
    // Level when stack is empty - value depends on number of locals
    final int currBBStkEmpty;
    // Number of parameters to the method being processed
    int paramCount;
    // Variables for processing JSR instructions, RET instructions and JSR subroutines
    PendingRETInfo[] bbPendingRETs = null;
    PendingRETInfo currPendingRET;
    JSRSubroutineInfo[] JSRSubs = null;
    // Blocks that need to be processed are put on the workStk
    short[] workStk;
    // Track whether a block has already been seen once. Any recording of maps done
    // within such a block will be processed as a "rerecording" instead of a new map.
    // 
    boolean[] blockSeen;
    // blocks that represent "catch" blocks need special processing. Catch blocks
    // also referred to as handlers
    // 
    // exception table class for method being processed
    ExceptionHandlerMap exceptions;
    // array of try start indicesinto byte code table
    int[] tryStartPC;
    // array of try end indices into byte code table
    int[] tryEndPC;
    // array of try handlers start indices into bytecode
    int[] tryHandlerPC;
    // length of try handlers array
    int tryHandlerLength;
    // array of reachable handlers from a given try block
    int[] reachableHandlerBBNums;
    // Number of reachable handlers
    int reachableHandlersCount;
    // Handler blocks are processed after the normal flow. As
    boolean[] handlerProcessed;
    // they may be nested, they need to be handled
    // individually. This array is used to track which
    // have been processed.
    boolean handlersAllDone;
    // Other local variables
    // 
    // byte codes for the method
    BytecodeStream bcodes;
    // For processing branches, need block number of target
    short brBBNum;
    final boolean debug = false;
    // Note that the mapping done here is "double mapping" of parameters.
    // Double mapping is when the parameters for a method are included in the map of
    // the method as well as in the map of the caller of the method. The original
    // intent was that with double mapping call sites that are tricks
    // (e.g. Magic.callFunctionReturnVoid ) would at least be correctly mapped on one
    // of the two sides. However with more recent changes to the runtime stack frame
    // layout, the parameters specified on the caller side occupy different
    // locations than the parameters on the callee side for the baseline compiler.
    // Thus both need to be described.
    // 
    // Initialization
    // 
    // Determine what stack empty looks like
    paramCount = method.getParameterWords();
    if (!method.isStatic())
        paramCount++;
    currBBStkEmpty = TemplateCompilerFramework.stackHeightForEmptyBasicBlock(method);
    if (debug) {
        VM.sysWriteln("getLocalWords() : " + method.getLocalWords());
        VM.sysWriteln("getOperandWords() : " + method.getOperandWords());
        VM.sysWriteln("getParameterWords() : " + method.getParameterWords());
    }
    // Get information from the method being processed
    bcodes = method.getBytecodes();
    // Set up the array of maps per block; block 0 is not used
    int numBB = buildBB.bbf.getNumberofBlocks();
    bbMaps = new byte[numBB + 1][];
    blockStkTop = new int[bbMaps.length];
    blockSeen = new boolean[bbMaps.length];
    // Try Handler processing initialization
    exceptions = method.getExceptionHandlerMap();
    if (exceptions != null) {
        tryStartPC = exceptions.getStartPC();
        tryEndPC = exceptions.getEndPC();
        tryHandlerPC = exceptions.getHandlerPC();
        tryHandlerLength = tryHandlerPC.length;
        reachableHandlerBBNums = new int[tryStartPC.length];
        handlerProcessed = new boolean[tryStartPC.length];
        if (jsrCount > 0) {
            JSRSubs = new JSRSubroutineInfo[jsrCount];
            JSRSubNext = 0;
            bbPendingRETs = new PendingRETInfo[bbMaps.length];
        }
        handlersAllDone = (tryHandlerLength == 0);
        // write poison values to help distinguish different errors
        for (int ii = 0; ii < reachableHandlerBBNums.length; ii++) {
            reachableHandlerBBNums[ii] = -1;
        }
    } else {
        tryHandlerLength = 0;
        handlersAllDone = true;
        tryStartPC = null;
        tryEndPC = null;
        tryHandlerPC = null;
        reachableHandlerBBNums = null;
        handlerProcessed = null;
    }
    reachableHandlersCount = 0;
    // Start a new set of maps with the reference Map class.
    // 3rd argument is parameter count included with the maps
    referenceMaps.startNewMaps(gcPointCount, jsrCount, paramCount);
    // Set up the Work stack
    workStk = new short[10 + tryHandlerLength];
    // Start by putting the first block on the work stack
    workStkTop = 0;
    workStk[workStkTop] = byteToBlockMap[0];
    currBBMap = new byte[method.getOperandWords() + currBBStkEmpty + 1];
    // 
    // Need to include the parameters of this method in the map
    // 
    TypeReference[] parameterTypes = method.getParameterTypes();
    int paramStart;
    if (!method.isStatic()) {
        // implicit "this" object
        currBBMap[0] = REFERENCE;
        localTypes[0] = ADDRESS_TYPE;
        paramStart = 1;
    } else {
        paramStart = 0;
    }
    for (int i = 0; i < parameterTypes.length; i++, paramStart++) {
        TypeReference parameterType = parameterTypes[i];
        if (parameterType.isReferenceType()) {
            localTypes[paramStart] = ADDRESS_TYPE;
            currBBMap[paramStart] = REFERENCE;
        } else {
            currBBMap[paramStart] = NON_REFERENCE;
            if (parameterType.getStackWords() == 2) {
                if (parameterType.isLongType()) {
                    localTypes[paramStart] = LONG_TYPE;
                } else {
                    localTypes[paramStart] = DOUBLE_TYPE;
                }
                paramStart++;
            } else if (parameterType.isFloatType()) {
                localTypes[paramStart] = FLOAT_TYPE;
            } else if (parameterType.isIntLikeType()) {
                localTypes[paramStart] = INT_TYPE;
            } else {
                localTypes[paramStart] = ADDRESS_TYPE;
            }
        }
    }
    // The map for the start of the first block, is stack empty, with none
    // of the locals set yet
    // 
    currBBStkTop = currBBStkEmpty;
    bbMaps[byteToBlockMap[0]] = currBBMap;
    blockStkTop[byteToBlockMap[0]] = currBBStkTop;
    // For all methods, record a map at the start of the method for the corresponding
    // conditional call to "yield".
    referenceMaps.recordStkMap(0, currBBMap, currBBStkTop, false);
    currBBMap = new byte[currBBMap.length];
    // ----------------------------------------------------------
    while (workStkTop > -1) {
        // Get the next item off the work stack
        currBBNum = workStk[workStkTop];
        workStkTop--;
        boolean inJSRSub = false;
        if (bbMaps[currBBNum] != null) {
            currBBStkTop = blockStkTop[currBBNum];
            for (int k = 0; k <= currBBStkTop; k++) {
                currBBMap[k] = bbMaps[currBBNum][k];
            }
            if (jsrCount > 0 && basicBlocks[currBBNum].isInJSR()) {
                inJSRSub = true;
            }
        } else {
            VM.sysWrite("BuildReferenceMaps, error: found a block on work stack with");
            VM.sysWrite(" no starting map. The block number is ");
            VM.sysWrite(basicBlocks[currBBNum].getBlockNumber());
            VM.sysWriteln();
            VM.sysFail("BuildReferenceMaps work stack failure");
        }
        int start = basicBlocks[currBBNum].getStart();
        int end = basicBlocks[currBBNum].getEnd();
        if (jsrCount > 0 && inJSRSub) {
            currPendingRET = bbPendingRETs[currBBNum];
            if (basicBlocks[currBBNum].isTryStart()) {
                for (int k = 0; k < tryHandlerLength; k++) {
                    if (tryStartPC[k] == start) {
                        int handlerBBNum = byteToBlockMap[tryHandlerPC[k]];
                        bbPendingRETs[handlerBBNum] = new PendingRETInfo(currPendingRET);
                    }
                }
            }
            if (currPendingRET == null) {
                int[] preds = basicBlocks[currBBNum].getPredecessors();
                for (int i = 0; i < preds.length; i++) {
                    int predBB = preds[i];
                    if (bbPendingRETs[predBB] != null) {
                        currPendingRET = bbPendingRETs[predBB];
                        break;
                    }
                }
            }
            if (VM.VerifyAssertions) {
                if (currPendingRET == null) {
                    String msg = "No pending return found in block " + currBBNum;
                    VM._assert(VM.NOT_REACHED, msg);
                }
            }
        } else {
            currPendingRET = null;
        }
        boolean inTryBlock;
        if (basicBlocks[currBBNum].isTryBlock()) {
            inTryBlock = true;
            reachableHandlersCount = 0;
            for (int i = 0; i < tryHandlerLength; i++) {
                if (start <= tryEndPC[i] && end >= tryStartPC[i]) {
                    reachableHandlerBBNums[reachableHandlersCount] = byteToBlockMap[tryHandlerPC[i]];
                    reachableHandlersCount++;
                    int handlerBBNum = byteToBlockMap[tryHandlerPC[i]];
                    if (bbMaps[handlerBBNum] == null) {
                        bbMaps[handlerBBNum] = new byte[currBBMap.length];
                        for (int k = 0; k <= currBBStkEmpty; k++) {
                            bbMaps[handlerBBNum][k] = currBBMap[k];
                        }
                        bbMaps[handlerBBNum][currBBStkEmpty + 1] = REFERENCE;
                        blockStkTop[handlerBBNum] = currBBStkEmpty + 1;
                    } else {
                        if (inJSRSub && basicBlocks[handlerBBNum].isInJSR()) {
                            // Ensure SET_TO_NONREFERENCE is carried across
                            for (int k = 0; k <= currBBStkEmpty; k++) {
                                if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != SET_TO_NONREFERENCE) {
                                    handlerProcessed[i] = false;
                                    bbMaps[handlerBBNum][k] = SET_TO_NONREFERENCE;
                                }
                            }
                        } else if (inJSRSub) {
                            // realise JSR and SET_TO_NONREFERENCE becomes NON_REFERENCE
                            for (int k = 0; k <= currBBStkEmpty; k++) {
                                if (currBBMap[k] == SET_TO_NONREFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) {
                                    handlerProcessed[i] = false;
                                    bbMaps[handlerBBNum][k] = NON_REFERENCE;
                                }
                            }
                        } else {
                            // No JSRs involved, simply ensure NON_REFERENCE is carried over
                            for (int k = 0; k <= currBBStkEmpty; k++) {
                                if (currBBMap[k] == NON_REFERENCE && bbMaps[handlerBBNum][k] != NON_REFERENCE) {
                                    handlerProcessed[i] = false;
                                    bbMaps[handlerBBNum][k] = NON_REFERENCE;
                                }
                            }
                        }
                    }
                }
            }
        } else {
            inTryBlock = false;
        }
        boolean processNextBlock = true;
        bcodes.reset(start);
        while (bcodes.index() <= end) {
            int biStart = bcodes.index();
            int opcode = bcodes.nextInstruction();
            if (stackHeights != null) {
                if (VM.VerifyAssertions) {
                    if (currBBStkTop < currBBStkEmpty) {
                        String msg = "Stack height for current basic block is " + currBBStkTop + " which is less than the stack height for " + "an empty block (" + currBBStkEmpty + ").";
                        VM._assert(VM.NOT_REACHED, msg);
                    }
                }
                stackHeights[biStart] = currBBStkTop;
            }
            if (debug) {
                VM.sysWriteln("bytecode: " + JBC_name(opcode) + " (opcode : " + opcode + ")");
                VM.sysWrite("current map: ");
                for (int j = 0; j <= currBBStkTop; j++) {
                    VM.sysWrite(currBBMap[j]);
                }
                VM.sysWriteln();
            }
            switch(opcode) {
                case JBC_nop:
                    {
                        break;
                    }
                case JBC_aconst_null:
                    {
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = REFERENCE;
                        break;
                    }
                case JBC_aload_0:
                    {
                        int localNumber = 0;
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
                        break;
                    }
                case JBC_aload_1:
                    {
                        int localNumber = 1;
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
                        break;
                    }
                case JBC_aload_2:
                    {
                        int localNumber = 2;
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
                        break;
                    }
                case JBC_aload_3:
                    {
                        int localNumber = 3;
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
                        break;
                    }
                case JBC_aload:
                    {
                        int localNumber = bcodes.getLocalNumber();
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = inJSRSub ? REFERENCE : currBBMap[localNumber];
                        break;
                    }
                case JBC_iconst_m1:
                case JBC_iconst_0:
                case JBC_iconst_1:
                case JBC_iconst_2:
                case JBC_iconst_3:
                case JBC_iconst_4:
                case JBC_iconst_5:
                case JBC_fconst_0:
                case JBC_fconst_1:
                case JBC_fconst_2:
                case JBC_iload_0:
                case JBC_iload_1:
                case JBC_iload_2:
                case JBC_iload_3:
                case JBC_fload_0:
                case JBC_fload_1:
                case JBC_fload_2:
                case JBC_fload_3:
                case JBC_bipush:
                case JBC_iload:
                case JBC_fload:
                case JBC_sipush:
                case JBC_i2l:
                case JBC_i2d:
                case JBC_f2l:
                case JBC_f2d:
                    {
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = NON_REFERENCE;
                        // contains mix of 1,2,3 byte bytecodes
                        bcodes.skipInstruction();
                        break;
                    }
                case JBC_lconst_0:
                case JBC_lconst_1:
                case JBC_dconst_0:
                case JBC_dconst_1:
                case JBC_lload_0:
                case JBC_lload_1:
                case JBC_lload_2:
                case JBC_lload_3:
                case JBC_dload_0:
                case JBC_dload_1:
                case JBC_dload_2:
                case JBC_dload_3:
                case JBC_ldc2_w:
                case JBC_lload:
                case JBC_dload:
                    {
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = NON_REFERENCE;
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = NON_REFERENCE;
                        // mix of 1, 2, and 3 byte bytecodes
                        bcodes.skipInstruction();
                        break;
                    }
                case JBC_ldc:
                    {
                        currBBStkTop++;
                        int cpi = bcodes.getConstantIndex();
                        int type = bcodes.getConstantType(cpi);
                        if (type == CP_STRING || type == CP_CLASS) {
                            currBBMap[currBBStkTop] = REFERENCE;
                        } else {
                            currBBMap[currBBStkTop] = NON_REFERENCE;
                        }
                        break;
                    }
                case JBC_ldc_w:
                    {
                        currBBStkTop++;
                        int cpi = bcodes.getWideConstantIndex();
                        int type = bcodes.getConstantType(cpi);
                        if (type == CP_STRING || type == CP_CLASS) {
                            currBBMap[currBBStkTop] = REFERENCE;
                        } else {
                            currBBMap[currBBStkTop] = NON_REFERENCE;
                        }
                        break;
                    }
                case JBC_istore:
                    {
                        int index = bcodes.getLocalNumber();
                        if (!inJSRSub) {
                            currBBMap[index] = NON_REFERENCE;
                        } else {
                            currBBMap[index] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[index] |= INT_TYPE;
                        break;
                    }
                case JBC_fstore:
                    {
                        int index = bcodes.getLocalNumber();
                        if (!inJSRSub) {
                            currBBMap[index] = NON_REFERENCE;
                        } else {
                            currBBMap[index] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(index, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[index] |= FLOAT_TYPE;
                        break;
                    }
                case JBC_lstore:
                    {
                        int index = bcodes.getLocalNumber();
                        if (!inJSRSub) {
                            currBBMap[index] = NON_REFERENCE;
                            currBBMap[index + 1] = NON_REFERENCE;
                        } else {
                            currBBMap[index] = SET_TO_NONREFERENCE;
                            currBBMap[index + 1] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[index] |= LONG_TYPE;
                        break;
                    }
                case JBC_dstore:
                    {
                        int index = bcodes.getLocalNumber();
                        if (!inJSRSub) {
                            currBBMap[index] = NON_REFERENCE;
                            currBBMap[index + 1] = NON_REFERENCE;
                        } else {
                            currBBMap[index] = SET_TO_NONREFERENCE;
                            currBBMap[index + 1] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(index, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[index] |= DOUBLE_TYPE;
                        break;
                    }
                case JBC_astore:
                    {
                        int index = bcodes.getLocalNumber();
                        // may be a reference or a return address
                        currBBMap[index] = currBBMap[currBBStkTop];
                        if (inJSRSub) {
                            if (currBBMap[index] == RETURN_ADDRESS) {
                                currPendingRET.updateReturnAddressLocation(index);
                            }
                            if (inTryBlock) {
                                if (currBBMap[index] == REFERENCE) {
                                    setHandlersMapsRef(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                } else {
                                    setHandlersMapsReturnAddress(index, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                }
                            }
                        }
                        currBBStkTop--;
                        localTypes[index] |= ADDRESS_TYPE;
                        break;
                    }
                case JBC_istore_0:
                    {
                        if (!inJSRSub) {
                            currBBMap[0] = NON_REFERENCE;
                        } else {
                            currBBMap[0] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[0] |= INT_TYPE;
                        break;
                    }
                case JBC_fstore_0:
                    {
                        if (!inJSRSub) {
                            currBBMap[0] = NON_REFERENCE;
                        } else {
                            currBBMap[0] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(0, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[0] |= FLOAT_TYPE;
                        break;
                    }
                case JBC_istore_1:
                    {
                        if (!inJSRSub) {
                            currBBMap[1] = NON_REFERENCE;
                        } else {
                            currBBMap[1] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[1] |= INT_TYPE;
                        break;
                    }
                case JBC_fstore_1:
                    {
                        if (!inJSRSub) {
                            currBBMap[1] = NON_REFERENCE;
                        } else {
                            currBBMap[1] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(1, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[1] |= FLOAT_TYPE;
                        break;
                    }
                case JBC_istore_2:
                    {
                        if (!inJSRSub) {
                            currBBMap[2] = NON_REFERENCE;
                        } else {
                            currBBMap[2] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[2] |= INT_TYPE;
                        break;
                    }
                case JBC_fstore_2:
                    {
                        if (!inJSRSub) {
                            currBBMap[2] = NON_REFERENCE;
                        } else {
                            currBBMap[2] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(2, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[2] |= FLOAT_TYPE;
                        break;
                    }
                case JBC_istore_3:
                    {
                        if (!inJSRSub) {
                            currBBMap[3] = NON_REFERENCE;
                        } else {
                            currBBMap[3] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[3] |= INT_TYPE;
                        break;
                    }
                case JBC_fstore_3:
                    {
                        if (!inJSRSub) {
                            currBBMap[3] = NON_REFERENCE;
                        } else {
                            currBBMap[3] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(3, PrimitiveSize.ONEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop--;
                        localTypes[3] |= FLOAT_TYPE;
                        break;
                    }
                case JBC_lstore_0:
                    {
                        if (inJSRSub) {
                            currBBMap[0] = NON_REFERENCE;
                            currBBMap[1] = NON_REFERENCE;
                        } else {
                            currBBMap[0] = SET_TO_NONREFERENCE;
                            currBBMap[1] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[0] |= LONG_TYPE;
                        break;
                    }
                case JBC_dstore_0:
                    {
                        if (inJSRSub) {
                            currBBMap[0] = NON_REFERENCE;
                            currBBMap[1] = NON_REFERENCE;
                        } else {
                            currBBMap[0] = SET_TO_NONREFERENCE;
                            currBBMap[1] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(0, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[0] |= DOUBLE_TYPE;
                        break;
                    }
                case JBC_lstore_1:
                    {
                        if (!inJSRSub) {
                            currBBMap[1] = NON_REFERENCE;
                            currBBMap[2] = NON_REFERENCE;
                        } else {
                            currBBMap[1] = SET_TO_NONREFERENCE;
                            currBBMap[2] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[1] |= LONG_TYPE;
                        break;
                    }
                case JBC_dstore_1:
                    {
                        if (!inJSRSub) {
                            currBBMap[1] = NON_REFERENCE;
                            currBBMap[2] = NON_REFERENCE;
                        } else {
                            currBBMap[1] = SET_TO_NONREFERENCE;
                            currBBMap[2] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(1, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[1] |= DOUBLE_TYPE;
                        break;
                    }
                case JBC_lstore_2:
                    {
                        if (!inJSRSub) {
                            currBBMap[2] = NON_REFERENCE;
                            currBBMap[3] = NON_REFERENCE;
                        } else {
                            currBBMap[2] = SET_TO_NONREFERENCE;
                            currBBMap[3] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[2] |= LONG_TYPE;
                        break;
                    }
                case JBC_dstore_2:
                    {
                        if (!inJSRSub) {
                            currBBMap[2] = NON_REFERENCE;
                            currBBMap[3] = NON_REFERENCE;
                        } else {
                            currBBMap[2] = SET_TO_NONREFERENCE;
                            currBBMap[3] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(2, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[2] |= DOUBLE_TYPE;
                        break;
                    }
                case JBC_lstore_3:
                    {
                        if (!inJSRSub) {
                            currBBMap[3] = NON_REFERENCE;
                            currBBMap[4] = NON_REFERENCE;
                        } else {
                            currBBMap[3] = SET_TO_NONREFERENCE;
                            currBBMap[4] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[3] |= LONG_TYPE;
                        break;
                    }
                case JBC_dstore_3:
                    {
                        if (!inJSRSub) {
                            currBBMap[3] = NON_REFERENCE;
                            currBBMap[4] = NON_REFERENCE;
                        } else {
                            currBBMap[3] = SET_TO_NONREFERENCE;
                            currBBMap[4] = SET_TO_NONREFERENCE;
                        }
                        if (inTryBlock) {
                            setHandlersMapsNonRef(3, PrimitiveSize.DOUBLEWORD, reachableHandlerBBNums, reachableHandlersCount, inJSRSub, bbMaps);
                        }
                        currBBStkTop = currBBStkTop - 2;
                        localTypes[3] |= DOUBLE_TYPE;
                        break;
                    }
                case JBC_astore_0:
                    {
                        currBBMap[0] = currBBMap[currBBStkTop];
                        if (inJSRSub) {
                            if (currBBMap[0] == RETURN_ADDRESS) {
                                currPendingRET.updateReturnAddressLocation(0);
                            }
                            if (inTryBlock) {
                                if (currBBMap[0] == REFERENCE) {
                                    setHandlersMapsRef(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                } else {
                                    setHandlersMapsReturnAddress(0, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                }
                            }
                        }
                        currBBStkTop--;
                        localTypes[0] |= ADDRESS_TYPE;
                        break;
                    }
                case JBC_astore_1:
                    {
                        currBBMap[1] = currBBMap[currBBStkTop];
                        if (inJSRSub) {
                            if (currBBMap[1] == RETURN_ADDRESS) {
                                currPendingRET.updateReturnAddressLocation(1);
                            }
                            if (inTryBlock) {
                                if (currBBMap[1] == REFERENCE) {
                                    setHandlersMapsRef(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                } else {
                                    setHandlersMapsReturnAddress(1, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                }
                            }
                        }
                        currBBStkTop--;
                        localTypes[1] |= ADDRESS_TYPE;
                        break;
                    }
                case JBC_astore_2:
                    {
                        currBBMap[2] = currBBMap[currBBStkTop];
                        if (inJSRSub) {
                            if (currBBMap[2] == RETURN_ADDRESS) {
                                currPendingRET.updateReturnAddressLocation(2);
                            }
                            if (inTryBlock) {
                                if (currBBMap[2] == REFERENCE) {
                                    setHandlersMapsRef(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                } else {
                                    setHandlersMapsReturnAddress(2, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                }
                            }
                        }
                        currBBStkTop--;
                        localTypes[2] |= ADDRESS_TYPE;
                        break;
                    }
                case JBC_astore_3:
                    {
                        currBBMap[3] = currBBMap[currBBStkTop];
                        if (inJSRSub) {
                            if (currBBMap[3] == RETURN_ADDRESS) {
                                currPendingRET.updateReturnAddressLocation(3);
                            }
                            if (inTryBlock) {
                                if (currBBMap[3] == REFERENCE) {
                                    setHandlersMapsRef(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                } else {
                                    setHandlersMapsReturnAddress(3, reachableHandlerBBNums, reachableHandlersCount, bbMaps);
                                }
                            }
                        }
                        currBBStkTop--;
                        localTypes[3] |= ADDRESS_TYPE;
                        break;
                    }
                case JBC_dup:
                    {
                        currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
                        currBBStkTop++;
                        break;
                    }
                case JBC_dup2:
                    {
                        currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
                        currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
                        currBBStkTop = currBBStkTop + 2;
                        break;
                    }
                case JBC_dup_x1:
                    {
                        currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
                        currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
                        currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 1];
                        currBBStkTop++;
                        break;
                    }
                case JBC_dup2_x1:
                    {
                        currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
                        currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
                        currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2];
                        currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop + 2];
                        currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1];
                        currBBStkTop = currBBStkTop + 2;
                        break;
                    }
                case JBC_dup_x2:
                    {
                        currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop];
                        currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
                        currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 2];
                        currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 1];
                        currBBStkTop++;
                        break;
                    }
                case JBC_dup2_x2:
                    {
                        currBBMap[currBBStkTop + 2] = currBBMap[currBBStkTop];
                        currBBMap[currBBStkTop + 1] = currBBMap[currBBStkTop - 1];
                        currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 2];
                        currBBMap[currBBStkTop - 1] = currBBMap[currBBStkTop - 3];
                        currBBMap[currBBStkTop - 2] = currBBMap[currBBStkTop + 2];
                        currBBMap[currBBStkTop - 3] = currBBMap[currBBStkTop + 1];
                        currBBStkTop = currBBStkTop + 2;
                        break;
                    }
                case JBC_swap:
                    {
                        byte temp;
                        temp = currBBMap[currBBStkTop];
                        currBBMap[currBBStkTop] = currBBMap[currBBStkTop - 1];
                        currBBMap[currBBStkTop - 1] = temp;
                        break;
                    }
                case JBC_pop:
                case JBC_iadd:
                case JBC_fadd:
                case JBC_isub:
                case JBC_fsub:
                case JBC_imul:
                case JBC_fmul:
                case JBC_fdiv:
                case JBC_frem:
                case JBC_ishl:
                case JBC_ishr:
                case JBC_iushr:
                // long shifts that int shift value
                case JBC_lshl:
                case JBC_lshr:
                case JBC_lushr:
                case JBC_iand:
                case JBC_ior:
                case JBC_ixor:
                case JBC_l2i:
                case JBC_l2f:
                case JBC_d2i:
                case JBC_d2f:
                case JBC_fcmpl:
                case JBC_fcmpg:
                    {
                        currBBStkTop--;
                        bcodes.skipInstruction();
                        break;
                    }
                case JBC_irem:
                case JBC_idiv:
                    {
                        // record map after 2 integers popped off stack
                        currBBStkTop = currBBStkTop - 2;
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop++;
                        break;
                    }
                case JBC_ladd:
                case JBC_dadd:
                case JBC_lsub:
                case JBC_dsub:
                case JBC_lmul:
                case JBC_dmul:
                case JBC_ddiv:
                case JBC_drem:
                case JBC_land:
                case JBC_lor:
                case JBC_lxor:
                case JBC_pop2:
                    {
                        currBBStkTop = currBBStkTop - 2;
                        break;
                    }
                case JBC_lrem:
                case JBC_ldiv:
                    {
                        // record map after 2 longs popped off stack
                        currBBStkTop = currBBStkTop - 4;
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop = currBBStkTop + 2;
                        break;
                    }
                case JBC_ineg:
                case JBC_lneg:
                case JBC_fneg:
                case JBC_dneg:
                case JBC_iinc:
                case JBC_i2f:
                case JBC_l2d:
                case JBC_f2i:
                case JBC_d2l:
                case JBC_int2byte:
                case JBC_int2char:
                case JBC_int2short:
                    {
                        bcodes.skipInstruction();
                        break;
                    }
                case JBC_lcmp:
                case JBC_dcmpl:
                case JBC_dcmpg:
                    {
                        currBBStkTop = currBBStkTop - 3;
                        break;
                    }
                case JBC_ifeq:
                case JBC_ifne:
                case JBC_iflt:
                case JBC_ifge:
                case JBC_ifgt:
                case JBC_ifle:
                    {
                        int offset = bcodes.getBranchOffset();
                        if (offset <= 0) {
                            if (!inJSRSub) {
                                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                            } else {
                                // in a jsr subroutine
                                referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                            }
                        }
                        // process the basic block logic
                        currBBStkTop--;
                        if (offset <= 0) {
                            short fallThruBBNum = byteToBlockMap[biStart + 3];
                            workStk = processBranchBB(fallThruBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                            processNextBlock = false;
                        }
                        brBBNum = byteToBlockMap[biStart + offset];
                        workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        break;
                    }
                case JBC_if_icmpeq:
                case JBC_if_icmpne:
                case JBC_if_icmplt:
                case JBC_if_icmpge:
                case JBC_if_icmpgt:
                case JBC_if_icmple:
                case JBC_if_acmpeq:
                case JBC_if_acmpne:
                    {
                        int offset = bcodes.getBranchOffset();
                        if (offset <= 0) {
                            if (!inJSRSub) {
                                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                            } else {
                                // in a jsr subroutine
                                referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                            }
                        }
                        // process the basic blocks
                        currBBStkTop = currBBStkTop - 2;
                        if (offset <= 0) {
                            short fallThruBBNum = byteToBlockMap[biStart + 3];
                            workStk = processBranchBB(fallThruBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                            processNextBlock = false;
                        }
                        brBBNum = byteToBlockMap[biStart + offset];
                        workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        break;
                    }
                case JBC_ifnull:
                case JBC_ifnonnull:
                    {
                        int offset = bcodes.getBranchOffset();
                        if (offset <= 0) {
                            if (!inJSRSub) {
                                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                            } else {
                                // in a jsr subroutine
                                referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                            }
                        }
                        // process the basic block logic
                        currBBStkTop--;
                        if (offset <= 0) {
                            short fallThruBBNum = byteToBlockMap[biStart + 3];
                            workStk = processBranchBB(fallThruBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                            processNextBlock = false;
                        }
                        brBBNum = byteToBlockMap[biStart + offset];
                        workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        break;
                    }
                case JBC_goto:
                    {
                        int offset = bcodes.getBranchOffset();
                        if (offset <= 0) {
                            // Register the reference map
                            if (!inJSRSub) {
                                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                            } else {
                                // in a jsr subroutine
                                referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                            }
                        }
                        // process the basic block logic
                        brBBNum = byteToBlockMap[biStart + offset];
                        workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        processNextBlock = false;
                        break;
                    }
                case JBC_goto_w:
                    {
                        int offset = bcodes.getWideBranchOffset();
                        if (offset <= 0) {
                            if (!inJSRSub) {
                                referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                            } else {
                                // in a jsr subroutine
                                referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                            }
                        }
                        // process basic block structures
                        brBBNum = byteToBlockMap[biStart + offset];
                        workStk = processBranchBB(brBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        processNextBlock = false;
                        break;
                    }
                case JBC_tableswitch:
                    {
                        currBBStkTop--;
                        bcodes.alignSwitch();
                        // get default offset and process branch to default branch point
                        int def = bcodes.getDefaultSwitchOffset();
                        workStk = processBranchBB(byteToBlockMap[biStart + def], currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        int low = bcodes.getLowSwitchValue();
                        int high = bcodes.getHighSwitchValue();
                        int n = high - low + 1;
                        // generate labels for offsets
                        for (int k = 0; k < n; k++) {
                            int offset = bcodes.getTableSwitchOffset(k);
                            workStk = processBranchBB(byteToBlockMap[biStart + offset], currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        }
                        bcodes.skipTableSwitchOffsets(n);
                        processNextBlock = false;
                        break;
                    }
                case JBC_lookupswitch:
                    {
                        currBBStkTop--;
                        bcodes.alignSwitch();
                        // get default offset and process branch to default branch point
                        int def = bcodes.getDefaultSwitchOffset();
                        workStk = processBranchBB(byteToBlockMap[biStart + def], currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        int npairs = bcodes.getSwitchLength();
                        // generate label for each offset in table
                        for (int k = 0; k < npairs; k++) {
                            int offset = bcodes.getLookupSwitchOffset(k);
                            workStk = processBranchBB(byteToBlockMap[biStart + offset], currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
                        }
                        bcodes.skipLookupSwitchPairs(npairs);
                        processNextBlock = false;
                        break;
                    }
                case JBC_jsr:
                    {
                        processNextBlock = false;
                        int offset = bcodes.getBranchOffset();
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkEmpty, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = RETURN_ADDRESS;
                        workStk = processJSR(byteToBlockMap[biStart], biStart + offset, byteToBlockMap[biStart + offset], byteToBlockMap[biStart + 3], bbMaps, currBBStkTop, currBBMap, currBBStkEmpty, blockStkTop, bbPendingRETs, currPendingRET, JSRSubs, workStk);
                        break;
                    }
                case JBC_jsr_w:
                    {
                        processNextBlock = false;
                        int offset = bcodes.getWideBranchOffset();
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkEmpty, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkEmpty, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = RETURN_ADDRESS;
                        workStk = processJSR(byteToBlockMap[biStart], biStart + offset, byteToBlockMap[biStart + offset], byteToBlockMap[biStart + 5], bbMaps, currBBStkTop, currBBMap, currBBStkEmpty, blockStkTop, bbPendingRETs, currPendingRET, JSRSubs, workStk);
                        break;
                    }
                case JBC_ret:
                    {
                        int index = bcodes.getLocalNumber();
                        // Can not be used again as a return addr.
                        // 
                        currBBMap[index] = SET_TO_NONREFERENCE;
                        processNextBlock = false;
                        int subStart = currPendingRET.JSRSubStartByteIndex;
                        int k;
                        for (k = 0; k < JSRSubNext; k++) {
                            if (JSRSubs[k].subroutineByteCodeStart == subStart) {
                                JSRSubs[k].newEndMaps(currBBMap, currBBStkTop);
                                break;
                            }
                        }
                        boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null;
                        workStk = computeJSRNextMaps(currPendingRET.JSRNextBBNum, currBBMap.length, k, JSRisinJSRSub, bbMaps, blockStkTop, JSRSubs, currBBStkEmpty, workStk);
                        if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) {
                            bbPendingRETs[currPendingRET.JSRNextBBNum] = new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]);
                        }
                        break;
                    }
                case JBC_invokevirtual:
                case JBC_invokespecial:
                    {
                        MethodReference target = bcodes.getMethodReference();
                        currBBStkTop = processInvoke(target, biStart, currBBStkTop, currBBMap, false, inJSRSub, referenceMaps, currPendingRET, blockSeen[currBBNum], currBBStkEmpty);
                        break;
                    }
                case JBC_invokeinterface:
                    {
                        MethodReference target = bcodes.getMethodReference();
                        bcodes.alignInvokeInterface();
                        currBBStkTop = processInvoke(target, biStart, currBBStkTop, currBBMap, false, inJSRSub, referenceMaps, currPendingRET, blockSeen[currBBNum], currBBStkEmpty);
                        break;
                    }
                case JBC_invokestatic:
                    {
                        MethodReference target = bcodes.getMethodReference();
                        currBBStkTop = processInvoke(target, biStart, currBBStkTop, currBBMap, true, inJSRSub, referenceMaps, currPendingRET, blockSeen[currBBNum], currBBStkEmpty);
                        break;
                    }
                case JBC_ireturn:
                case JBC_lreturn:
                case JBC_freturn:
                case JBC_dreturn:
                case JBC_areturn:
                case JBC_return:
                    {
                        if (VM.UseEpilogueYieldPoints || method.isSynchronized()) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        }
                        processNextBlock = false;
                        break;
                    }
                case JBC_getstatic:
                    {
                        // Register the reference map (could cause dynamic linking)
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
                        currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE;
                        if (fieldType.getStackWords() == 2) {
                            currBBMap[++currBBStkTop] = NON_REFERENCE;
                        }
                        break;
                    }
                case JBC_putstatic:
                    {
                        // Register the reference map (could cause dynamic linking)
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
                        currBBStkTop--;
                        if (fieldType.getStackWords() == 2) {
                            currBBStkTop--;
                        }
                        break;
                    }
                case JBC_getfield:
                    {
                        TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
                        // Register the reference map (could cause dynamic linking..if so there will be a NPE, but the linking happens first.)
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        // pop object pointer
                        currBBStkTop--;
                        currBBMap[++currBBStkTop] = fieldType.isPrimitiveType() ? NON_REFERENCE : REFERENCE;
                        if (fieldType.getStackWords() == 2) {
                            currBBMap[++currBBStkTop] = NON_REFERENCE;
                        }
                        break;
                    }
                case JBC_putfield:
                    {
                        TypeReference fieldType = bcodes.getFieldReference().getFieldContentsType();
                        // note: putfield could result in a call to the classloader
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        // remove objectref and one value
                        currBBStkTop -= 2;
                        if (fieldType.getStackWords() == 2) {
                            currBBStkTop--;
                        }
                        break;
                    }
                case JBC_checkcast:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        bcodes.skipInstruction();
                        break;
                    }
                case JBC_instanceof:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBMap[currBBStkTop] = NON_REFERENCE;
                        bcodes.skipInstruction();
                        break;
                    }
                case JBC_new:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop++;
                        currBBMap[currBBStkTop] = REFERENCE;
                        bcodes.skipInstruction();
                        break;
                    }
                // altered yet.
                case JBC_iaload:
                case JBC_faload:
                case JBC_baload:
                case JBC_caload:
                case JBC_saload:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop--;
                        currBBMap[currBBStkTop] = NON_REFERENCE;
                        break;
                    }
                case JBC_laload:
                case JBC_daload:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBMap[currBBStkTop - 1] = NON_REFERENCE;
                        break;
                    }
                case JBC_aaload:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop--;
                        break;
                    }
                // Stack has not been modified at this point.
                case JBC_iastore:
                case JBC_fastore:
                case JBC_aastore:
                case JBC_bastore:
                case JBC_castore:
                case JBC_sastore:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop = currBBStkTop - 3;
                        break;
                    }
                case JBC_lastore:
                case JBC_dastore:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop = currBBStkTop - 4;
                        break;
                    }
                case JBC_newarray:
                case JBC_anewarray:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBMap[currBBStkTop] = REFERENCE;
                        bcodes.skipInstruction();
                        break;
                    }
                case JBC_multianewarray:
                    {
                        bcodes.getTypeReference();
                        int dim = bcodes.getArrayDimension();
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop = currBBStkTop - dim + 1;
                        currBBMap[currBBStkTop] = REFERENCE;
                        break;
                    }
                case JBC_arraylength:
                    {
                        currBBMap[currBBStkTop] = NON_REFERENCE;
                        break;
                    }
                case JBC_athrow:
                    {
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        currBBStkTop = currBBStkEmpty + 1;
                        currBBMap[currBBStkTop] = REFERENCE;
                        processNextBlock = false;
                        break;
                    }
                case JBC_monitorenter:
                case JBC_monitorexit:
                    {
                        currBBStkTop--;
                        if (!inJSRSub) {
                            referenceMaps.recordStkMap(biStart, currBBMap, currBBStkTop, blockSeen[currBBNum]);
                        } else {
                            referenceMaps.recordJSRSubroutineMap(biStart, currBBMap, currBBStkTop, currPendingRET.returnAddressLocation, blockSeen[currBBNum]);
                        }
                        break;
                    }
                case JBC_wide:
                    {
                        int widecode = bcodes.getWideOpcode();
                        int index = bcodes.getWideLocalNumber();
                        switch(widecode) {
                            case JBC_iload:
                            case JBC_fload:
                                {
                                    currBBStkTop++;
                                    currBBMap[currBBStkTop] = NON_REFERENCE;
                                    break;
                                }
                            case JBC_lload:
                            case JBC_dload:
                                {
                                    currBBStkTop++;
                                    currBBMap[currBBStkTop] = NON_REFERENCE;
                                    currBBStkTop++;
                                    currBBMap[currBBStkTop] = NON_REFERENCE;
                                    break;
                                }
                            case JBC_aload:
                                {
                                    currBBStkTop++;
                                    currBBMap[currBBStkTop] = currBBMap[index];
                                    break;
                                }
                            case JBC_istore:
                                {
                                    if (!inJSRSub) {
                                        currBBMap[index] = NON_REFERENCE;
                                    } else {
                                        currBBMap[index] = SET_TO_NONREFERENCE;
                                    }
                                    currBBStkTop--;
                                    localTypes[index] |= INT_TYPE;
                                    break;
                                }
                            case JBC_fstore:
                                {
                                    if (!inJSRSub) {
                                        currBBMap[index] = NON_REFERENCE;
                                    } else {
                                        currBBMap[index] = SET_TO_NONREFERENCE;
                                    }
                                    currBBStkTop--;
                                    localTypes[index] |= FLOAT_TYPE;
                                    break;
                                }
                            case JBC_lstore:
                                {
                                    if (!inJSRSub) {
                                        currBBMap[index] = NON_REFERENCE;
                                        currBBMap[index + 1] = NON_REFERENCE;
                                    } else {
                                        currBBMap[index] = SET_TO_NONREFERENCE;
                                        currBBMap[index + 1] = SET_TO_NONREFERENCE;
                                    }
                                    currBBStkTop = currBBStkTop - 2;
                                    localTypes[index] |= LONG_TYPE;
                                    break;
                                }
                            case JBC_dstore:
                                {
                                    if (!inJSRSub) {
                                        currBBMap[index] = NON_REFERENCE;
                                        currBBMap[index + 1] = NON_REFERENCE;
                                    } else {
                                        currBBMap[index] = SET_TO_NONREFERENCE;
                                        currBBMap[index + 1] = SET_TO_NONREFERENCE;
                                    }
                                    currBBStkTop = currBBStkTop - 2;
                                    localTypes[index] |= DOUBLE_TYPE;
                                    break;
                                }
                            case JBC_astore:
                                {
                                    currBBMap[index] = currBBMap[currBBStkTop];
                                    currBBStkTop--;
                                    localTypes[index] |= ADDRESS_TYPE;
                                    break;
                                }
                            case JBC_iinc:
                                {
                                    bcodes.getWideIncrement();
                                    break;
                                }
                            case JBC_ret:
                                {
                                    // Can not be used again as a return addr.
                                    // 
                                    currBBMap[index] = SET_TO_NONREFERENCE;
                                    processNextBlock = false;
                                    int subStart = currPendingRET.JSRSubStartByteIndex;
                                    int k;
                                    for (k = 0; k < JSRSubNext; k++) {
                                        if (JSRSubs[k].subroutineByteCodeStart == subStart) {
                                            JSRSubs[k].newEndMaps(currBBMap, currBBStkTop);
                                            break;
                                        }
                                    }
                                    boolean JSRisinJSRSub = bbPendingRETs[currPendingRET.JSRBBNum] != null;
                                    workStk = computeJSRNextMaps(currPendingRET.JSRNextBBNum, currBBMap.length, k, JSRisinJSRSub, bbMaps, blockStkTop, JSRSubs, currBBStkEmpty, workStk);
                                    if (JSRisinJSRSub && bbPendingRETs[currPendingRET.JSRNextBBNum] == null) {
                                        bbPendingRETs[currPendingRET.JSRNextBBNum] = new PendingRETInfo(bbPendingRETs[currPendingRET.JSRBBNum]);
                                    }
                                    break;
                                }
                            default:
                                // switch on widecode
                                if (VM.VerifyAssertions)
                                    VM._assert(VM.NOT_REACHED);
                        }
                        break;
                    }
                default:
                    {
                        VM.sysFail("Unknown opcode:" + opcode);
                    }
            }
        // end switch (opcode)
        }
        // for start to end
        blockSeen[currBBNum] = true;
        if (processNextBlock) {
            short fallThruBBNum = byteToBlockMap[bcodes.index()];
            workStk = processBranchBB(fallThruBBNum, currBBStkTop, currBBMap, currBBStkEmpty, inJSRSub, bbMaps, blockStkTop, currPendingRET, bbPendingRETs, workStk);
        }
        // 
        if ((workStkTop == -1) && !handlersAllDone) {
            int i;
            for (i = 0; i < tryHandlerLength; i++) {
                // the try block must be in one of the other handlers
                if (!handlerProcessed[i] && bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null)
                    break;
            }
            if (i == tryHandlerLength) {
                handlersAllDone = true;
            } else {
                int considerIndex = i;
                while (i != tryHandlerLength) {
                    int tryStart = tryStartPC[considerIndex];
                    int tryEnd = tryEndPC[considerIndex];
                    for (i = 0; i < tryHandlerLength; i++) {
                        // I'm not entirely convinced this is right, but don't know what else we can do. --dave
                        if (i == considerIndex)
                            continue;
                        // we are considering working on.
                        if (!handlerProcessed[i] && tryStart <= tryHandlerPC[i] && tryHandlerPC[i] < tryEnd && bbMaps[byteToBlockMap[tryHandlerPC[i]]] != null) {
                            break;
                        }
                    }
                    if (i != tryHandlerLength) {
                        considerIndex = i;
                    }
                }
                short blockNum = byteToBlockMap[tryHandlerPC[considerIndex]];
                handlerProcessed[considerIndex] = true;
                workStk = addToWorkStk(blockNum, workStk);
            }
        }
    }
    // while workStk not empty
    // Indicate that any temporaries can be freed
    referenceMaps.recordingComplete();
}
Also used : ExceptionHandlerMap(org.jikesrvm.classloader.ExceptionHandlerMap) BytecodeStream(org.jikesrvm.classloader.BytecodeStream) MethodReference(org.jikesrvm.classloader.MethodReference) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 2 with MethodReference

use of org.jikesrvm.classloader.MethodReference in project JikesRVM by JikesRVM.

the class JNIHelpers method invokeInitializer.

/**
 * Common code shared by the JNI functions NewObjectA, NewObjectV, NewObject
 * (object creation)
 * @param cls class whose constructor is to be invoked
 * @param methodID the method ID for a constructor
 * @param argAddress where to find the arguments for the constructor
 * @param isJvalue {@code true} if parameters are passed as a jvalue array
 * @param isDotDotStyle {@code true} if the method uses varargs
 * @return a new object created by the specified constructor
 * @throws Exception when the reflective invocation of the constructor fails
 */
public static Object invokeInitializer(Class<?> cls, int methodID, Address argAddress, boolean isJvalue, boolean isDotDotStyle) throws Exception {
    // get the parameter list as Java class
    MemberReference mr = MemberReference.getMemberRef(methodID);
    TypeReference tr = java.lang.JikesRVMSupport.getTypeForClass(cls).getTypeRef();
    MethodReference methodRef = MemberReference.findOrCreate(tr, mr.getName(), mr.getDescriptor()).asMethodReference();
    RVMMethod mth = methodRef.resolve();
    Constructor<?> constMethod = java.lang.reflect.JikesRVMSupport.createConstructor(mth);
    if (!mth.isPublic()) {
        constMethod.setAccessible(true);
    }
    // Package the parameters for the constructor
    Address varargAddress;
    if (isDotDotStyle) {
        // flag is false because this JNI function has 3 args before the var args
        varargAddress = getVarArgAddress(false);
    } else {
        varargAddress = argAddress;
    }
    Object[] argObjs;
    if (isJvalue) {
        argObjs = packageParametersFromJValuePtr(methodRef, argAddress);
    } else {
        argObjs = packageParameterFromVarArg(methodRef, varargAddress);
    }
    // construct the new object
    return constMethod.newInstance(argObjs);
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) Address(org.vmmagic.unboxed.Address) MemberReference(org.jikesrvm.classloader.MemberReference) MethodReference(org.jikesrvm.classloader.MethodReference) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 3 with MethodReference

use of org.jikesrvm.classloader.MethodReference in project JikesRVM by JikesRVM.

the class JNIHelpers method invokeWithVarArg.

/**
 * Common code shared by the JNI functions Call&lt;type&gt;MethodV
 * @param obj the object instance
 * @param methodID the method ID
 * @param argAddress a raw address for the variable argument list
 * @param expectReturnType the return type for checking purpose
 * @param skip4Args received from the JNI function, passed on to Reflection.invoke()
 * @return an object that may be the return object or a wrapper for the primitive return value
 * @throws Exception if the return type doesn't match the expected return type
 */
public static Object invokeWithVarArg(Object obj, int methodID, Address argAddress, TypeReference expectReturnType, boolean skip4Args) throws Exception {
    MethodReference mr = MemberReference.getMethodRef(methodID);
    Object[] argObjectArray = packageParameterFromVarArg(mr, argAddress);
    return callMethod(obj, mr, argObjectArray, expectReturnType, skip4Args);
}
Also used : MethodReference(org.jikesrvm.classloader.MethodReference)

Example 4 with MethodReference

use of org.jikesrvm.classloader.MethodReference in project JikesRVM by JikesRVM.

the class JNIHelpers method invokeWithVarArg.

/**
 * Common code shared by the JNI functions CallStatic&lt;type&gt;MethodV
 * @param methodID the method ID
 * @param argAddress a raw address for the variable argument list
 * @param expectReturnType the return type of the method to be invoked
 * @return an object that may be the return object or a wrapper for the primitive return value
 * @throws Exception if the return type doesn't match the expected return type
 */
public static Object invokeWithVarArg(int methodID, Address argAddress, TypeReference expectReturnType) throws Exception {
    MethodReference mr = MemberReference.getMethodRef(methodID);
    Object[] argObjectArray = packageParameterFromVarArg(mr, argAddress);
    return callMethod(null, mr, argObjectArray, expectReturnType, true);
}
Also used : MethodReference(org.jikesrvm.classloader.MethodReference)

Example 5 with MethodReference

use of org.jikesrvm.classloader.MethodReference in project JikesRVM by JikesRVM.

the class JNIHelpers method invokeWithDotDotVarArg.

/**
 * Common code shared by the JNI functions CallStatic&lt;type&gt;Method
 * (static method invocation)
 * @param methodID the method ID
 * @param expectReturnType the return type of the method to be invoked
 * @return an object that may be the return object or a wrapper for the primitive return value
 * @throws Exception if the return type doesn't match the expected return type
 */
@NoInline
@NoOptCompile
public static // expect a certain stack frame structure
Object invokeWithDotDotVarArg(int methodID, TypeReference expectReturnType) throws Exception {
    MethodReference mr = MemberReference.getMethodRef(methodID);
    Address varargAddress = getVarArgAddress(false);
    Object[] argObjectArray = packageParameterFromVarArg(mr, varargAddress);
    return callMethod(null, mr, argObjectArray, expectReturnType, true);
}
Also used : Address(org.vmmagic.unboxed.Address) MethodReference(org.jikesrvm.classloader.MethodReference) NoInline(org.vmmagic.pragma.NoInline) NoOptCompile(org.vmmagic.pragma.NoOptCompile)

Aggregations

MethodReference (org.jikesrvm.classloader.MethodReference)23 RVMMethod (org.jikesrvm.classloader.RVMMethod)8 Address (org.vmmagic.unboxed.Address)7 TypeReference (org.jikesrvm.classloader.TypeReference)6 NoInline (org.vmmagic.pragma.NoInline)4 FieldReference (org.jikesrvm.classloader.FieldReference)3 MemberReference (org.jikesrvm.classloader.MemberReference)3 RVMClass (org.jikesrvm.classloader.RVMClass)3 Offset (org.vmmagic.unboxed.Offset)3 RVMType (org.jikesrvm.classloader.RVMType)2 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)2 ExecutionState (org.jikesrvm.osr.ExecutionState)2 OSRMapIterator (org.jikesrvm.osr.OSRMapIterator)2 VariableElement (org.jikesrvm.osr.VariableElement)2 NoOptCompile (org.vmmagic.pragma.NoOptCompile)2 IOException (java.io.IOException)1 UnResolvedCallSite (org.jikesrvm.adaptive.util.UnResolvedCallSite)1 UnResolvedWeightedCallTargets (org.jikesrvm.adaptive.util.UnResolvedWeightedCallTargets)1 BytecodeStream (org.jikesrvm.classloader.BytecodeStream)1 ExceptionHandlerMap (org.jikesrvm.classloader.ExceptionHandlerMap)1