Search in sources :

Example 66 with RVMClass

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

the class BytecodeTraverser method scanBlocks.

// //////////////////////////
// IMPLEMENTATION
// /////////////////////////
/* return true --> hit the bytecode pointed by PC */
private // which method
boolean scanBlocks(// which method
NormalMethod method, // the bytecodes
BytecodeStream bytecodes, // do a DFS or one-pass scan
boolean doDFS, // the target pcs, if doDFS
int pcs, // the local types if doDFS
byte[] ltypes, // the stack types if doDFS
byte[] stypes, // start pc
int startpc, // stack
TypeStack S, int[] stackHeights) {
    // the stack height if not doDFS
    int localsize = method.getLocalWords() - 1;
    RVMClass declaringClass = method.getDeclaringClass();
    bytecodes.reset(startpc);
    boolean found = false;
    while (bytecodes.hasMoreBytecodes()) {
        // get current pc
        int pc = bytecodes.index();
        if (visitedpc[pc] == 1) {
            return false;
        } else {
            visitedpc[pc] = 1;
        }
        if (doDFS && (pc == pcs)) {
            /* make a copy of stack frame and put into stypes. */
            byte[] stack = S.snapshot();
            System.arraycopy(stack, 0, stypes, 0, stack.length);
            return true;
        }
        if (!doDFS) {
            // record stack heights
            stackHeights[pc] = localsize + S.depth();
        }
        /* let's continue */
        int bcode = bytecodes.nextInstruction();
        if (TRACE) {
            if (bcode <= JBC_jsr_w) {
                VM.sysWriteln(pc + " : " + S.depth() + " : " + JBC_name(bcode));
            } else {
                VM.sysWriteln(pc + " : " + S.depth() + " : impdep1");
            }
        }
        switch(bcode) {
            case JBC_nop:
                break;
            case JBC_aconst_null:
                S.push(ClassTypeCode);
                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:
                S.push(IntTypeCode);
                break;
            case JBC_lconst_0:
            case JBC_lconst_1:
                /* we should do the save order as opt compiler */
                S.push(VoidTypeCode);
                S.push(LongTypeCode);
                break;
            case JBC_fconst_0:
            case JBC_fconst_1:
            case JBC_fconst_2:
                S.push(FloatTypeCode);
                break;
            case JBC_dconst_0:
            case JBC_dconst_1:
                S.push(VoidTypeCode);
                S.push(DoubleTypeCode);
                break;
            case JBC_bipush:
                bytecodes.getByteValue();
                S.push(IntTypeCode);
                break;
            case JBC_sipush:
                bytecodes.getShortValue();
                S.push(IntTypeCode);
                break;
            case JBC_ldc:
            case JBC_ldc_w:
                {
                    int cpoolidx = (bcode == JBC_ldc) ? bytecodes.getConstantIndex() : bytecodes.getWideConstantIndex();
                    byte tdesc = declaringClass.getLiteralDescription(cpoolidx);
                    switch(tdesc) {
                        case CP_INT:
                            S.push(IntTypeCode);
                            break;
                        case CP_FLOAT:
                            S.push(FloatTypeCode);
                            break;
                        case CP_STRING:
                            S.push(ClassTypeCode);
                            break;
                        case CP_CLASS:
                            S.push(ClassTypeCode);
                            break;
                        default:
                            if (VM.TraceOnStackReplacement)
                                VM.sysWriteln("ldc unknown type " + tdesc);
                            if (VM.VerifyAssertions)
                                VM._assert(VM.NOT_REACHED);
                            break;
                    }
                // end of switch
                }
                break;
            case JBC_ldc2_w:
                {
                    int cpoolidx = bytecodes.getWideConstantIndex();
                    byte tdesc = declaringClass.getLiteralDescription(cpoolidx);
                    S.push(VoidTypeCode);
                    switch(tdesc) {
                        case CP_LONG:
                            S.push(LongTypeCode);
                            break;
                        case CP_DOUBLE:
                            S.push(DoubleTypeCode);
                            break;
                        default:
                            if (VM.TraceOnStackReplacement)
                                VM.sysWriteln("ldc2_w unknown type " + tdesc);
                            if (VM.VerifyAssertions)
                                VM._assert(VM.NOT_REACHED);
                            break;
                    }
                // end of switch
                }
                break;
            case JBC_iload:
                // skip local
                bytecodes.getLocalNumber();
                S.push(IntTypeCode);
                break;
            case JBC_lload:
                // skip local
                bytecodes.getLocalNumber();
                S.push(VoidTypeCode);
                S.push(LongTypeCode);
                break;
            case JBC_fload:
                // skip local
                bytecodes.getLocalNumber();
                S.push(FloatTypeCode);
                break;
            case JBC_dload:
                bytecodes.getLocalNumber();
                S.push(VoidTypeCode);
                S.push(DoubleTypeCode);
                break;
            case JBC_aload:
                bytecodes.getLocalNumber();
                S.push(ClassTypeCode);
                break;
            case JBC_iload_0:
            case JBC_iload_1:
            case JBC_iload_2:
            case JBC_iload_3:
                S.push(IntTypeCode);
                break;
            case JBC_lload_0:
            case JBC_lload_1:
            case JBC_lload_2:
            case JBC_lload_3:
                S.push(VoidTypeCode);
                S.push(LongTypeCode);
                break;
            case JBC_fload_0:
            case JBC_fload_1:
            case JBC_fload_2:
            case JBC_fload_3:
                S.push(FloatTypeCode);
                break;
            case JBC_dload_0:
            case JBC_dload_1:
            case JBC_dload_2:
            case JBC_dload_3:
                S.push(VoidTypeCode);
                S.push(DoubleTypeCode);
                break;
            case JBC_aload_0:
            case JBC_aload_1:
            case JBC_aload_2:
            case JBC_aload_3:
                S.push(ClassTypeCode);
                break;
            case JBC_iaload:
            case JBC_baload:
            case JBC_caload:
            case JBC_saload:
                S.pop();
                S.pop();
                S.push(IntTypeCode);
                break;
            case JBC_laload:
                S.pop();
                S.pop();
                S.push(VoidTypeCode);
                S.push(LongTypeCode);
                break;
            case JBC_faload:
                S.pop();
                S.pop();
                S.push(FloatTypeCode);
                break;
            case JBC_daload:
                S.pop();
                S.pop();
                S.push(VoidTypeCode);
                S.push(DoubleTypeCode);
                break;
            case JBC_aaload:
                S.pop();
                S.pop();
                S.push(ClassTypeCode);
                break;
            case JBC_istore:
                {
                    S.pop();
                    int index = bytecodes.getLocalNumber();
                    if (doDFS)
                        ltypes[index] = IntTypeCode;
                }
                break;
            case JBC_istore_0:
            case JBC_istore_1:
            case JBC_istore_2:
            case JBC_istore_3:
                {
                    S.pop();
                    int index = bcode - JBC_istore_0;
                    if (doDFS)
                        ltypes[index] = IntTypeCode;
                }
                break;
            case JBC_lstore:
                {
                    S.pop();
                    S.pop();
                    int index = bytecodes.getLocalNumber();
                    if (doDFS) {
                        ltypes[index] = LongTypeCode;
                        ltypes[index + 1] = VoidTypeCode;
                    }
                }
                break;
            case JBC_lstore_0:
            case JBC_lstore_1:
            case JBC_lstore_2:
            case JBC_lstore_3:
                {
                    S.pop();
                    S.pop();
                    int index = bcode - JBC_lstore_0;
                    if (doDFS) {
                        ltypes[index] = LongTypeCode;
                        ltypes[index + 1] = VoidTypeCode;
                    }
                }
                break;
            case JBC_fstore:
                {
                    S.pop();
                    int index = bytecodes.getLocalNumber();
                    if (doDFS)
                        ltypes[index] = FloatTypeCode;
                }
                break;
            case JBC_fstore_0:
            case JBC_fstore_1:
            case JBC_fstore_2:
            case JBC_fstore_3:
                {
                    S.pop();
                    int index = bcode - JBC_fstore_0;
                    if (doDFS)
                        ltypes[index] = FloatTypeCode;
                }
                break;
            case JBC_dstore:
                {
                    S.pop();
                    S.pop();
                    int index = bytecodes.getLocalNumber();
                    if (doDFS) {
                        ltypes[index] = DoubleTypeCode;
                        ltypes[index + 1] = VoidTypeCode;
                    }
                }
                break;
            case JBC_dstore_0:
            case JBC_dstore_1:
            case JBC_dstore_2:
            case JBC_dstore_3:
                {
                    S.pop();
                    S.pop();
                    int index = bcode - JBC_dstore_0;
                    if (doDFS) {
                        ltypes[index] = DoubleTypeCode;
                        ltypes[index + 1] = VoidTypeCode;
                    }
                }
                break;
            case JBC_astore:
                {
                    // caution: astore may save return address type
                    int index = bytecodes.getLocalNumber();
                    byte tcode = S.pop();
                    if (doDFS)
                        ltypes[index] = tcode;
                    // for ret address.
                    if (tcode == ReturnAddressTypeCode) {
                        retaddr[index] = addr;
                        addr = -1;
                    }
                }
                break;
            case JBC_astore_0:
            case JBC_astore_1:
            case JBC_astore_2:
            case JBC_astore_3:
                {
                    // caution: astore may save return address type
                    int index = bcode - JBC_astore_0;
                    byte tcode = S.pop();
                    if (doDFS)
                        ltypes[index] = tcode;
                    // for ret address.
                    if (tcode == ReturnAddressTypeCode) {
                        retaddr[index] = addr;
                        addr = -1;
                    }
                }
                break;
            case JBC_iastore:
            case JBC_bastore:
            case JBC_castore:
            case JBC_sastore:
                S.pop(3);
                break;
            case JBC_lastore:
                S.pop(4);
                break;
            case JBC_fastore:
                S.pop(3);
                break;
            case JBC_dastore:
                S.pop(4);
                break;
            case JBC_aastore:
                S.pop(3);
                break;
            case JBC_pop:
                S.pop();
                break;
            case JBC_pop2:
                S.pop(2);
                break;
            case JBC_dup:
                {
                    byte v1 = S.peek();
                    S.push(v1);
                }
                break;
            case JBC_dup_x1:
                {
                    byte v1 = S.peek();
                    S.pop();
                    byte v2 = S.peek();
                    S.pop();
                    S.push(v1);
                    S.push(v2);
                    S.push(v1);
                }
                break;
            case JBC_dup_x2:
                {
                    byte v1 = S.peek();
                    S.pop();
                    byte v2 = S.peek();
                    S.pop();
                    byte v3 = S.peek();
                    S.pop();
                    S.push(v1);
                    S.push(v3);
                    S.push(v2);
                    S.push(v1);
                }
                break;
            case JBC_dup2:
                {
                    byte v1 = S.peek();
                    S.pop();
                    byte v2 = S.peek();
                    S.push(v1);
                    S.push(v2);
                    S.push(v1);
                }
                break;
            case JBC_dup2_x1:
                {
                    byte v1 = S.peek();
                    S.pop();
                    byte v2 = S.peek();
                    S.pop();
                    byte v3 = S.peek();
                    S.pop();
                    S.push(v2);
                    S.push(v1);
                    S.push(v3);
                    S.push(v2);
                    S.push(v1);
                }
                break;
            case JBC_dup2_x2:
                {
                    byte v1 = S.peek();
                    S.pop();
                    byte v2 = S.peek();
                    S.pop();
                    byte v3 = S.peek();
                    S.pop();
                    byte v4 = S.peek();
                    S.pop();
                    S.push(v2);
                    S.push(v1);
                    S.push(v4);
                    S.push(v3);
                    S.push(v2);
                    S.push(v1);
                }
                break;
            case JBC_swap:
                {
                    byte v1 = S.peek();
                    S.pop();
                    byte v2 = S.peek();
                    S.pop();
                    S.push(v1);
                    S.push(v2);
                }
                break;
            case JBC_iadd:
            case JBC_isub:
            case JBC_imul:
            case JBC_idiv:
            case JBC_irem:
            case JBC_iand:
            case JBC_ior:
            case JBC_ixor:
            case JBC_ishl:
            case JBC_ishr:
            case JBC_iushr:
                S.pop();
                break;
            case JBC_ladd:
            case JBC_lsub:
            case JBC_lmul:
            case JBC_ldiv:
            case JBC_lrem:
            case JBC_land:
            case JBC_lor:
            case JBC_lxor:
                S.pop(2);
                break;
            case JBC_lshl:
            case JBC_lshr:
            case JBC_lushr:
                S.pop();
                break;
            case JBC_fadd:
            case JBC_fsub:
            case JBC_fmul:
            case JBC_fdiv:
            case JBC_frem:
                S.pop();
                break;
            case JBC_dadd:
            case JBC_dsub:
            case JBC_dmul:
            case JBC_ddiv:
            case JBC_drem:
                S.pop(2);
                break;
            case JBC_ineg:
            case JBC_lneg:
            case JBC_fneg:
            case JBC_dneg:
                break;
            case JBC_iinc:
                {
                    int index = bytecodes.getLocalNumber();
                    /* int value = */
                    bytecodes.getIncrement();
                    if (doDFS)
                        ltypes[index] = IntTypeCode;
                }
                break;
            case JBC_i2l:
                S.pop();
                S.push(VoidTypeCode);
                S.push(LongTypeCode);
                break;
            case JBC_i2f:
                S.pop();
                S.push(FloatTypeCode);
                break;
            case JBC_i2d:
                S.pop();
                S.push(VoidTypeCode);
                S.push(DoubleTypeCode);
                break;
            case JBC_l2i:
                S.pop(2);
                S.push(IntTypeCode);
                break;
            case JBC_l2f:
                S.pop(2);
                S.push(FloatTypeCode);
                break;
            case JBC_l2d:
                S.pop(2);
                S.push(VoidTypeCode);
                S.push(DoubleTypeCode);
                break;
            case JBC_f2i:
                S.pop();
                S.push(IntTypeCode);
                break;
            case JBC_f2l:
                S.pop();
                S.push(VoidTypeCode);
                S.push(LongTypeCode);
                break;
            case JBC_f2d:
                S.pop();
                S.push(VoidTypeCode);
                S.push(DoubleTypeCode);
                break;
            case JBC_d2i:
                S.pop(2);
                S.push(IntTypeCode);
                break;
            case JBC_d2l:
                S.pop(2);
                S.push(VoidTypeCode);
                S.push(LongTypeCode);
                break;
            case JBC_d2f:
                S.pop(2);
                S.push(FloatTypeCode);
                break;
            case JBC_int2byte:
            case JBC_int2char:
            case JBC_int2short:
                break;
            case JBC_lcmp:
                S.pop(4);
                S.push(IntTypeCode);
                break;
            case JBC_fcmpl:
            case JBC_fcmpg:
                S.pop(2);
                S.push(IntTypeCode);
                break;
            case JBC_dcmpl:
            case JBC_dcmpg:
                S.pop(4);
                S.push(IntTypeCode);
                break;
            case JBC_ifeq:
            case JBC_ifne:
            case JBC_iflt:
            case JBC_ifge:
            case JBC_ifgt:
            case JBC_ifle:
            case JBC_ifnull:
            case JBC_ifnonnull:
                {
                    S.pop();
                    // flowthrough first
                    int nextpc = pc + 3;
                    int target = pc + bytecodes.getBranchOffset();
                    if (doDFS) {
                        // make a copy of ltypes, stypes to pass in
                        byte[] newltypes = new byte[ltypes.length];
                        byte[] newstypes = new byte[stypes.length];
                        System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
                        System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
                        found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
                        if (found) {
                            // copy back the ltypes and stypes
                            System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
                            System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
                            return true;
                        }
                    } else {
                        found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
                    }
                    bytecodes.reset(target);
                }
                break;
            case JBC_if_icmpeq:
            case JBC_if_icmpne:
            case JBC_if_icmplt:
            case JBC_if_icmpge:
            case JBC_if_icmpgt:
            case JBC_if_icmple:
            case JBC_if_acmpeq:
            case JBC_if_acmpne:
                {
                    S.pop(2);
                    // flowthrough first
                    int nextpc = pc + 3;
                    int target = pc + bytecodes.getBranchOffset();
                    if (doDFS) {
                        // make a copy of ltypes, stypes to pass in
                        byte[] newltypes = new byte[ltypes.length];
                        byte[] newstypes = new byte[stypes.length];
                        System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
                        System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
                        found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
                        if (found) {
                            // copy back the ltypes and stypes
                            System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
                            System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
                            return true;
                        }
                    } else {
                        found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
                    }
                    bytecodes.reset(target);
                }
                break;
            case JBC_goto:
                {
                    int offset = bytecodes.getBranchOffset();
                    if (!ignoreGotos) {
                        bytecodes.reset(pc + offset);
                    }
                }
                break;
            case JBC_goto_w:
                {
                    int offset = bytecodes.getWideBranchOffset();
                    if (!ignoreGotos) {
                        bytecodes.reset(pc + offset);
                    }
                }
                break;
            case JBC_jsr:
            case JBC_jsr_w:
                {
                    // flow through firs
                    int nextpc = pc + ((bcode == JBC_jsr) ? 3 : 5);
                    int target = pc + ((bcode == JBC_jsr) ? bytecodes.getBranchOffset() : bytecodes.getWideBranchOffset());
                    if (doDFS) {
                        // make a copy of ltypes, stypes to pass in
                        byte[] newltypes = new byte[ltypes.length];
                        byte[] newstypes = new byte[stypes.length];
                        System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
                        System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
                        found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, nextpc, new TypeStack(S), null);
                        if (found) {
                            // copy back the ltypes and stypes
                            System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
                            System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
                            return true;
                        }
                    } else {
                        found = scanBlocks(method, bytecodes, false, -1, null, null, nextpc, new TypeStack(S), stackHeights);
                    }
                    // branch to jsr subroutine
                    // remember return address for ret.
                    addr = pc + ((bcode == JBC_jsr) ? 3 : 5);
                    S.push(ReturnAddressTypeCode);
                    bytecodes.reset(target);
                }
                break;
            case JBC_ret:
                {
                    // the OPT compiler set local to null after _ret instruction,
                    // then we should clean it here also, otherwise it will
                    // throw a null pointer exception.
                    // HOWEVER, it is not part of JVM spec.
                    int index = bytecodes.getLocalNumber();
                    if (doDFS)
                        ltypes[index] = VoidTypeCode;
                    /* the ret address may be saved by a PSEUDO_LoadRetAddrConstant
          */
                    if (retaddr[index] != -1) {
                        bytecodes.reset(retaddr[index]);
                        retaddr[index] = -1;
                    } else {
                        // now we hit ret, return out
                        return false;
                    }
                }
                break;
            case JBC_tableswitch:
                {
                    S.pop();
                    bytecodes.alignSwitch();
                    int defaultval = bytecodes.getDefaultSwitchOffset();
                    int low = bytecodes.getLowSwitchValue();
                    int high = bytecodes.getHighSwitchValue();
                    // write down a list of targets
                    int npairs = high - low + 1;
                    int[] offsets = new int[npairs];
                    for (int i = 0; i < npairs; i++) {
                        offsets[i] = bytecodes.getTableSwitchOffset(i);
                    }
                    for (int i = 0; i < npairs; i++) {
                        int tgtpc = pc + offsets[i];
                        if (doDFS) {
                            // make a copy of ltypes, stypes to pass in
                            byte[] newltypes = new byte[ltypes.length];
                            byte[] newstypes = new byte[stypes.length];
                            System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
                            System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
                            found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
                            if (found) {
                                // copy back the ltypes and stypes
                                System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
                                System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
                                return true;
                            }
                        } else {
                            found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
                        }
                    }
                    // default
                    {
                        int tgtpc = pc + defaultval;
                        if (doDFS) {
                            // make a copy of ltypes, stypes to pass in
                            byte[] newltypes = new byte[ltypes.length];
                            byte[] newstypes = new byte[stypes.length];
                            System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
                            System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
                            found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
                            if (found) {
                                // copy back the ltypes and stypes
                                System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
                                System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
                            }
                        } else {
                            found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
                        }
                        return found;
                    }
                }
            case JBC_lookupswitch:
                {
                    // pop the key
                    S.pop();
                    bytecodes.alignSwitch();
                    int defaultval = bytecodes.getDefaultSwitchOffset();
                    int npairs = bytecodes.getSwitchLength();
                    int[] matches = new int[npairs];
                    int[] offsets = new int[npairs];
                    for (int i = 0; i < npairs; i++) {
                        matches[i] = bytecodes.getLookupSwitchValue(i);
                        offsets[i] = bytecodes.getLookupSwitchOffset(i);
                    }
                    for (int i = 0; i < npairs; i++) {
                        // int match = matches[i];
                        int offset = offsets[i];
                        int tgtpc = pc + offset;
                        if (doDFS) {
                            // make a copy of ltypes, stypes to pass in
                            byte[] newltypes = new byte[ltypes.length];
                            byte[] newstypes = new byte[stypes.length];
                            System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
                            System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
                            found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
                            if (found) {
                                // copy back the ltypes and stypes
                                System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
                                System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
                                return true;
                            }
                        } else {
                            found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
                        }
                    }
                    // default
                    {
                        int tgtpc = pc + defaultval;
                        if (doDFS) {
                            // make a copy of ltypes, stypes to pass in
                            byte[] newltypes = new byte[ltypes.length];
                            byte[] newstypes = new byte[stypes.length];
                            System.arraycopy(ltypes, 0, newltypes, 0, ltypes.length);
                            System.arraycopy(stypes, 0, newstypes, 0, stypes.length);
                            found = scanBlocks(method, bytecodes, true, pcs, newltypes, newstypes, tgtpc, new TypeStack(S), null);
                            if (found) {
                                // copy back the ltypes and stypes
                                System.arraycopy(newltypes, 0, ltypes, 0, ltypes.length);
                                System.arraycopy(newstypes, 0, stypes, 0, stypes.length);
                            }
                        } else {
                            found = scanBlocks(method, bytecodes, false, -1, null, null, tgtpc, new TypeStack(S), stackHeights);
                        }
                    }
                }
                return found;
            case JBC_ireturn:
                S.pop();
                return false;
            case JBC_lreturn:
                S.pop(2);
                return false;
            case JBC_freturn:
                S.pop();
                return false;
            case JBC_dreturn:
                S.pop(2);
                return false;
            case JBC_areturn:
                S.pop();
                return false;
            case JBC_return:
                return false;
            case JBC_getfield:
                S.pop();
            case JBC_getstatic:
                {
                    FieldReference fieldRef = bytecodes.getFieldReference();
                    TypeReference ftype = fieldRef.getFieldContentsType();
                    byte tcode = ftype.getName().parseForTypeCode();
                    if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
                        S.push(VoidTypeCode);
                    }
                    S.push(tcode);
                }
                break;
            case JBC_putstatic:
                {
                    FieldReference fieldRef = bytecodes.getFieldReference();
                    TypeReference ftype = fieldRef.getFieldContentsType();
                    byte tcode = ftype.getName().parseForTypeCode();
                    if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
                        S.pop(2);
                    } else {
                        S.pop();
                    }
                }
                break;
            case JBC_putfield:
                {
                    FieldReference fieldRef = bytecodes.getFieldReference();
                    TypeReference ftype = fieldRef.getFieldContentsType();
                    byte tcode = ftype.getName().parseForTypeCode();
                    if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
                        S.pop(2);
                    } else {
                        S.pop();
                    }
                }
                S.pop();
                break;
            case JBC_invokevirtual:
            case JBC_invokespecial:
            case JBC_invokestatic:
            case JBC_invokeinterface:
                {
                    MethodReference callee = bytecodes.getMethodReference();
                    int psize = callee.getParameterWords();
                    S.pop(psize);
                    if (bcode != JBC_invokestatic) {
                        // pop the object reference
                        S.pop();
                    }
                    TypeReference rtype = callee.getReturnType();
                    byte tcode = rtype.getName().parseForTypeCode();
                    if (tcode == VoidTypeCode) {
                    // nothing to do with void return type
                    } else {
                        if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
                            S.push(VoidTypeCode);
                        }
                        S.push(tcode);
                    }
                    if (bcode == JBC_invokeinterface) {
                        bytecodes.alignInvokeInterface();
                    }
                }
                break;
            case JBC_invokedynamic:
                break;
            case JBC_new:
                // skip cpi of type
                bytecodes.getTypeReference();
                S.push(ClassTypeCode);
                break;
            case JBC_newarray:
                S.pop();
                S.push(ArrayTypeCode);
                // skip cpi of element type
                bytecodes.getArrayElementType();
                break;
            case JBC_anewarray:
                S.pop();
                S.push(ArrayTypeCode);
                // skip cpi of reference type
                bytecodes.getTypeReference();
                break;
            case JBC_arraylength:
                S.pop();
                S.push(IntTypeCode);
                break;
            case JBC_athrow:
                S.clear();
                S.push(ClassTypeCode);
                return false;
            case JBC_checkcast:
                // skip cpi of reference type
                bytecodes.getTypeReference();
                break;
            case JBC_instanceof:
                S.pop();
                S.push(IntTypeCode);
                // skip cpi of reference type
                bytecodes.getTypeReference();
                break;
            case JBC_monitorenter:
            case JBC_monitorexit:
                S.pop();
                break;
            case JBC_wide:
                {
                    int widecode = bytecodes.getWideOpcode();
                    int index = bytecodes.getWideLocalNumber();
                    switch(widecode) {
                        case JBC_iload:
                            S.push(IntTypeCode);
                            break;
                        case JBC_lload:
                            S.push(LongTypeCode);
                            break;
                        case JBC_fload:
                            S.push(FloatTypeCode);
                            break;
                        case JBC_dload:
                            S.push(DoubleTypeCode);
                            break;
                        case JBC_aload:
                            S.push(ClassTypeCode);
                            break;
                        case JBC_istore:
                            S.pop();
                            if (doDFS)
                                ltypes[index] = IntTypeCode;
                            break;
                        case JBC_lstore:
                            S.pop();
                            if (doDFS)
                                ltypes[index] = LongTypeCode;
                            break;
                        case JBC_fstore:
                            S.pop();
                            if (doDFS)
                                ltypes[index] = FloatTypeCode;
                            break;
                        case JBC_dstore:
                            S.pop();
                            if (doDFS)
                                ltypes[index] = DoubleTypeCode;
                            break;
                        case JBC_astore:
                            {
                                byte tcode = S.pop();
                                if (doDFS)
                                    ltypes[index] = tcode;
                                // for ret address.
                                if (tcode == ReturnAddressTypeCode) {
                                    retaddr[index] = addr;
                                    addr = -1;
                                }
                            }
                            break;
                        case JBC_iinc:
                            {
                                // skip increment
                                bytecodes.getWideIncrement();
                                if (doDFS)
                                    ltypes[index] = IntTypeCode;
                            }
                            break;
                        case JBC_ret:
                            if (doDFS)
                                ltypes[index] = VoidTypeCode;
                            if (retaddr[index] != -1) {
                                bytecodes.reset(retaddr[index]);
                                retaddr[index] = -1;
                            } else {
                                // now we hit ret, return out
                                return false;
                            }
                            break;
                        default:
                            if (VM.VerifyAssertions)
                                VM._assert(VM.NOT_REACHED);
                            break;
                    }
                    break;
                }
            case JBC_multianewarray:
                {
                    // skip type reference
                    bytecodes.getTypeReference();
                    int dims = bytecodes.getArrayDimension();
                    S.pop(dims);
                    S.push(ArrayTypeCode);
                }
                break;
            case JBC_impdep1:
                {
                    int pseudo_opcode = bytecodes.nextPseudoInstruction();
                    switch(pseudo_opcode) {
                        case PSEUDO_LoadIntConst:
                            // skip value
                            bytecodes.readIntConst();
                            S.push(IntTypeCode);
                            break;
                        case PSEUDO_LoadLongConst:
                            // skip value
                            bytecodes.readLongConst();
                            S.push(VoidTypeCode);
                            S.push(LongTypeCode);
                            break;
                        case PSEUDO_LoadWordConst:
                            if (VM.BuildFor32Addr) {
                                bytecodes.readIntConst();
                            } else {
                                // skip value
                                bytecodes.readLongConst();
                            }
                            S.push(WordTypeCode);
                            break;
                        case PSEUDO_LoadFloatConst:
                            // skip value
                            bytecodes.readIntConst();
                            S.push(FloatTypeCode);
                            break;
                        case PSEUDO_LoadDoubleConst:
                            // skip value
                            bytecodes.readLongConst();
                            S.push(VoidTypeCode);
                            S.push(DoubleTypeCode);
                            break;
                        case PSEUDO_LoadRetAddrConst:
                            // remember the address for ret.
                            // get address
                            addr = bytecodes.readIntConst();
                            S.push(ReturnAddressTypeCode);
                            break;
                        case PSEUDO_InvokeStatic:
                            {
                                // get METHIDX
                                int mid = bytecodes.readIntConst();
                                RVMMethod callee = InvokeStatic.targetMethod(mid);
                                int psize = callee.getParameterWords();
                                S.pop(psize);
                                TypeReference rtype = callee.getReturnType();
                                byte tcode = rtype.getName().parseForTypeCode();
                                if (tcode == VoidTypeCode) {
                                // nothing to do with void return type
                                } else {
                                    if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
                                        S.push(VoidTypeCode);
                                    }
                                    S.push(tcode);
                                }
                                break;
                            }
                        /*
        case PSEUDO_CheckCast:
          bytecodes.readIntConst(); // skip type id
          break;
*/
                        case PSEUDO_InvokeCompiledMethod:
                            // cmid
                            int cmid = bytecodes.readIntConst();
                            // skip bcindex
                            bytecodes.readIntConst();
                            RVMMethod callee = CompiledMethods.getCompiledMethod(cmid).getMethod();
                            int psize = callee.getParameterWords();
                            S.pop(psize);
                            if (!callee.isStatic()) {
                                // pop receiver
                                S.pop();
                            }
                            TypeReference rtype = callee.getReturnType();
                            byte tcode = rtype.getName().parseForTypeCode();
                            if (tcode == VoidTypeCode) {
                            // nothing to do with void return type
                            } else {
                                if ((tcode == LongTypeCode) || (tcode == DoubleTypeCode)) {
                                    S.push(VoidTypeCode);
                                }
                                S.push(tcode);
                            }
                            break;
                        case PSEUDO_ParamInitEnd:
                            break;
                        default:
                            if (VM.VerifyAssertions) {
                                VM.sysWriteln(" Error, no such pseudo code : " + pseudo_opcode);
                                VM._assert(VM.NOT_REACHED);
                            }
                            return false;
                    }
                    break;
                }
            default:
                VM.sysWriteln("Unknown bytecode : " + bcode);
                return false;
        }
    }
    /* did not found the PC. */
    return false;
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) FieldReference(org.jikesrvm.classloader.FieldReference) MethodReference(org.jikesrvm.classloader.MethodReference) TypeReference(org.jikesrvm.classloader.TypeReference) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 67 with RVMClass

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

the class MemoryManager method pickAllocator.

/**
 * Returns the appropriate allocation scheme/area for the given type
 * and given method requesting the allocation.
 *
 * @param type the type of the object to be allocated
 * @param method the method requesting the allocation
 * @return the identifier of the appropriate allocator
 */
@Interruptible
public static int pickAllocator(RVMType type, RVMMethod method) {
    if (traceAllocator) {
        VM.sysWrite("allocator for ");
        VM.sysWrite(type.getDescriptor());
        VM.sysWrite(": ");
    }
    if (method != null) {
        // We should strive to be allocation-free here.
        RVMClass cls = method.getDeclaringClass();
        byte[] clsBA = cls.getDescriptor().toByteArray();
        if (Selected.Constraints.get().withGCspy()) {
            if (isPrefix("Lorg/mmtk/vm/gcspy/", clsBA) || isPrefix("[Lorg/mmtk/vm/gcspy/", clsBA)) {
                if (traceAllocator) {
                    VM.sysWriteln("GCSPY");
                }
                return Plan.ALLOC_GCSPY;
            }
        }
        if (isPrefix("Lorg/jikesrvm/mm/mmtk/ReferenceProcessor", clsBA)) {
            if (traceAllocator) {
                VM.sysWriteln("DEFAULT");
            }
            return Plan.ALLOC_DEFAULT;
        }
        if (isPrefix("Lorg/mmtk/", clsBA) || isPrefix("Lorg/jikesrvm/mm/", clsBA)) {
            if (traceAllocator) {
                VM.sysWriteln("NONMOVING");
            }
            return Plan.ALLOC_NON_MOVING;
        }
        if (method.isNonMovingAllocation()) {
            return Plan.ALLOC_NON_MOVING;
        }
    }
    if (traceAllocator) {
        VM.sysWriteln(type.getMMAllocator());
    }
    return type.getMMAllocator();
}
Also used : RVMClass(org.jikesrvm.classloader.RVMClass) Interruptible(org.vmmagic.pragma.Interruptible)

Example 68 with RVMClass

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

the class JNIFunctions method AllocObject.

/**
 * AllocObject:  allocate the space for an object without running any constructor
 *               the header is filled and the fields are initialized to null
 * @param env A JREF index for the JNI environment object
 * @param classJREF a JREF index for the class object
 * @return a JREF index for the uninitialized object
 * @throws InstantiationException if the class is abstract or is an interface
 * @throws OutOfMemoryError if no more memory to allocate
 */
private static int AllocObject(JNIEnvironment env, int classJREF) throws InstantiationException, OutOfMemoryError {
    if (traceJNI)
        VM.sysWriteln("JNI called: AllocObject");
    RuntimeEntrypoints.checkJNICountDownToGC();
    try {
        Class<?> javaCls = (Class<?>) env.getJNIRef(classJREF);
        RVMType type = java.lang.JikesRVMSupport.getTypeForClass(javaCls);
        if (type.isArrayType() || type.isPrimitiveType() || type.isUnboxedType()) {
            env.recordException(new InstantiationException());
            return 0;
        }
        RVMClass cls = type.asClass();
        if (cls.isAbstract() || cls.isInterface()) {
            env.recordException(new InstantiationException());
            return 0;
        }
        Object newObj = RuntimeEntrypoints.resolvedNewScalar(cls);
        return env.pushJNIRef(newObj);
    } catch (Throwable unexpected) {
        if (traceJNI)
            unexpected.printStackTrace(System.err);
        env.recordException(unexpected);
        return 0;
    }
}
Also used : RVMType(org.jikesrvm.classloader.RVMType) RVMClass(org.jikesrvm.classloader.RVMClass) RVMClass(org.jikesrvm.classloader.RVMClass)

Example 69 with RVMClass

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

the class JNIFunctions method GetFieldID.

/**
 * GetFieldID:  return a field id, which can be cached in native code and reused
 * @param env A JREF index for the JNI environment object
 * @param classJREF a JREF index for the RVMClass object
 * @param fieldNameAddress a raw address to a null-terminated string in C for the field name
 * @param descriptorAddress a raw address to a null-terminated string in C for the descriptor
 * @return the fieldID of an instance field given the class, field name
 *         and type. Return 0 if the field is not found
 * @throws NoSuchFieldError if the specified field cannot be found
 * @throws ExceptionInInitializerError if the class initializer fails
 * @throws OutOfMemoryError if the system runs out of memory
 */
private static int GetFieldID(JNIEnvironment env, int classJREF, Address fieldNameAddress, Address descriptorAddress) {
    if (traceJNI)
        VM.sysWriteln("JNI called: GetFieldID");
    RuntimeEntrypoints.checkJNICountDownToGC();
    try {
        if (traceJNI)
            VM.sysWriteln("called GetFieldID with classJREF = ", classJREF);
        Class<?> cls = (Class<?>) env.getJNIRef(classJREF);
        if (VM.VerifyAssertions)
            VM._assert(cls != null);
        String fieldString = JNIGenericHelpers.createStringFromC(fieldNameAddress);
        Atom fieldName = Atom.findOrCreateAsciiAtom(fieldString);
        String descriptorString = JNIGenericHelpers.createStringFromC(descriptorAddress);
        Atom descriptor = Atom.findOrCreateAsciiAtom(descriptorString);
        // list of all instance fields including superclasses.
        // Iterate in reverse order since if there are multiple instance
        // fields of the same name & descriptor we want to find the most derived one.
        RVMField[] fields = java.lang.JikesRVMSupport.getTypeForClass(cls).getInstanceFields();
        for (int i = fields.length - 1; i >= 0; i--) {
            RVMField f = fields[i];
            if (f.getName() == fieldName && f.getDescriptor() == descriptor) {
                return f.getId();
            }
        }
        // create exception and return 0 if not found
        env.recordException(new NoSuchFieldError(fieldString + ", " + descriptorString + " of " + cls));
        return 0;
    } catch (Throwable unexpected) {
        if (traceJNI)
            unexpected.printStackTrace(System.err);
        env.recordException(unexpected);
        return 0;
    }
}
Also used : RVMField(org.jikesrvm.classloader.RVMField) RVMClass(org.jikesrvm.classloader.RVMClass) Atom(org.jikesrvm.classloader.Atom)

Aggregations

RVMClass (org.jikesrvm.classloader.RVMClass)69 RVMMethod (org.jikesrvm.classloader.RVMMethod)28 TypeReference (org.jikesrvm.classloader.TypeReference)22 RVMType (org.jikesrvm.classloader.RVMType)20 Atom (org.jikesrvm.classloader.Atom)14 RVMField (org.jikesrvm.classloader.RVMField)11 RVMArray (org.jikesrvm.classloader.RVMArray)8 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)8 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)8 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)8 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)8 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)8 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)7 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)7 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)7 Address (org.vmmagic.unboxed.Address)7 NormalMethod (org.jikesrvm.classloader.NormalMethod)6 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)6 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)6 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)5