Search in sources :

Example 21 with MethodReference

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

the class JNIHelpers method invokeWithDotDotVarArg.

/**
 * Common code shared by the JNI functions Call<type>Method
 * (virtual method invocation)
 * @param obj the object instance
 * @param methodID the method ID
 * @param expectReturnType the return type for checking purpose
 * @param skip4Args  true if the calling JNI Function takes 4 args before the vararg
 *                   false if the calling JNI Function takes 3 args before the vararg
 * @return an object that may be the return object or a wrapper for the primitive return value
 */
@NoInline
public static Object invokeWithDotDotVarArg(Object obj, int methodID, TypeReference expectReturnType, boolean skip4Args) throws Exception {
    MethodReference mr = MemberReference.getMethodRef(methodID);
    if (VM.BuildForPower64ELF_ABI) {
        Address varargAddress = pushVarArgToSpillArea(methodID, skip4Args);
        Object[] argObjectArray = packageParameterFromVarArg(mr, varargAddress);
        return callMethod(obj, mr, argObjectArray, expectReturnType, skip4Args);
    } else {
        if (VM.VerifyAssertions)
            VM._assert(VM.BuildForSVR4ABI);
        Address glueFP = Magic.getCallerFramePointer(Magic.getCallerFramePointer(Magic.getCallerFramePointer(Magic.getFramePointer())));
        Object[] argObjectArray = packageParameterFromDotArgSVR4(mr, glueFP, skip4Args);
        return callMethod(obj, mr, argObjectArray, expectReturnType, skip4Args);
    }
}
Also used : Address(org.vmmagic.unboxed.Address) MethodReference(org.jikesrvm.classloader.MethodReference) NoInline(org.vmmagic.pragma.NoInline)

Example 22 with MethodReference

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

the class JNIHelpers method invokeInitializer.

/**
 * Common code shared by the JNI functions NewObjectA, NewObjectV, NewObject
 * (object creation)
 * @param methodID the method ID for a constructor
 * @return a new object created by the specified constructor
 */
public static Object invokeInitializer(Class<?> cls, int methodID, Address argAddress, boolean isJvalue, boolean isDotDotStyle) throws Exception {
    // get the parameter list as Java class
    MemberReference mr = MemberReference.getMemberRef(methodID);
    TypeReference tr = java.lang.JikesRVMSupport.getTypeForClass(cls).getTypeRef();
    MethodReference methodRef = MemberReference.findOrCreate(tr, mr.getName(), mr.getDescriptor()).asMethodReference();
    RVMMethod mth = methodRef.resolve();
    Constructor<?> constMethod = java.lang.reflect.JikesRVMSupport.createConstructor(mth);
    if (!mth.isPublic()) {
        constMethod.setAccessible(true);
    }
    Object[] argObjs;
    if (isJvalue) {
        argObjs = packageParametersFromJValuePtr(methodRef, argAddress);
    } else if (isDotDotStyle) {
        // dot dot var arg
        if (VM.BuildForPower64ELF_ABI) {
            Address varargAddress = pushVarArgToSpillArea(methodID, false);
            argObjs = packageParameterFromVarArg(methodRef, varargAddress);
        } else {
            if (VM.VerifyAssertions)
                VM._assert(VM.BuildForSVR4ABI);
            // pass in the frame pointer of glue stack frames
            // stack frame looks as following:
            // this method ->
            // 
            // architecture.JNIHelpers.method -->
            // 
            // native to java method ->
            // 
            // glue frame ->
            // 
            // native C method ->
            Address gluefp = Magic.getCallerFramePointer(Magic.getCallerFramePointer(Magic.getCallerFramePointer(Magic.getFramePointer())));
            argObjs = packageParameterFromDotArgSVR4(methodRef, gluefp, false);
        }
    } else {
        // mormal var arg
        if (VM.BuildForPower64ELF_ABI) {
            argObjs = packageParameterFromVarArg(methodRef, argAddress);
        } else {
            if (VM.VerifyAssertions)
                VM._assert(VM.BuildForSVR4ABI);
            argObjs = packageParameterFromVarArgSVR4(methodRef, argAddress);
        }
    }
    // construct the new object
    return constMethod.newInstance(argObjs);
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) Address(org.vmmagic.unboxed.Address) MemberReference(org.jikesrvm.classloader.MemberReference) MethodReference(org.jikesrvm.classloader.MethodReference) TypeReference(org.jikesrvm.classloader.TypeReference)

Example 23 with MethodReference

use of org.jikesrvm.classloader.MethodReference 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)

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