Search in sources :

Example 11 with MethodReference

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

the class DynamicCallFileInfoReader method readOneCallSiteAttribute.

private static void readOneCallSiteAttribute(StringTokenizer parser, boolean boot) {
    String firstToken = parser.nextToken();
    if (firstToken.equals("CallSite")) {
        try {
            MemberReference callerKey = MemberReference.parse(parser, boot);
            if (callerKey == null)
                return;
            MethodReference callerRef = callerKey.asMethodReference();
            RVMMethod caller, callee;
            caller = getMethod(callerRef);
            // serves as doco - token skipped
            @SuppressWarnings("unused") int callerSize = Integer.parseInt(parser.nextToken());
            int bci = Integer.parseInt(parser.nextToken());
            MemberReference calleeKey = MemberReference.parse(parser, boot);
            if (calleeKey == null)
                return;
            MethodReference calleeRef = calleeKey.asMethodReference();
            callee = getMethod(calleeRef);
            // serves as doco - token skipped
            @SuppressWarnings("unused") int calleeSize = Integer.parseInt(parser.nextToken());
            // skip "weight:"
            parser.nextToken();
            float weight = Float.parseFloat(parser.nextToken());
            if ((caller == null) || (callee == null)) {
                Controller.dcg.incrementUnResolvedEdge(callerRef, bci, calleeRef, weight);
            } else {
                Controller.dcg.incrementEdge(caller, bci, callee, weight);
            }
        } catch (Exception e) {
            VM.sysWriteln("Caught exception: " + e);
        }
    } else {
        VM.sysFail("Format error in dynamic call graph file");
    }
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) MemberReference(org.jikesrvm.classloader.MemberReference) MethodReference(org.jikesrvm.classloader.MethodReference) IOException(java.io.IOException)

Example 12 with MethodReference

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

the class OptExecutionStateExtractor method getExecStateSequence.

private ExecutionState getExecStateSequence(RVMThread thread, byte[] stack, Offset ipOffset, Offset fpOffset, int cmid, Offset tsFPOffset, TempRegisters registers, EncodedOSRMap osrmap) {
    // go through the stack frame and extract values
    // In the variable value list, we keep the order as follows:
    // L0, L1, ..., S0, S1, ....
    /* go over osr map element, build list of VariableElement.
    * assuming iterator has ordered element as
    *     L0, L1, ..., S0, S1, ...
    *
    *     ThreadSwitch
    *     threadSwitchFromOsr
    *     FOO                                        <-- fpOffset
    *
    * Also, all registers saved by threadSwitchFromDeopt method
    * is restored in "registers", address for object is converted
    * back to object references.
    *
    * This method should be called in non-GC critical section since
    * it allocates many objects.
    */
    // for 64-bit type values which have two int parts.
    // this holds the high part.
    int lvalue_one = 0;
    int lvtype_one = 0;
    // now recover execution states
    OSRMapIterator iterator = osrmap.getOsrMapIteratorForMCOffset(ipOffset);
    if (VM.VerifyAssertions)
        VM._assert(iterator != null);
    ExecutionState state = new ExecutionState(thread, fpOffset, cmid, iterator.getBcIndex(), tsFPOffset);
    MethodReference mref = MemberReference.getMethodRef(iterator.getMethodId());
    state.setMethod((NormalMethod) mref.peekResolvedMethod());
    // this is not caller, but the callee, reverse it when outside
    // of this function.
    state.callerState = null;
    if (VM.TraceOnStackReplacement) {
        VM.sysWriteln("osr map table of " + state.meth.toString());
    }
    while (iterator.hasMore()) {
        if (iterator.getMethodId() != state.meth.getId()) {
            ExecutionState newstate = new ExecutionState(thread, fpOffset, cmid, iterator.getBcIndex(), tsFPOffset);
            mref = MemberReference.getMethodRef(iterator.getMethodId());
            newstate.setMethod((NormalMethod) mref.peekResolvedMethod());
            // this is not caller, but the callee, reverse it when outside
            // of this function.
            newstate.callerState = state;
            state = newstate;
            if (VM.TraceOnStackReplacement) {
                VM.sysWriteln("osr map table of " + state.meth.toString());
            }
        }
        // create a VariableElement for it.
        boolean kind = iterator.getKind();
        char num = iterator.getNumber();
        byte tcode = iterator.getTypeCode();
        byte vtype = iterator.getValueType();
        int value = iterator.getValue();
        iterator.moveToNext();
        if (VM.TraceOnStackReplacement) {
            VM.sysWrite((kind == LOCAL) ? "L" : "S");
            VM.sysWrite((int) num);
            VM.sysWrite(" , ");
            if (vtype == ICONST) {
                VM.sysWrite("ICONST ");
                VM.sysWrite(value);
            } else if (vtype == PHYREG) {
                VM.sysWrite("PHYREG ");
                VM.sysWrite(GPR.lookup(value).toString());
            } else if (vtype == SPILL) {
                VM.sysWrite("SPILL  ");
                VM.sysWrite(value);
            }
            VM.sysWriteln();
        }
        switch(tcode) {
            case INT:
                {
                    int ibits = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
                    state.add(new VariableElement(kind, num, tcode, ibits));
                    break;
                }
            case FLOAT:
                {
                    float fv = (float) getDoubleFrom(vtype, value, stack, fpOffset, registers);
                    int ibits = Magic.floatAsIntBits(fv);
                    state.add(new VariableElement(kind, num, tcode, ibits));
                    break;
                }
            case HIGH_64BIT:
                {
                    lvalue_one = value;
                    lvtype_one = vtype;
                    break;
                }
            case LONG:
                {
                    long lbits = getLongBitsFrom(lvtype_one, lvalue_one, vtype, value, stack, fpOffset, registers);
                    lvalue_one = 0;
                    lvtype_one = 0;
                    state.add(new VariableElement(kind, num, LONG, lbits));
                    break;
                }
            case DOUBLE:
                {
                    double dv = getDoubleFrom(vtype, value, stack, fpOffset, registers);
                    long lbits = Magic.doubleAsLongBits(dv);
                    state.add(new VariableElement(kind, num, tcode, lbits));
                    break;
                }
            // To be VERIFIED.
            case RET_ADDR:
                {
                    int bcIndex = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
                    state.add(new VariableElement(kind, num, tcode, bcIndex));
                    break;
                }
            case WORD:
                {
                    // KV:TODO
                    if (VM.BuildFor64Addr) {
                        if (VM.VerifyAssertions) {
                            VM._assert(VM.NOT_REACHED);
                        } else {
                            VM.sysFail("Case not yet implemented for 64-bit addresssing.");
                        }
                    }
                    int word = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
                    state.add(new VariableElement(kind, num, tcode, word));
                    break;
                }
            case REF:
                {
                    Object ref = getObjectFrom(vtype, value, stack, fpOffset, registers);
                    state.add(new VariableElement(kind, num, tcode, ref));
                    break;
                }
            default:
                if (VM.VerifyAssertions)
                    VM._assert(VM.NOT_REACHED);
                break;
        }
    // switch
    }
    return state;
}
Also used : ExecutionState(org.jikesrvm.osr.ExecutionState) MethodReference(org.jikesrvm.classloader.MethodReference) OSRMapIterator(org.jikesrvm.osr.OSRMapIterator) VariableElement(org.jikesrvm.osr.VariableElement)

Example 13 with MethodReference

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

the class OptExecutionStateExtractor method getExecStateSequence.

private ExecutionState getExecStateSequence(RVMThread thread, byte[] stack, Offset ipOffset, Offset fpOffset, int cmid, Offset tsFPOffset, TempRegisters registers, EncodedOSRMap osrmap) {
    // go through the stack frame and extract values
    // In the variable value list, we keep the order as follows:
    // L0, L1, ..., S0, S1, ....
    /* go over osr map element, build list of VariableElement.
    * assuming iterator has ordered element as
    *     L0, L1, ..., S0, S1, ...
    *
    *     RVMThread.ThreadSwitch
    *     OptSaveVolatile.threadSwitchFromDeopt
    *     FOO                                        <-- fpOffset
    *
    * Also, all registers saved by threadSwitchFromDeopt method
    * is restored in "registers", address for object is converted
    * back to object references.
    *
    * This method should be called in non-GC critical section since
    * it allocates many objects.
    */
    // for 64-bit type values which have two int parts.
    // this holds the high part.
    int lpart_one = 0;
    // now recover execution states
    OSRMapIterator iterator = osrmap.getOsrMapIteratorForMCOffset(ipOffset);
    if (VM.VerifyAssertions)
        VM._assert(iterator != null);
    ExecutionState state = new ExecutionState(thread, fpOffset, cmid, iterator.getBcIndex(), tsFPOffset);
    MethodReference mref = MemberReference.getMethodRef(iterator.getMethodId());
    state.setMethod((NormalMethod) mref.peekResolvedMethod());
    state.callerState = null;
    while (iterator.hasMore()) {
        if (iterator.getMethodId() != state.meth.getId()) {
            ExecutionState newstate = new ExecutionState(thread, fpOffset, cmid, iterator.getBcIndex(), tsFPOffset);
            mref = MemberReference.getMethodRef(iterator.getMethodId());
            newstate.setMethod((NormalMethod) mref.peekResolvedMethod());
            // this is not caller, but the callee, reverse it when outside
            // of this function.
            newstate.callerState = state;
            state = newstate;
        }
        // create a VariableElement for it.
        boolean kind = iterator.getKind();
        int num = iterator.getNumber();
        byte tcode = iterator.getTypeCode();
        byte vtype = iterator.getValueType();
        int value = iterator.getValue();
        iterator.moveToNext();
        switch(tcode) {
            case INT:
                {
                    int ibits = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
                    state.add(new VariableElement(kind, num, tcode, ibits));
                    break;
                }
            case FLOAT:
                {
                    float fv = (float) getDoubleFrom(vtype, value, stack, fpOffset, registers);
                    int ibits = Magic.floatAsIntBits(fv);
                    state.add(new VariableElement(kind, num, tcode, ibits));
                    break;
                }
            case HIGH_64BIT:
                {
                    lpart_one = value;
                    break;
                }
            case LONG:
                {
                    long lbits = getLongBitsFrom(vtype, lpart_one, value, stack, fpOffset, registers);
                    lpart_one = 0;
                    state.add(new // not use LONG2,
                    VariableElement(// not use LONG2,
                    kind, // not use LONG2,
                    num, // not use LONG2,
                    LONG, lbits));
                    break;
                }
            case DOUBLE:
                {
                    double dv = getDoubleFrom(vtype, value, stack, fpOffset, registers);
                    long lbits = Magic.doubleAsLongBits(dv);
                    state.add(new VariableElement(kind, num, tcode, lbits));
                    break;
                }
            // To be VERIFIED.
            case RET_ADDR:
                {
                    int bcIndex = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
                    state.add(new VariableElement(kind, num, tcode, bcIndex));
                    break;
                }
            case REF:
                {
                    Object ref = getObjectFrom(vtype, value, stack, fpOffset, registers);
                    state.add(new VariableElement(kind, num, tcode, ref));
                    break;
                }
            case WORD:
                {
                    if (VM.BuildFor32Addr) {
                        int word = getIntBitsFrom(vtype, value, stack, fpOffset, registers);
                        state.add(new VariableElement(kind, num, tcode, word));
                    } else {
                        long word = getLongBitsFrom(vtype, lpart_one, value, stack, fpOffset, registers);
                        lpart_one = 0;
                        state.add(new VariableElement(kind, num, tcode, word));
                    }
                    break;
                }
            default:
                if (VM.VerifyAssertions)
                    VM._assert(VM.NOT_REACHED);
                break;
        }
    // switch
    }
    return state;
}
Also used : ExecutionState(org.jikesrvm.osr.ExecutionState) MethodReference(org.jikesrvm.classloader.MethodReference) OSRMapIterator(org.jikesrvm.osr.OSRMapIterator) VariableElement(org.jikesrvm.osr.VariableElement)

Example 14 with MethodReference

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

the class BaselineCompilerImpl method emit_invoke_compiledmethod.

/**
 * Emit code to invoke a compiled method (with known jtoc offset).
 * Treat it like a resolved invoke static, but take care of
 * this object in the case.<p>
 *
 * I havenot thought about GCMaps for invoke_compiledmethod
 * TODO: Figure out what the above GCMaps comment means and fix it!
 */
@Override
protected void emit_invoke_compiledmethod(CompiledMethod cm) {
    Offset methOffset = cm.getOsrJTOCoffset();
    asm.emitLAddrToc(T0, methOffset);
    asm.emitMTCTR(T0);
    boolean takeThis = !cm.method.isStatic();
    MethodReference ref = cm.method.getMemberRef().asMethodReference();
    genMoveParametersToRegisters(takeThis, ref);
    asm.emitBCCTRL();
    genPopParametersAndPushReturnValue(takeThis, ref);
}
Also used : MethodReference(org.jikesrvm.classloader.MethodReference) Offset(org.vmmagic.unboxed.Offset)

Example 15 with MethodReference

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

the class BC2IR method generateFrom.

/**
 * Generate instructions for a basic block.
 * May discover other basic blocks that need to be generated along the way.
 *
 * @param fromIndex bytecode index to start from
 */
private void generateFrom(int fromIndex) {
    if (DBG_BB || DBG_SELECTED) {
        db("generating code into " + currentBBLE + " with runoff " + runoff);
    }
    currentBBLE.setGenerated();
    endOfBasicBlock = fallThrough = false;
    lastInstr = null;
    bcodes.reset(fromIndex);
    while (true) {
        // Must keep currentBBLE.high up-to-date in case we try to jump into
        // the middle of the block we're currently generating.  Simply updating
        // high once endsBasicBlock is true doesn't enable us to catch this case.
        currentBBLE.high = instrIndex = bcodes.index();
        int code = bcodes.nextInstruction();
        if (DBG_BCPARSE) {
            db("parsing " + instrIndex + " " + code + " : 0x" + Integer.toHexString(code) + " " + JBC_name(code));
        }
        Instruction s = null;
        lastOsrBarrier = null;
        switch(code) {
            case JBC_nop:
                break;
            case JBC_aconst_null:
                push(new NullConstantOperand());
                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:
                push(new IntConstantOperand(code - JBC_iconst_0));
                break;
            case JBC_lconst_0:
            case JBC_lconst_1:
                pushDual(new LongConstantOperand(code - JBC_lconst_0));
                break;
            case JBC_fconst_0:
                push(new FloatConstantOperand(0.f));
                break;
            case JBC_fconst_1:
                push(new FloatConstantOperand(1.f));
                break;
            case JBC_fconst_2:
                push(new FloatConstantOperand(2.f));
                break;
            case JBC_dconst_0:
                pushDual(new DoubleConstantOperand(0.));
                break;
            case JBC_dconst_1:
                pushDual(new DoubleConstantOperand(1.));
                break;
            case JBC_bipush:
                push(new IntConstantOperand(bcodes.getByteValue()));
                break;
            case JBC_sipush:
                push(new IntConstantOperand(bcodes.getShortValue()));
                break;
            case JBC_ldc:
                push(getConstantOperand(bcodes.getConstantIndex()));
                break;
            case JBC_ldc_w:
                push(getConstantOperand(bcodes.getWideConstantIndex()));
                break;
            case JBC_ldc2_w:
                pushDual(getConstantOperand(bcodes.getWideConstantIndex()));
                break;
            case JBC_iload:
                s = do_iload(bcodes.getLocalNumber());
                break;
            case JBC_lload:
                s = do_lload(bcodes.getLocalNumber());
                break;
            case JBC_fload:
                s = do_fload(bcodes.getLocalNumber());
                break;
            case JBC_dload:
                s = do_dload(bcodes.getLocalNumber());
                break;
            case JBC_aload:
                s = do_aload(bcodes.getLocalNumber());
                break;
            case JBC_iload_0:
            case JBC_iload_1:
            case JBC_iload_2:
            case JBC_iload_3:
                s = do_iload(code - JBC_iload_0);
                break;
            case JBC_lload_0:
            case JBC_lload_1:
            case JBC_lload_2:
            case JBC_lload_3:
                s = do_lload(code - JBC_lload_0);
                break;
            case JBC_fload_0:
            case JBC_fload_1:
            case JBC_fload_2:
            case JBC_fload_3:
                s = do_fload(code - JBC_fload_0);
                break;
            case JBC_dload_0:
            case JBC_dload_1:
            case JBC_dload_2:
            case JBC_dload_3:
                s = do_dload(code - JBC_dload_0);
                break;
            case JBC_aload_0:
            case JBC_aload_1:
            case JBC_aload_2:
            case JBC_aload_3:
                s = do_aload(code - JBC_aload_0);
                break;
            case JBC_iaload:
                {
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.IntArray);
                    }
                    s = _aloadHelper(INT_ALOAD, ref, index, TypeReference.Int);
                }
                break;
            case JBC_laload:
                {
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.LongArray);
                    }
                    s = _aloadHelper(LONG_ALOAD, ref, index, TypeReference.Long);
                }
                break;
            case JBC_faload:
                {
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.FloatArray);
                    }
                    s = _aloadHelper(FLOAT_ALOAD, ref, index, TypeReference.Float);
                }
                break;
            case JBC_daload:
                {
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.DoubleArray);
                    }
                    s = _aloadHelper(DOUBLE_ALOAD, ref, index, TypeReference.Double);
                }
                break;
            case JBC_aaload:
                {
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    TypeReference type = getRefTypeOf(ref).getArrayElementType();
                    if (VM.VerifyAssertions)
                        opt_assert(type.isReferenceType());
                    s = _aloadHelper(REF_ALOAD, ref, index, type);
                }
                break;
            case JBC_baload:
                {
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    TypeReference type = getArrayTypeOf(ref);
                    if (VM.VerifyAssertions) {
                        opt_assert(type == TypeReference.ByteArray || type == TypeReference.BooleanArray);
                    }
                    if (type == TypeReference.ByteArray) {
                        s = _aloadHelper(BYTE_ALOAD, ref, index, TypeReference.Byte);
                    } else {
                        s = _aloadHelper(UBYTE_ALOAD, ref, index, TypeReference.Boolean);
                    }
                }
                break;
            case JBC_caload:
                {
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.CharArray);
                    }
                    s = _aloadHelper(USHORT_ALOAD, ref, index, TypeReference.Char);
                }
                break;
            case JBC_saload:
                {
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.ShortArray);
                    }
                    s = _aloadHelper(SHORT_ALOAD, ref, index, TypeReference.Short);
                }
                break;
            case JBC_istore:
                s = do_store(bcodes.getLocalNumber(), popInt());
                break;
            case JBC_lstore:
                s = do_store(bcodes.getLocalNumber(), popLong());
                break;
            case JBC_fstore:
                s = do_store(bcodes.getLocalNumber(), popFloat());
                break;
            case JBC_dstore:
                s = do_store(bcodes.getLocalNumber(), popDouble());
                break;
            case JBC_astore:
                s = do_astore(bcodes.getLocalNumber());
                break;
            case JBC_istore_0:
            case JBC_istore_1:
            case JBC_istore_2:
            case JBC_istore_3:
                s = do_store(code - JBC_istore_0, popInt());
                break;
            case JBC_lstore_0:
            case JBC_lstore_1:
            case JBC_lstore_2:
            case JBC_lstore_3:
                s = do_store(code - JBC_lstore_0, popLong());
                break;
            case JBC_fstore_0:
            case JBC_fstore_1:
            case JBC_fstore_2:
            case JBC_fstore_3:
                s = do_store(code - JBC_fstore_0, popFloat());
                break;
            case JBC_dstore_0:
            case JBC_dstore_1:
            case JBC_dstore_2:
            case JBC_dstore_3:
                s = do_store(code - JBC_dstore_0, popDouble());
                break;
            case JBC_astore_0:
            case JBC_astore_1:
            case JBC_astore_2:
            case JBC_astore_3:
                s = do_astore(code - JBC_astore_0);
                break;
            case JBC_iastore:
                {
                    Operand val = popInt();
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.IntArray);
                    }
                    s = AStore.create(INT_ASTORE, val, ref, index, new LocationOperand(TypeReference.Int), getCurrentGuard());
                }
                break;
            case JBC_lastore:
                {
                    Operand val = popLong();
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.LongArray);
                    }
                    s = AStore.create(LONG_ASTORE, val, ref, index, new LocationOperand(TypeReference.Long), getCurrentGuard());
                }
                break;
            case JBC_fastore:
                {
                    Operand val = popFloat();
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.FloatArray);
                    }
                    s = AStore.create(FLOAT_ASTORE, val, ref, index, new LocationOperand(TypeReference.Float), getCurrentGuard());
                }
                break;
            case JBC_dastore:
                {
                    Operand val = popDouble();
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.DoubleArray);
                    }
                    s = AStore.create(DOUBLE_ASTORE, val, ref, index, new LocationOperand(TypeReference.Double), getCurrentGuard());
                }
                break;
            case JBC_aastore:
                {
                    Operand val = pop();
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    TypeReference type = getRefTypeOf(ref).getArrayElementType();
                    if (VM.VerifyAssertions)
                        opt_assert(type.isReferenceType());
                    if (do_CheckStore(ref, val, type)) {
                        break;
                    }
                    s = AStore.create(REF_ASTORE, val, ref, index, new LocationOperand(type), getCurrentGuard());
                }
                break;
            case JBC_bastore:
                {
                    Operand val = popInt();
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    TypeReference type = getArrayTypeOf(ref);
                    if (VM.VerifyAssertions) {
                        opt_assert(type == TypeReference.ByteArray || type == TypeReference.BooleanArray);
                    }
                    if (type == TypeReference.ByteArray) {
                        type = TypeReference.Byte;
                    } else {
                        type = TypeReference.Boolean;
                    }
                    s = AStore.create(BYTE_ASTORE, val, ref, index, new LocationOperand(type), getCurrentGuard());
                }
                break;
            case JBC_castore:
                {
                    Operand val = popInt();
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.CharArray);
                    }
                    s = AStore.create(SHORT_ASTORE, val, ref, index, new LocationOperand(TypeReference.Char), getCurrentGuard());
                }
                break;
            case JBC_sastore:
                {
                    Operand val = popInt();
                    Operand index = popInt();
                    Operand ref = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(ref) || do_BoundsCheck(ref, index)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        assertIsType(ref, TypeReference.ShortArray);
                    }
                    s = AStore.create(SHORT_ASTORE, val, ref, index, new LocationOperand(TypeReference.Short), getCurrentGuard());
                }
                break;
            case JBC_pop:
                stack.pop();
                break;
            case JBC_pop2:
                stack.pop2();
                break;
            case JBC_dup:
                {
                    Operand op1 = stack.pop();
                    stack.push(op1);
                    s = pushCopy(op1);
                }
                break;
            case JBC_dup_x1:
                {
                    Operand op1 = stack.pop();
                    Operand op2 = stack.pop();
                    stack.push(op1);
                    stack.push(op2);
                    s = pushCopy(op1);
                }
                break;
            case JBC_dup_x2:
                {
                    Operand op1 = stack.pop();
                    Operand op2 = stack.pop();
                    Operand op3 = stack.pop();
                    stack.push(op1);
                    stack.push(op3);
                    stack.push(op2);
                    s = pushCopy(op1);
                }
                break;
            case JBC_dup2:
                {
                    Operand op1 = stack.pop();
                    Operand op2 = stack.pop();
                    stack.push(op2);
                    stack.push(op1);
                    s = pushCopy(op2);
                    if (s != null) {
                        appendInstruction(s);
                        s = null;
                    }
                    s = pushCopy(op1);
                }
                break;
            case JBC_dup2_x1:
                {
                    Operand op1 = stack.pop();
                    Operand op2 = stack.pop();
                    Operand op3 = stack.pop();
                    stack.push(op2);
                    stack.push(op1);
                    stack.push(op3);
                    s = pushCopy(op2);
                    if (s != null) {
                        appendInstruction(s);
                        s = null;
                    }
                    s = pushCopy(op1);
                }
                break;
            case JBC_dup2_x2:
                {
                    Operand op1 = stack.pop();
                    Operand op2 = stack.pop();
                    Operand op3 = stack.pop();
                    Operand op4 = stack.pop();
                    stack.push(op2);
                    stack.push(op1);
                    stack.push(op4);
                    stack.push(op3);
                    s = pushCopy(op2);
                    if (s != null) {
                        appendInstruction(s);
                        s = null;
                    }
                    s = pushCopy(op1);
                }
                break;
            case JBC_swap:
                {
                    stack.swap();
                }
                break;
            case JBC_iadd:
                {
                    Operand op2 = popInt();
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_ADD, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_ladd:
                {
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_ADD, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_fadd:
                {
                    Operand op2 = popFloat();
                    Operand op1 = popFloat();
                    s = _binaryHelper(FLOAT_ADD, op1, op2, TypeReference.Float);
                }
                break;
            case JBC_dadd:
                {
                    Operand op2 = popDouble();
                    Operand op1 = popDouble();
                    s = _binaryDualHelper(DOUBLE_ADD, op1, op2, TypeReference.Double);
                }
                break;
            case JBC_isub:
                {
                    Operand op2 = popInt();
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_SUB, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_lsub:
                {
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_SUB, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_fsub:
                {
                    Operand op2 = popFloat();
                    Operand op1 = popFloat();
                    s = _binaryHelper(FLOAT_SUB, op1, op2, TypeReference.Float);
                }
                break;
            case JBC_dsub:
                {
                    Operand op2 = popDouble();
                    Operand op1 = popDouble();
                    s = _binaryDualHelper(DOUBLE_SUB, op1, op2, TypeReference.Double);
                }
                break;
            case JBC_imul:
                {
                    Operand op2 = popInt();
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_MUL, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_lmul:
                {
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_MUL, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_fmul:
                {
                    Operand op2 = popFloat();
                    Operand op1 = popFloat();
                    s = _binaryHelper(FLOAT_MUL, op1, op2, TypeReference.Float);
                }
                break;
            case JBC_dmul:
                {
                    Operand op2 = popDouble();
                    Operand op1 = popDouble();
                    s = _binaryDualHelper(DOUBLE_MUL, op1, op2, TypeReference.Double);
                }
                break;
            case JBC_idiv:
                {
                    clearCurrentGuard();
                    Operand op2 = popInt();
                    Operand op1 = popInt();
                    if (do_IntZeroCheck(op2)) {
                        break;
                    }
                    s = _guardedBinaryHelper(INT_DIV, op1, op2, getCurrentGuard(), TypeReference.Int);
                }
                break;
            case JBC_ldiv:
                {
                    clearCurrentGuard();
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    if (do_LongZeroCheck(op2)) {
                        break;
                    }
                    s = _guardedBinaryDualHelper(LONG_DIV, op1, op2, getCurrentGuard(), TypeReference.Long);
                }
                break;
            case JBC_fdiv:
                {
                    Operand op2 = popFloat();
                    Operand op1 = popFloat();
                    s = _binaryHelper(FLOAT_DIV, op1, op2, TypeReference.Float);
                }
                break;
            case JBC_ddiv:
                {
                    Operand op2 = popDouble();
                    Operand op1 = popDouble();
                    s = _binaryDualHelper(DOUBLE_DIV, op1, op2, TypeReference.Double);
                }
                break;
            case JBC_irem:
                {
                    clearCurrentGuard();
                    Operand op2 = popInt();
                    Operand op1 = popInt();
                    if (do_IntZeroCheck(op2)) {
                        break;
                    }
                    s = _guardedBinaryHelper(INT_REM, op1, op2, getCurrentGuard(), TypeReference.Int);
                }
                break;
            case JBC_lrem:
                {
                    clearCurrentGuard();
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    if (do_LongZeroCheck(op2)) {
                        break;
                    }
                    s = _guardedBinaryDualHelper(LONG_REM, op1, op2, getCurrentGuard(), TypeReference.Long);
                }
                break;
            case JBC_frem:
                {
                    Operand op2 = popFloat();
                    Operand op1 = popFloat();
                    s = _binaryHelper(FLOAT_REM, op1, op2, TypeReference.Float);
                }
                break;
            case JBC_drem:
                {
                    Operand op2 = popDouble();
                    Operand op1 = popDouble();
                    s = _binaryDualHelper(DOUBLE_REM, op1, op2, TypeReference.Double);
                }
                break;
            case JBC_ineg:
                s = _unaryHelper(INT_NEG, popInt(), TypeReference.Int);
                break;
            case JBC_lneg:
                s = _unaryDualHelper(LONG_NEG, popLong(), TypeReference.Long);
                break;
            case JBC_fneg:
                s = _unaryHelper(FLOAT_NEG, popFloat(), TypeReference.Float);
                break;
            case JBC_dneg:
                s = _unaryDualHelper(DOUBLE_NEG, popDouble(), TypeReference.Double);
                break;
            case JBC_ishl:
                {
                    Operand op2 = popShiftInt(false);
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_SHL, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_lshl:
                {
                    Operand op2 = popShiftInt(true);
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_SHL, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_ishr:
                {
                    Operand op2 = popShiftInt(false);
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_SHR, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_lshr:
                {
                    Operand op2 = popShiftInt(true);
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_SHR, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_iushr:
                {
                    Operand op2 = popShiftInt(false);
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_USHR, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_lushr:
                {
                    Operand op2 = popShiftInt(true);
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_USHR, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_iand:
                {
                    Operand op2 = popInt();
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_AND, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_land:
                {
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_AND, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_ior:
                {
                    Operand op2 = popInt();
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_OR, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_lor:
                {
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_OR, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_ixor:
                {
                    Operand op2 = popInt();
                    Operand op1 = popInt();
                    s = _binaryHelper(INT_XOR, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_lxor:
                {
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    s = _binaryDualHelper(LONG_XOR, op1, op2, TypeReference.Long);
                }
                break;
            case JBC_iinc:
                {
                    int index = bcodes.getLocalNumber();
                    s = do_iinc(index, bcodes.getIncrement());
                }
                break;
            case JBC_i2l:
                s = _unaryDualHelper(INT_2LONG, popInt(), TypeReference.Long);
                break;
            case JBC_i2f:
                s = _unaryHelper(INT_2FLOAT, popInt(), TypeReference.Float);
                break;
            case JBC_i2d:
                s = _unaryDualHelper(INT_2DOUBLE, popInt(), TypeReference.Double);
                break;
            case JBC_l2i:
                s = _unaryHelper(LONG_2INT, popLong(), TypeReference.Int);
                break;
            case JBC_l2f:
                s = _unaryHelper(LONG_2FLOAT, popLong(), TypeReference.Float);
                break;
            case JBC_l2d:
                s = _unaryDualHelper(LONG_2DOUBLE, popLong(), TypeReference.Double);
                break;
            case JBC_f2i:
                s = _unaryHelper(FLOAT_2INT, popFloat(), TypeReference.Int);
                break;
            case JBC_f2l:
                s = _unaryDualHelper(FLOAT_2LONG, popFloat(), TypeReference.Long);
                break;
            case JBC_f2d:
                s = _unaryDualHelper(FLOAT_2DOUBLE, popFloat(), TypeReference.Double);
                break;
            case JBC_d2i:
                s = _unaryHelper(DOUBLE_2INT, popDouble(), TypeReference.Int);
                break;
            case JBC_d2l:
                s = _unaryDualHelper(DOUBLE_2LONG, popDouble(), TypeReference.Long);
                break;
            case JBC_d2f:
                s = _unaryHelper(DOUBLE_2FLOAT, popDouble(), TypeReference.Float);
                break;
            case JBC_int2byte:
                s = _unaryHelper(INT_2BYTE, popInt(), TypeReference.Byte);
                break;
            case JBC_int2char:
                s = _unaryHelper(INT_2USHORT, popInt(), TypeReference.Char);
                break;
            case JBC_int2short:
                s = _unaryHelper(INT_2SHORT, popInt(), TypeReference.Short);
                break;
            case JBC_lcmp:
                {
                    Operand op2 = popLong();
                    Operand op1 = popLong();
                    s = _binaryHelper(LONG_CMP, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_fcmpl:
                {
                    Operand op2 = popFloat();
                    Operand op1 = popFloat();
                    s = _binaryHelper(FLOAT_CMPL, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_fcmpg:
                {
                    Operand op2 = popFloat();
                    Operand op1 = popFloat();
                    s = _binaryHelper(FLOAT_CMPG, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_dcmpl:
                {
                    Operand op2 = popDouble();
                    Operand op1 = popDouble();
                    s = _binaryHelper(DOUBLE_CMPL, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_dcmpg:
                {
                    Operand op2 = popDouble();
                    Operand op1 = popDouble();
                    s = _binaryHelper(DOUBLE_CMPG, op1, op2, TypeReference.Int);
                }
                break;
            case JBC_ifeq:
                s = _intIfHelper(ConditionOperand.EQUAL());
                break;
            case JBC_ifne:
                s = _intIfHelper(ConditionOperand.NOT_EQUAL());
                break;
            case JBC_iflt:
                s = _intIfHelper(ConditionOperand.LESS());
                break;
            case JBC_ifge:
                s = _intIfHelper(ConditionOperand.GREATER_EQUAL());
                break;
            case JBC_ifgt:
                s = _intIfHelper(ConditionOperand.GREATER());
                break;
            case JBC_ifle:
                s = _intIfHelper(ConditionOperand.LESS_EQUAL());
                break;
            case JBC_if_icmpeq:
                s = _intIfCmpHelper(ConditionOperand.EQUAL());
                break;
            case JBC_if_icmpne:
                s = _intIfCmpHelper(ConditionOperand.NOT_EQUAL());
                break;
            case JBC_if_icmplt:
                s = _intIfCmpHelper(ConditionOperand.LESS());
                break;
            case JBC_if_icmpge:
                s = _intIfCmpHelper(ConditionOperand.GREATER_EQUAL());
                break;
            case JBC_if_icmpgt:
                s = _intIfCmpHelper(ConditionOperand.GREATER());
                break;
            case JBC_if_icmple:
                s = _intIfCmpHelper(ConditionOperand.LESS_EQUAL());
                break;
            case JBC_if_acmpeq:
                s = _refIfCmpHelper(ConditionOperand.EQUAL());
                break;
            case JBC_if_acmpne:
                s = _refIfCmpHelper(ConditionOperand.NOT_EQUAL());
                break;
            case JBC_goto:
                {
                    int offset = bcodes.getBranchOffset();
                    if (offset != 3) {
                        // skip generating frivolous goto's
                        s = _gotoHelper(offset);
                    }
                }
                break;
            case JBC_jsr:
                s = _jsrHelper(bcodes.getBranchOffset());
                break;
            case JBC_ret:
                s = _retHelper(bcodes.getLocalNumber());
                break;
            case JBC_tableswitch:
                {
                    bcodes.alignSwitch();
                    Operand op0 = popInt();
                    int defaultoff = bcodes.getDefaultSwitchOffset();
                    int low = bcodes.getLowSwitchValue();
                    int high = bcodes.getHighSwitchValue();
                    int number = high - low + 1;
                    if (CF_TABLESWITCH && op0 instanceof IntConstantOperand) {
                        int v1 = ((IntConstantOperand) op0).value;
                        int match = bcodes.computeTableSwitchOffset(v1, low, high);
                        int offset = match == 0 ? defaultoff : match;
                        bcodes.skipTableSwitchOffsets(number);
                        if (DBG_CF) {
                            db("changed tableswitch to goto because index (" + v1 + ") is constant");
                        }
                        s = _gotoHelper(offset);
                        break;
                    }
                    s = TableSwitch.create(TABLESWITCH, op0, null, null, new IntConstantOperand(low), new IntConstantOperand(high), generateTarget(defaultoff), null, number * 2);
                    for (int i = 0; i < number; ++i) {
                        TableSwitch.setTarget(s, i, generateTarget(bcodes.getTableSwitchOffset(i)));
                    }
                    bcodes.skipTableSwitchOffsets(number);
                    // Set branch probabilities
                    SwitchBranchProfile sp = gc.getSwitchProfile(instrIndex - bciAdjustment);
                    if (sp == null) {
                        // number targets + default
                        float approxProb = 1.0f / (number + 1);
                        TableSwitch.setDefaultBranchProfile(s, new BranchProfileOperand(approxProb));
                        for (int i = 0; i < number; ++i) {
                            TableSwitch.setBranchProfile(s, i, new BranchProfileOperand(approxProb));
                        }
                    } else {
                        TableSwitch.setDefaultBranchProfile(s, new BranchProfileOperand(sp.getDefaultProbability()));
                        for (int i = 0; i < number; ++i) {
                            TableSwitch.setBranchProfile(s, i, new BranchProfileOperand(sp.getCaseProbability(i)));
                        }
                    }
                }
                break;
            case JBC_lookupswitch:
                {
                    bcodes.alignSwitch();
                    Operand op0 = popInt();
                    int defaultoff = bcodes.getDefaultSwitchOffset();
                    int numpairs = bcodes.getSwitchLength();
                    if (numpairs == 0) {
                        s = _gotoHelper(defaultoff);
                        break;
                    }
                    if (CF_LOOKUPSWITCH && op0 instanceof IntConstantOperand) {
                        int v1 = ((IntConstantOperand) op0).value;
                        int match = bcodes.computeLookupSwitchOffset(v1, numpairs);
                        int offset = match == 0 ? defaultoff : match;
                        bcodes.skipLookupSwitchPairs(numpairs);
                        if (DBG_CF) {
                            db("changed lookupswitch to goto because index (" + v1 + ") is constant");
                        }
                        s = _gotoHelper(offset);
                        break;
                    }
                    // Construct switch
                    s = LookupSwitch.create(LOOKUPSWITCH, op0, null, null, generateTarget(defaultoff), null, numpairs * 3);
                    for (int i = 0; i < numpairs; ++i) {
                        LookupSwitch.setMatch(s, i, new IntConstantOperand(bcodes.getLookupSwitchValue(i)));
                        LookupSwitch.setTarget(s, i, generateTarget(bcodes.getLookupSwitchOffset(i)));
                    }
                    bcodes.skipLookupSwitchPairs(numpairs);
                    // Set branch probabilities
                    SwitchBranchProfile sp = gc.getSwitchProfile(instrIndex - bciAdjustment);
                    if (sp == null) {
                        // num targets + default
                        float approxProb = 1.0f / (numpairs + 1);
                        LookupSwitch.setDefaultBranchProfile(s, new BranchProfileOperand(approxProb));
                        for (int i = 0; i < numpairs; ++i) {
                            LookupSwitch.setBranchProfile(s, i, new BranchProfileOperand(approxProb));
                        }
                    } else {
                        LookupSwitch.setDefaultBranchProfile(s, new BranchProfileOperand(sp.getDefaultProbability()));
                        for (int i = 0; i < numpairs; ++i) {
                            LookupSwitch.setBranchProfile(s, i, new BranchProfileOperand(sp.getCaseProbability(i)));
                        }
                    }
                }
                break;
            case JBC_ireturn:
                _returnHelper(INT_MOVE, popInt());
                break;
            case JBC_lreturn:
                _returnHelper(LONG_MOVE, popLong());
                break;
            case JBC_freturn:
                _returnHelper(FLOAT_MOVE, popFloat());
                break;
            case JBC_dreturn:
                _returnHelper(DOUBLE_MOVE, popDouble());
                break;
            case JBC_areturn:
                {
                    Operand op0 = popRef();
                    if (VM.VerifyAssertions && !op0.isDefinitelyNull()) {
                        TypeReference retType = op0.getType();
                        assertIsAssignable(gc.getMethod().getReturnType(), retType);
                    }
                    _returnHelper(REF_MOVE, op0);
                }
                break;
            case JBC_return:
                _returnHelper(null, null);
                break;
            case JBC_getstatic:
                {
                    // field resolution
                    FieldReference ref = bcodes.getFieldReference();
                    boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
                    LocationOperand fieldOp = makeStaticFieldRef(ref);
                    Operand offsetOp;
                    TypeReference fieldType = ref.getFieldContentsType();
                    RegisterOperand t = gc.getTemps().makeTemp(fieldType);
                    if (unresolved) {
                        RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                        appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), fieldOp.copy()));
                        offsetOp = offsetrop;
                        rectifyStateWithErrorHandler();
                    } else {
                        RVMField field = ref.peekResolvedField();
                        offsetOp = new AddressConstantOperand(field.getOffset());
                        // use results of field analysis to refine type of result
                        RVMType ft = fieldType.peekType();
                        if (ft != null && ft.isClassType()) {
                            TypeReference concreteType = FieldAnalysis.getConcreteType(field);
                            if (concreteType != null) {
                                if (concreteType == fieldType) {
                                    t.setDeclaredType();
                                    t.setPreciseType();
                                } else {
                                    fieldType = concreteType;
                                    t.setPreciseType(concreteType);
                                }
                            }
                        }
                        // time.
                        if (gc.getOptions().SIMPLIFY_CHASE_FINAL_FIELDS && field.isFinal()) {
                            RVMClass declaringClass = field.getDeclaringClass();
                            boolean initializedClassAtRuntime = VM.runningVM & declaringClass.isInitialized();
                            boolean fieldFromRVMInternalClassInBootImage = declaringClass.isInBootImage() && declaringClass.getDescriptor().isRVMDescriptor();
                            // We cannot assume that non-public fields from the host JVM's class library are present in
                            // the class library used by Jikes RVM: only public fields are part of the API.
                            boolean publicFieldInBootImage = declaringClass.isInBootImage() && field.isPublic();
                            if (initializedClassAtRuntime || fieldFromRVMInternalClassInBootImage || publicFieldInBootImage) {
                                try {
                                    ConstantOperand rhs = StaticFieldReader.getStaticFieldValue(field);
                                    // VM.sysWriteln("Replaced getstatic of " + field + " with " + rhs);
                                    push(rhs, fieldType);
                                    break;
                                } catch (NoSuchFieldException e) {
                                    if (VM.runningVM) {
                                        throw new Error("Unexpected exception", e);
                                    } else {
                                    // Field not found during bootstrap due to chasing a field
                                    // only valid in the bootstrap JVM.
                                    // Although we try to avoid most cases where this could happen, we cannot
                                    // avoid all. For example, a NoSuchFieldException can occur when we're trying
                                    // to optimize a public field from Jikes RVM's class library that's not present
                                    // in the host JVM's class library (example: a field from an internal
                                    // helper class).
                                    }
                                }
                            }
                        } else if (field.isRuntimeFinal()) {
                            if (VM.VerifyAssertions)
                                opt_assert(fieldType.isBooleanType());
                            boolean rhsBool = field.getRuntimeFinalValue();
                            push(new IntConstantOperand(rhsBool ? 1 : 0));
                            break;
                        }
                    }
                    s = GetStatic.create(GETSTATIC, t, offsetOp, fieldOp);
                    if (fieldOp.mayBeVolatile()) {
                        appendInstruction(s);
                        s = Empty.create(READ_CEILING);
                    }
                    push(t.copyD2U(), fieldType);
                }
                break;
            case JBC_putstatic:
                {
                    // field resolution
                    FieldReference ref = bcodes.getFieldReference();
                    boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
                    LocationOperand fieldOp = makeStaticFieldRef(ref);
                    Operand offsetOp;
                    if (unresolved) {
                        RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                        appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), fieldOp.copy()));
                        offsetOp = offsetrop;
                        rectifyStateWithErrorHandler();
                    } else {
                        RVMField field = ref.peekResolvedField();
                        offsetOp = new AddressConstantOperand(field.getOffset());
                    }
                    TypeReference fieldType = ref.getFieldContentsType();
                    Operand r = pop(fieldType);
                    if (fieldOp.mayBeVolatile()) {
                        appendInstruction(Empty.create(WRITE_FLOOR));
                    }
                    s = PutStatic.create(PUTSTATIC, r, offsetOp, fieldOp);
                    if (fieldOp.mayBeVolatile()) {
                        appendInstruction(s);
                        s = Empty.create(FENCE);
                    }
                }
                break;
            case JBC_getfield:
                {
                    // field resolution
                    FieldReference ref = bcodes.getFieldReference();
                    boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
                    LocationOperand fieldOp = makeInstanceFieldRef(ref);
                    Operand offsetOp;
                    TypeReference fieldType = ref.getFieldContentsType();
                    RVMField field = null;
                    RegisterOperand t = gc.getTemps().makeTemp(fieldType);
                    if (unresolved) {
                        RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                        appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), fieldOp.copy()));
                        offsetOp = offsetrop;
                        rectifyStateWithErrorHandler();
                    } else {
                        field = ref.peekResolvedField();
                        offsetOp = new AddressConstantOperand(field.getOffset());
                        // use results of field analysis to refine type.
                        RVMType ft = fieldType.peekType();
                        if (ft != null && ft.isClassType()) {
                            TypeReference concreteType = FieldAnalysis.getConcreteType(field);
                            if (concreteType != null) {
                                if (concreteType == fieldType) {
                                    t.setDeclaredType();
                                    t.setPreciseType();
                                } else {
                                    fieldType = concreteType;
                                    t.setType(concreteType);
                                    t.setPreciseType();
                                }
                            }
                        }
                    }
                    Operand op1 = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(op1)) {
                        break;
                    }
                    // NB avoid String fields
                    if (op1.isConstant() && field.isFinal()) {
                        try {
                            ConstantOperand rhs = StaticFieldReader.getFieldValueAsConstant(field, op1.asObjectConstant().value);
                            push(rhs, fieldType);
                            break;
                        } catch (NoSuchFieldException e) {
                            if (VM.runningVM) {
                                // this is unexpected
                                throw new Error("Unexpected exception", e);
                            } else {
                            // Field not found during bootstrap due to chasing a field
                            // only valid in the bootstrap JVM
                            }
                        }
                    }
                    s = GetField.create(GETFIELD, t, op1, offsetOp, fieldOp, getCurrentGuard());
                    if (fieldOp.mayBeVolatile()) {
                        appendInstruction(s);
                        s = Empty.create(READ_CEILING);
                    }
                    push(t.copyD2U(), fieldType);
                }
                break;
            case JBC_putfield:
                {
                    // field resolution
                    FieldReference ref = bcodes.getFieldReference();
                    boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
                    LocationOperand fieldOp = makeInstanceFieldRef(ref);
                    TypeReference fieldType = ref.getFieldContentsType();
                    Operand offsetOp;
                    if (unresolved) {
                        RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                        appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), fieldOp.copy()));
                        offsetOp = offsetrop;
                        rectifyStateWithErrorHandler();
                    } else {
                        RVMField field = ref.peekResolvedField();
                        offsetOp = new AddressConstantOperand(field.getOffset());
                    }
                    Operand val = pop(fieldType);
                    Operand obj = popRef();
                    clearCurrentGuard();
                    if (do_NullCheck(obj)) {
                        break;
                    }
                    if (fieldOp.mayBeVolatile()) {
                        appendInstruction(Empty.create(WRITE_FLOOR));
                    }
                    s = PutField.create(PUTFIELD, val, obj, offsetOp, fieldOp, getCurrentGuard());
                    if (fieldOp.mayBeVolatile()) {
                        appendInstruction(s);
                        s = Empty.create(FENCE);
                    }
                }
                break;
            case JBC_invokevirtual:
                {
                    MethodReference ref = bcodes.getMethodReference();
                    // If it is, generate the inline code and we are done.
                    if (ref.isMagic()) {
                        boolean generated = GenerateMagic.generateMagic(this, gc, ref);
                        // all done.
                        if (generated)
                            break;
                    }
                    /* just create an osr barrier right before _callHelper
           * changes the states of locals and stacks.
           */
                    if (this.osrGuardedInline) {
                        lastOsrBarrier = _createOsrBarrier();
                    }
                    if (ref.isMiranda()) {
                        // An invokevirtual that is really an invokeinterface.
                        s = _callHelper(ref, MethodOperand.INTERFACE(ref, null));
                        if (s == null)
                            break;
                        Operand receiver = Call.getParam(s, 0);
                        RVMClass receiverType = (RVMClass) receiver.getType().peekType();
                        // null check on this parameter of call
                        clearCurrentGuard();
                        if (do_NullCheck(receiver)) {
                            // call will always raise null pointer exception
                            s = null;
                            break;
                        }
                        Call.setGuard(s, getCurrentGuard());
                        // Attempt to resolve the interface call to a particular virtual method.
                        // This is independent of whether or not the static type of the receiver is
                        // known to implement the interface and it is not that case that being able
                        // to prove one implies the other.
                        RVMMethod vmeth = null;
                        if (receiverType != null && receiverType.isInitialized() && !receiverType.isInterface()) {
                            vmeth = ClassLoaderProxy.lookupMethod(receiverType, ref);
                        }
                        if (vmeth != null) {
                            MethodReference vmethRef = vmeth.getMemberRef().asMethodReference();
                            MethodOperand mop = MethodOperand.VIRTUAL(vmethRef, vmeth);
                            if (receiver.isConstant() || (receiver.isRegister() && receiver.asRegister().isPreciseType())) {
                                mop.refine(vmeth, true);
                            }
                            Call.setMethod(s, mop);
                            boolean unresolved = vmethRef.needsDynamicLink(bcodes.getMethod());
                            if (unresolved) {
                                RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                                appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
                                Call.setAddress(s, offsetrop);
                                rectifyStateWithErrorHandler();
                            } else {
                                Call.setAddress(s, new AddressConstantOperand(vmeth.getOffset()));
                            }
                            // Attempt to inline virtualized call.
                            if (maybeInlineMethod(shouldInline(s, receiver.isConstant() || (receiver.isRegister() && receiver.asRegister().isExtant()), instrIndex - bciAdjustment), s)) {
                                return;
                            }
                        }
                    } else {
                        // A normal invokevirtual.  Create call instruction.
                        boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
                        RVMMethod target = ref.peekResolvedMethod();
                        MethodOperand methOp = MethodOperand.VIRTUAL(ref, target);
                        s = _callHelper(ref, methOp);
                        if (s == null)
                            break;
                        // Must be done before null_check!
                        if (unresolved) {
                            RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                            appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
                            Call.setAddress(s, offsetrop);
                            rectifyStateWithErrorHandler();
                        } else {
                            if (VM.VerifyAssertions)
                                opt_assert(target != null);
                            Call.setAddress(s, new AddressConstantOperand(target.getOffset()));
                        }
                        // null check receiver
                        Operand receiver = Call.getParam(s, 0);
                        clearCurrentGuard();
                        if (do_NullCheck(receiver)) {
                            // call will always raise null pointer exception
                            s = null;
                            break;
                        }
                        Call.setGuard(s, getCurrentGuard());
                        // Use compile time type of receiver to try reduce the number
                        // of targets.
                        // If we succeed, we'll update meth and s's method operand.
                        boolean isExtant = false;
                        boolean isPreciseType = false;
                        TypeReference tr = null;
                        if (receiver.isRegister()) {
                            RegisterOperand rop = receiver.asRegister();
                            isExtant = rop.isExtant();
                            isPreciseType = rop.isPreciseType();
                            tr = rop.getType();
                        } else {
                            isExtant = true;
                            isPreciseType = true;
                            tr = receiver.getType();
                        }
                        RVMType type = tr.peekType();
                        if (type != null && type.isResolved()) {
                            if (type.isClassType()) {
                                RVMMethod vmeth = target;
                                if (target == null || type != target.getDeclaringClass()) {
                                    vmeth = ClassLoaderProxy.lookupMethod(type.asClass(), ref);
                                }
                                if (vmeth != null) {
                                    methOp.refine(vmeth, isPreciseType || type.asClass().isFinal());
                                }
                            } else {
                                // Array: will always be calling the method defined in java.lang.Object
                                if (VM.VerifyAssertions)
                                    opt_assert(target != null, "Huh?  Target method must already be resolved if receiver is array");
                                methOp.refine(target, true);
                            }
                        }
                        // Consider inlining it.
                        if (maybeInlineMethod(shouldInline(s, isExtant, instrIndex - bciAdjustment), s)) {
                            return;
                        }
                    }
                    // noninlined CALL must be treated as potential throw of anything
                    rectifyStateWithExceptionHandlers();
                }
                break;
            case JBC_invokespecial:
                {
                    MethodReference ref = bcodes.getMethodReference();
                    RVMMethod target = ref.resolveInvokeSpecial();
                    /* just create an osr barrier right before _callHelper
           * changes the states of locals and stacks.
           */
                    if (this.osrGuardedInline) {
                        lastOsrBarrier = _createOsrBarrier();
                    }
                    s = _callHelper(ref, MethodOperand.SPECIAL(ref, target));
                    if (s == null)
                        break;
                    // NOTE: different definition of unresolved due to semantics of invokespecial.
                    if (target == null) {
                        RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                        appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
                        Call.setAddress(s, offsetrop);
                        rectifyStateWithErrorHandler();
                    } else {
                        Call.setAddress(s, new AddressConstantOperand(target.getOffset()));
                    }
                    // null check receiver
                    Operand receiver = Call.getParam(s, 0);
                    clearCurrentGuard();
                    if (do_NullCheck(receiver)) {
                        // call will always raise null pointer exception
                        s = null;
                        break;
                    }
                    Call.setGuard(s, getCurrentGuard());
                    // Consider inlining it.
                    if (maybeInlineMethod(shouldInline(s, false, instrIndex - bciAdjustment), s)) {
                        return;
                    }
                    // noninlined CALL must be treated as potential throw of anything
                    rectifyStateWithExceptionHandlers();
                }
                break;
            case JBC_invokestatic:
                {
                    MethodReference ref = bcodes.getMethodReference();
                    // If it is, generate the inline code and we are done.
                    if (ref.isMagic()) {
                        boolean generated = GenerateMagic.generateMagic(this, gc, ref);
                        if (generated)
                            break;
                    }
                    // A non-magical invokestatic.  Create call instruction.
                    boolean unresolved = ref.needsDynamicLink(bcodes.getMethod());
                    RVMMethod target = ref.peekResolvedMethod();
                    /* just create an osr barrier right before _callHelper
          * changes the states of locals and stacks.
          */
                    if (this.osrGuardedInline) {
                        lastOsrBarrier = _createOsrBarrier();
                    }
                    s = _callHelper(ref, MethodOperand.STATIC(ref, target));
                    if (s == null)
                        break;
                    if (Call.conforms(s)) {
                        MethodOperand methOp = Call.getMethod(s);
                        if (methOp.getTarget() == target) {
                            // Handle possibility of dynamic linking.
                            if (unresolved) {
                                RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                                appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
                                Call.setAddress(s, offsetrop);
                                rectifyStateWithErrorHandler();
                            } else {
                                Call.setAddress(s, new AddressConstantOperand(target.getOffset()));
                            }
                            // Consider inlining it.
                            if (maybeInlineMethod(shouldInline(s, false, instrIndex - bciAdjustment), s)) {
                                return;
                            }
                        }
                    }
                    // noninlined CALL must be treated as potential throw of anything
                    rectifyStateWithExceptionHandlers();
                }
                break;
            case JBC_invokeinterface:
                {
                    MethodReference ref = bcodes.getMethodReference();
                    bcodes.alignInvokeInterface();
                    RVMMethod resolvedMethod = null;
                    resolvedMethod = ref.peekInterfaceMethod();
                    /* just create an osr barrier right before _callHelper
           * changes the states of locals and stacks.
           */
                    if (this.osrGuardedInline) {
                        lastOsrBarrier = _createOsrBarrier();
                    }
                    s = _callHelper(ref, MethodOperand.INTERFACE(ref, resolvedMethod));
                    if (s == null)
                        break;
                    Operand receiver = Call.getParam(s, 0);
                    RVMClass receiverType = (RVMClass) receiver.getType().peekType();
                    boolean requiresImplementsTest = VM.BuildForIMTInterfaceInvocation;
                    // that it is not needed.
                    if (requiresImplementsTest && resolvedMethod == null) {
                        // Sigh.  Can't even resolve the reference to figure out what interface
                        // method we are trying to call. Therefore we must make generate a call
                        // to an out-of-line typechecking routine to handle it at runtime.
                        RVMMethod target = Entrypoints.unresolvedInvokeinterfaceImplementsTestMethod;
                        Instruction callCheck = Call.create2(CALL, null, new AddressConstantOperand(target.getOffset()), MethodOperand.STATIC(target), new IntConstantOperand(ref.getId()), receiver.copy());
                        if (gc.getOptions().H2L_NO_CALLEE_EXCEPTIONS) {
                            callCheck.markAsNonPEI();
                        }
                        appendInstruction(callCheck);
                        callCheck.setBytecodeIndex(RUNTIME_SERVICES_BCI);
                        // the above call subsumes the test
                        requiresImplementsTest = false;
                        // Can raise incompatible class change error.
                        rectifyStateWithErrorHandler();
                    }
                    // null check on this parameter of call. Must be done after dynamic linking!
                    clearCurrentGuard();
                    if (do_NullCheck(receiver)) {
                        // call will always raise null pointer exception
                        s = null;
                        break;
                    }
                    Call.setGuard(s, getCurrentGuard());
                    if (requiresImplementsTest) {
                        // We know what interface method the program wants to invoke.
                        // Attempt to avoid inserting the type check by seeing if the
                        // known static type of the receiver implements the desired interface.
                        RVMType interfaceType = resolvedMethod.getDeclaringClass();
                        if (receiverType != null && receiverType.isResolved() && !receiverType.isInterface()) {
                            byte doesImplement = ClassLoaderProxy.includesType(interfaceType.getTypeRef(), receiverType.getTypeRef());
                            requiresImplementsTest = doesImplement != YES;
                        }
                    }
                    // Attempt to resolve the interface call to a particular virtual method.
                    // This is independent of whether or not the static type of the receiver is
                    // known to implement the interface and it is not that case that being able
                    // to prove one implies the other.
                    RVMMethod vmeth = null;
                    if (receiverType != null && receiverType.isInitialized() && !receiverType.isInterface()) {
                        vmeth = ClassLoaderProxy.lookupMethod(receiverType, ref);
                    }
                    if (vmeth != null) {
                        MethodReference vmethRef = vmeth.getMemberRef().asMethodReference();
                        // Note that at this point requiresImplementsTest => resolvedMethod != null
                        if (requiresImplementsTest) {
                            RegisterOperand checkedReceiver = gc.getTemps().makeTemp(receiver);
                            appendInstruction(TypeCheck.create(MUST_IMPLEMENT_INTERFACE, checkedReceiver, receiver.copy(), makeTypeOperand(resolvedMethod.getDeclaringClass()), getCurrentGuard()));
                            checkedReceiver.refine(resolvedMethod.getDeclaringClass().getTypeRef());
                            Call.setParam(s, 0, checkedReceiver.copyRO());
                            receiver = checkedReceiver;
                            // Can raise incompatible class change error.
                            rectifyStateWithErrorHandler();
                        }
                        MethodOperand mop = MethodOperand.VIRTUAL(vmethRef, vmeth);
                        if (receiver.isConstant() || receiver.asRegister().isPreciseType()) {
                            mop.refine(vmeth, true);
                        }
                        Call.setMethod(s, mop);
                        boolean unresolved = vmethRef.needsDynamicLink(bcodes.getMethod());
                        if (unresolved) {
                            RegisterOperand offsetrop = gc.getTemps().makeTempOffset();
                            appendInstruction(Unary.create(RESOLVE_MEMBER, offsetrop.copyRO(), Call.getMethod(s).copy()));
                            Call.setAddress(s, offsetrop);
                            rectifyStateWithErrorHandler();
                        } else {
                            Call.setAddress(s, new AddressConstantOperand(vmeth.getOffset()));
                        }
                        // Attempt to inline virtualized call.
                        if (maybeInlineMethod(shouldInline(s, receiver.isConstant() || receiver.asRegister().isExtant(), instrIndex - bciAdjustment), s)) {
                            return;
                        }
                    } else {
                        // inline code will include DTC to ensure receiver implements the interface.
                        if (resolvedMethod != null && maybeInlineMethod(shouldInline(s, false, instrIndex - bciAdjustment), s)) {
                            return;
                        } else {
                            if (requiresImplementsTest) {
                                RegisterOperand checkedReceiver = gc.getTemps().makeTemp(receiver);
                                appendInstruction(TypeCheck.create(MUST_IMPLEMENT_INTERFACE, checkedReceiver, receiver.copy(), makeTypeOperand(resolvedMethod.getDeclaringClass()), getCurrentGuard()));
                                checkedReceiver.refine(resolvedMethod.getDeclaringClass().getTypeRef());
                                Call.setParam(s, 0, checkedReceiver.copyRO());
                            // don't have to rectify with error handlers; rectify call below subsumes.
                            }
                        }
                    }
                    // CALL must be treated as potential throw of anything
                    rectifyStateWithExceptionHandlers();
                }
                break;
            case JBC_invokedynamic:
                OptimizingCompilerException.UNREACHABLE();
                break;
            case JBC_new:
                {
                    TypeReference klass = bcodes.getTypeReference();
                    RegisterOperand t = gc.getTemps().makeTemp(klass);
                    t.setPreciseType();
                    markGuardlessNonNull(t);
                    Operator operator;
                    TypeOperand klassOp;
                    RVMClass klassType = (RVMClass) klass.peekType();
                    if (klassType != null && (klassType.isInitialized() || klassType.isInBootImage())) {
                        klassOp = makeTypeOperand(klassType);
                        operator = NEW;
                        t.setExtant();
                    } else {
                        operator = NEW_UNRESOLVED;
                        klassOp = makeTypeOperand(klass);
                    }
                    s = New.create(operator, t, klassOp);
                    push(t.copyD2U());
                    rectifyStateWithErrorHandler();
                }
                break;
            case JBC_newarray:
                {
                    RVMType array = bcodes.getPrimitiveArrayType();
                    TypeOperand arrayOp = makeTypeOperand(array);
                    RegisterOperand t = gc.getTemps().makeTemp(array.getTypeRef());
                    t.setPreciseType();
                    t.setExtant();
                    markGuardlessNonNull(t);
                    s = NewArray.create(NEWARRAY, t, arrayOp, popInt());
                    push(t.copyD2U());
                    rectifyStateWithExceptionHandler(TypeReference.JavaLangNegativeArraySizeException);
                }
                break;
            case JBC_anewarray:
                {
                    TypeReference elementTypeRef = bcodes.getTypeReference();
                    s = generateAnewarray(null, elementTypeRef);
                }
                break;
            case JBC_arraylength:
                {
                    Operand op1 = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(op1)) {
                        break;
                    }
                    if (VM.VerifyAssertions) {
                        opt_assert(getArrayTypeOf(op1).isArrayType());
                    }
                    RegisterOperand t = gc.getTemps().makeTempInt();
                    s = GuardedUnary.create(ARRAYLENGTH, t, op1, getCurrentGuard());
                    push(t.copyD2U());
                }
                break;
            case JBC_athrow:
                {
                    Operand op0 = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(op0)) {
                        break;
                    }
                    TypeReference type = getRefTypeOf(op0);
                    if (VM.VerifyAssertions)
                        assertIsAssignable(TypeReference.JavaLangThrowable, type);
                    if (!gc.getMethod().isInterruptible()) {
                        // prevent code motion in or out of uninterruptible code sequence
                        appendInstruction(Empty.create(UNINT_END));
                    }
                    endOfBasicBlock = true;
                    BasicBlock definiteTarget = rectifyStateWithExceptionHandler(type, true);
                    if (definiteTarget != null) {
                        appendInstruction(CacheOp.create(SET_CAUGHT_EXCEPTION, op0));
                        s = Goto.create(GOTO, definiteTarget.makeJumpTarget());
                        definiteTarget.setExceptionHandlerWithNormalIn();
                    } else {
                        s = Athrow.create(ATHROW, op0);
                    }
                }
                break;
            case JBC_checkcast:
                {
                    TypeReference typeRef = bcodes.getTypeReference();
                    boolean classLoading = couldCauseClassLoading(typeRef);
                    Operand op2 = pop();
                    if (typeRef.isWordLikeType()) {
                        op2 = op2.copy();
                        if (op2 instanceof RegisterOperand) {
                            ((RegisterOperand) op2).setType(typeRef);
                        }
                        push(op2);
                        if (DBG_CF)
                            db("skipped gen of checkcast to word type " + typeRef);
                        break;
                    }
                    if (VM.VerifyAssertions)
                        opt_assert(op2.isRef());
                    if (CF_CHECKCAST && !classLoading) {
                        if (op2.isDefinitelyNull()) {
                            push(op2);
                            if (DBG_CF)
                                db("skipped gen of null checkcast");
                            break;
                        }
                        // non-null, null case above
                        TypeReference type = getRefTypeOf(op2);
                        byte typeTestResult = ClassLoaderProxy.includesType(typeRef, type);
                        if (typeTestResult == YES) {
                            push(op2);
                            if (DBG_CF) {
                                db("skipped gen of checkcast of " + op2 + " from " + typeRef + " to " + type);
                            }
                            break;
                        }
                        if (typeTestResult == NO) {
                            if (isNonNull(op2)) {
                                // Definite class cast exception
                                endOfBasicBlock = true;
                                appendInstruction(Trap.create(TRAP, gc.getTemps().makeTempValidation(), TrapCodeOperand.CheckCast()));
                                rectifyStateWithExceptionHandler(TypeReference.JavaLangClassCastException);
                                if (DBG_CF)
                                    db("Converted checkcast into unconditional trap");
                                break;
                            } else {
                                // At runtime either it is null and the checkcast succeeds or it is non-null
                                // and a class cast exception is raised
                                RegisterOperand refinedOp2 = gc.getTemps().makeTemp(op2);
                                s = TypeCheck.create(CHECKCAST, refinedOp2, op2.copy(), makeTypeOperand(typeRef.peekType()));
                                refinedOp2.refine(TypeReference.NULL_TYPE);
                                push(refinedOp2.copyRO());
                                rectifyStateWithExceptionHandler(TypeReference.JavaLangClassCastException);
                                if (DBG_CF)
                                    db("Narrowed type downstream of checkcast to NULL");
                                break;
                            }
                        }
                    }
                    RegisterOperand refinedOp2 = gc.getTemps().makeTemp(op2);
                    if (classLoading) {
                        s = TypeCheck.create(CHECKCAST_UNRESOLVED, refinedOp2, op2.copy(), makeTypeOperand(typeRef));
                    } else {
                        TypeOperand typeOp = makeTypeOperand(typeRef.peekType());
                        if (isNonNull(op2)) {
                            s = TypeCheck.create(CHECKCAST_NOTNULL, refinedOp2, op2.copy(), typeOp, copyGuardFromOperand(op2));
                        } else {
                            s = TypeCheck.create(CHECKCAST, refinedOp2, op2.copy(), typeOp);
                        }
                    }
                    refinedOp2.refine(typeRef);
                    push(refinedOp2.copyRO());
                    rectifyStateWithExceptionHandler(TypeReference.JavaLangClassCastException);
                    if (classLoading)
                        rectifyStateWithErrorHandler();
                }
                break;
            case JBC_instanceof:
                {
                    TypeReference typeRef = bcodes.getTypeReference();
                    boolean classLoading = couldCauseClassLoading(typeRef);
                    Operand op2 = pop();
                    if (VM.VerifyAssertions)
                        opt_assert(op2.isRef());
                    if (CF_INSTANCEOF && !classLoading) {
                        if (op2.isDefinitelyNull()) {
                            push(new IntConstantOperand(0));
                            if (DBG_CF)
                                db("skipped gen of null instanceof");
                            break;
                        }
                        // non-null
                        TypeReference type = getRefTypeOf(op2);
                        int answer = ClassLoaderProxy.includesType(typeRef, type);
                        if (answer == YES && isNonNull(op2)) {
                            push(new IntConstantOperand(1));
                            if (DBG_CF) {
                                db(op2 + " instanceof " + typeRef + " is always true ");
                            }
                            break;
                        } else if (answer == NO) {
                            if (DBG_CF) {
                                db(op2 + " instanceof " + typeRef + " is always false ");
                            }
                            push(new IntConstantOperand(0));
                            break;
                        }
                    }
                    RegisterOperand t = gc.getTemps().makeTempInt();
                    if (classLoading) {
                        s = InstanceOf.create(INSTANCEOF_UNRESOLVED, t, makeTypeOperand(typeRef), op2);
                    } else {
                        TypeOperand typeOp = makeTypeOperand(typeRef.peekType());
                        if (isNonNull(op2)) {
                            s = InstanceOf.create(INSTANCEOF_NOTNULL, t, typeOp, op2, copyGuardFromOperand(op2));
                        } else {
                            s = InstanceOf.create(INSTANCEOF, t, typeOp, op2);
                        }
                    }
                    push(t.copyD2U());
                    if (classLoading)
                        rectifyStateWithErrorHandler();
                }
                break;
            case JBC_monitorenter:
                {
                    Operand op0 = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(op0)) {
                        break;
                    }
                    if (VM.VerifyAssertions)
                        opt_assert(op0.isRef());
                    s = MonitorOp.create(MONITORENTER, op0, getCurrentGuard());
                }
                break;
            case JBC_monitorexit:
                {
                    Operand op0 = pop();
                    clearCurrentGuard();
                    if (do_NullCheck(op0)) {
                        break;
                    }
                    s = MonitorOp.create(MONITOREXIT, op0, getCurrentGuard());
                    rectifyStateWithExceptionHandler(TypeReference.JavaLangIllegalMonitorStateException);
                }
                break;
            case JBC_wide:
                {
                    int widecode = bcodes.getWideOpcode();
                    int index = bcodes.getWideLocalNumber();
                    switch(widecode) {
                        case JBC_iload:
                            s = do_iload(index);
                            break;
                        case JBC_lload:
                            s = do_lload(index);
                            break;
                        case JBC_fload:
                            s = do_fload(index);
                            break;
                        case JBC_dload:
                            s = do_dload(index);
                            break;
                        case JBC_aload:
                            s = do_aload(index);
                            break;
                        case JBC_istore:
                            s = do_store(index, popInt());
                            break;
                        case JBC_lstore:
                            s = do_store(index, popLong());
                            break;
                        case JBC_fstore:
                            s = do_store(index, popFloat());
                            break;
                        case JBC_dstore:
                            s = do_store(index, popDouble());
                            break;
                        case JBC_astore:
                            s = do_astore(index);
                            break;
                        case JBC_iinc:
                            s = do_iinc(index, bcodes.getWideIncrement());
                            break;
                        case JBC_ret:
                            s = _retHelper(index);
                            break;
                        default:
                            OptimizingCompilerException.UNREACHABLE();
                            break;
                    }
                }
                break;
            case JBC_multianewarray:
                {
                    TypeReference arrayType = bcodes.getTypeReference();
                    int dimensions = bcodes.getArrayDimension();
                    if (dimensions == 1) {
                        s = generateAnewarray(arrayType, null);
                    } else {
                        TypeOperand typeOp = makeTypeOperand(arrayType);
                        RegisterOperand result = gc.getTemps().makeTemp(arrayType);
                        markGuardlessNonNull(result);
                        result.setPreciseType();
                        TypeReference innermostElementTypeRef = arrayType.getInnermostElementType();
                        RVMType innermostElementType = innermostElementTypeRef.peekType();
                        if (innermostElementType != null && (innermostElementType.isInitialized() || innermostElementType.isInBootImage())) {
                            result.setExtant();
                        }
                        s = Multianewarray.create(NEWOBJMULTIARRAY, result, typeOp, dimensions);
                        for (int i = 0; i < dimensions; i++) {
                            Multianewarray.setDimension(s, dimensions - i - 1, popInt());
                        }
                        push(result.copyD2U());
                        rectifyStateWithErrorHandler();
                        rectifyStateWithExceptionHandler(TypeReference.JavaLangNegativeArraySizeException);
                    }
                }
                break;
            case JBC_ifnull:
                s = _refIfNullHelper(ConditionOperand.EQUAL());
                break;
            case JBC_ifnonnull:
                s = _refIfNullHelper(ConditionOperand.NOT_EQUAL());
                break;
            case JBC_goto_w:
                {
                    int offset = bcodes.getWideBranchOffset();
                    if (offset != 5) {
                        // skip generating frivolous goto's
                        s = _gotoHelper(offset);
                    }
                }
                break;
            case JBC_jsr_w:
                s = _jsrHelper(bcodes.getWideBranchOffset());
                break;
            case JBC_impdep1:
                {
                    if (VM.BuildForAdaptiveSystem) {
                        int pseudo_opcode = bcodes.nextPseudoInstruction();
                        switch(pseudo_opcode) {
                            case PSEUDO_LoadIntConst:
                                {
                                    int value = bcodes.readIntConst();
                                    if (VM.TraceOnStackReplacement) {
                                        VM.sysWriteln("PSEUDO_LoadIntConst " + value);
                                    }
                                    push(new IntConstantOperand(value));
                                    // used for PSEUDO_InvokeStatic to recover the type info
                                    param1 = param2;
                                    param2 = value;
                                    break;
                                }
                            case PSEUDO_LoadLongConst:
                                {
                                    long value = bcodes.readLongConst();
                                    if (VM.TraceOnStackReplacement) {
                                        VM.sysWriteln("PSEUDO_LoadLongConst " + value);
                                    }
                                    pushDual(new LongConstantOperand(value));
                                    break;
                                }
                            case PSEUDO_LoadWordConst:
                                {
                                    Address a = (VM.BuildFor32Addr) ? Address.fromIntSignExtend(bcodes.readIntConst()) : Address.fromLong(bcodes.readLongConst());
                                    push(new AddressConstantOperand(a));
                                    if (VM.TraceOnStackReplacement) {
                                        VM.sysWrite("PSEUDO_LoadWordConst 0x");
                                    }
                                    VM.sysWrite(a);
                                    VM.sysWriteln();
                                    break;
                                }
                            case PSEUDO_LoadFloatConst:
                                {
                                    int ibits = bcodes.readIntConst();
                                    float value = Float.intBitsToFloat(ibits);
                                    if (VM.TraceOnStackReplacement) {
                                        VM.sysWriteln("PSEUDO_LoadFloatConst " + value);
                                    }
                                    push(new FloatConstantOperand(value, Offset.zero()));
                                    break;
                                }
                            case PSEUDO_LoadDoubleConst:
                                {
                                    long lbits = bcodes.readLongConst();
                                    double value = Magic.longBitsAsDouble(lbits);
                                    if (VM.TraceOnStackReplacement) {
                                        VM.sysWriteln("PSEUDO_LoadDoubleConst " + lbits);
                                    }
                                    pushDual(new DoubleConstantOperand(value, Offset.zero()));
                                    break;
                                }
                            case PSEUDO_LoadRetAddrConst:
                                {
                                    int value = bcodes.readIntConst();
                                    if (VM.TraceOnStackReplacement) {
                                        VM.sysWriteln("PSEUDO_LoadRetAddrConst " + value);
                                    }
                                    push(new ReturnAddressOperand(value));
                                    break;
                                }
                            case PSEUDO_InvokeStatic:
                                {
                                    /* pseudo invoke static for getRefAt and cleanRefAt, both must be resolved already */
                                    int targetidx = bcodes.readIntConst();
                                    RVMMethod meth = InvokeStatic.targetMethod(targetidx);
                                    if (VM.TraceOnStackReplacement) {
                                        VM.sysWriteln("PSEUDO_Invoke " + meth);
                                        VM.sysWriteln();
                                    }
                                    s = _callHelper(meth.getMemberRef().asMethodReference(), MethodOperand.STATIC(meth));
                                    if (s == null)
                                        break;
                                    Call.setAddress(s, new AddressConstantOperand(meth.getOffset()));
                                    /* try to set the type of return register */
                                    if (targetidx == GETREFAT) {
                                        Object realObj = ObjectHolder.getRefAt(param1, param2);
                                        if (VM.VerifyAssertions)
                                            opt_assert(realObj != null);
                                        TypeReference klass = Magic.getObjectType(realObj).getTypeRef();
                                        RegisterOperand op0 = gc.getTemps().makeTemp(klass);
                                        Call.setResult(s, op0);
                                        // pop the old one and push the new return type.
                                        pop();
                                        push(op0.copyD2U(), klass);
                                    }
                                    // CALL must be treated as potential throw of anything
                                    rectifyStateWithExceptionHandlers();
                                    break;
                                }
                            case PSEUDO_InvokeCompiledMethod:
                                {
                                    int cmid = bcodes.readIntConst();
                                    // skip it
                                    int origBCIdx = bcodes.readIntConst();
                                    CompiledMethod cm = CompiledMethods.getCompiledMethod(cmid);
                                    RVMMethod meth = cm.getMethod();
                                    if (VM.TraceOnStackReplacement) {
                                        VM.sysWriteln("PSEUDO_InvokeCompiledMethod " + meth);
                                        VM.sysWriteln();
                                    }
                                    /* the bcIndex should be adjusted to the original */
                                    s = _callHelper(meth.getMemberRef().asMethodReference(), MethodOperand.COMPILED(meth, cm.getOsrJTOCoffset()));
                                    if (s == null)
                                        break;
                                    // adjust the bcindex of s to the original bytecode's index
                                    // it should be able to give the correct exception handling
                                    s.adjustBytecodeIndex(bciAdjustment);
                                    rectifyStateWithExceptionHandlers();
                                    break;
                                }
                            case PSEUDO_ParamInitEnd:
                                {
                                    break;
                                }
                            default:
                                if (VM.TraceOnStackReplacement) {
                                    VM.sysWriteln("OSR Error, no such pseudo opcode : " + pseudo_opcode);
                                }
                                OptimizingCompilerException.UNREACHABLE();
                                break;
                        }
                        break;
                    } else {
                        OptimizingCompilerException.UNREACHABLE();
                    }
                }
            default:
                OptimizingCompilerException.UNREACHABLE();
                break;
        }
        if (s != null && !currentBBLE.isSelfRegen()) {
            appendInstruction(s);
        }
        // check runoff
        if (VM.VerifyAssertions)
            opt_assert(bcodes.index() <= runoff);
        if (!endOfBasicBlock && bcodes.index() == runoff) {
            if (DBG_BB || DBG_SELECTED) {
                db("runoff occurred! current basic block: " + currentBBLE + ", runoff = " + runoff);
            }
            endOfBasicBlock = fallThrough = true;
        }
        if (endOfBasicBlock) {
            if (currentBBLE.isSelfRegen()) {
                // This block ended in a goto that jumped into the middle of it.
                // Through away all out edges from this block, they're out of date
                // because we're going to have to regenerate this block.
                currentBBLE.block.deleteOut();
                if (DBG_CFG || DBG_SELECTED) {
                    db("Deleted all out edges of " + currentBBLE.block);
                }
                return;
            }
            if (fallThrough) {
                if (VM.VerifyAssertions)
                    opt_assert(bcodes.index() < bcodes.length());
                // Get/Create fallthrough BBLE and record it as
                // currentBBLE's fallThrough.
                currentBBLE.fallThrough = getOrCreateBlock(bcodes.index());
                currentBBLE.block.insertOut(currentBBLE.fallThrough.block);
            }
            return;
        }
    }
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) Operator(org.jikesrvm.compilers.opt.ir.Operator) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) Address(org.vmmagic.unboxed.Address) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) OsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.OsrTypeInfoOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) RVMType(org.jikesrvm.classloader.RVMType) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) CompiledMethod(org.jikesrvm.compilers.common.CompiledMethod) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) DoubleConstantOperand(org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) FieldReference(org.jikesrvm.classloader.FieldReference) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) SwitchBranchProfile(org.jikesrvm.compilers.baseline.SwitchBranchProfile) OsrPoint(org.jikesrvm.compilers.opt.ir.OsrPoint) RVMClass(org.jikesrvm.classloader.RVMClass) RVMMethod(org.jikesrvm.classloader.RVMMethod) FloatConstantOperand(org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) MethodReference(org.jikesrvm.classloader.MethodReference)

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