Search in sources :

Example 1 with SpecializedMethod

use of org.jikesrvm.compilers.opt.specialization.SpecializedMethod in project JikesRVM by JikesRVM.

the class ConvertToLowLevelIR method callHelper.

/**
 * Helper method for call expansion.
 * @param v the call instruction
 * @param ir the containing IR
 * @return the last expanded instruction
 */
static Instruction callHelper(Instruction v, IR ir) {
    if (!Call.hasMethod(v)) {
        if (VM.VerifyAssertions)
            VM._assert(Call.getAddress(v) instanceof RegisterOperand);
        // nothing to do....very low level call to address already in the register.
        return v;
    }
    MethodOperand methOp = Call.getMethod(v);
    // Handle recursive invocations.
    if (methOp.hasPreciseTarget() && methOp.getTarget() == ir.method) {
        Call.setAddress(v, new BranchOperand(ir.firstInstructionInCodeOrder()));
        return v;
    }
    // has been marked as a specialized call.
    if (VM.runningVM) {
        SpecializedMethod spMethod = methOp.spMethod;
        if (spMethod != null) {
            int smid = spMethod.getSpecializedMethodIndex();
            Call.setAddress(v, getSpecialMethod(v, ir, smid));
            return v;
        }
    }
    // Used mainly (only?) by OSR
    if (methOp.hasDesignatedTarget()) {
        Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, methOp.jtocOffset));
        return v;
    }
    if (methOp.isStatic()) {
        if (VM.VerifyAssertions)
            VM._assert(Call.hasAddress(v));
        Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, Call.getClearAddress(v)));
    } else if (methOp.isVirtual()) {
        if (VM.VerifyAssertions)
            VM._assert(Call.hasAddress(v));
        if (ir.options.H2L_CALL_VIA_JTOC && methOp.hasPreciseTarget()) {
            // Call to precise type can go via JTOC
            RVMMethod target = methOp.getTarget();
            Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, target.findOrCreateJtocOffset()));
        } else {
            Operand tib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
            Call.setAddress(v, InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, tib, Call.getClearAddress(v), null, TG()));
        }
    } else if (methOp.isSpecial()) {
        RVMMethod target = methOp.getTarget();
        if (target == null || target.isObjectInitializer() || target.isStatic()) {
            // target == null => we are calling an unresolved <init> method.
            Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, Call.getClearAddress(v)));
        } else {
            if (ir.options.H2L_CALL_VIA_JTOC) {
                Call.setAddress(v, InsertLoadOffsetJTOC(v, ir, REF_LOAD, TypeReference.CodeArray, target.findOrCreateJtocOffset()));
            } else {
                // invoking a virtual method; do it via TIB of target's declaring class.
                Operand tib = getTIB(v, ir, target.getDeclaringClass());
                Call.setAddress(v, InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, tib, Call.getClearAddress(v), null, TG()));
            }
        }
    } else {
        if (VM.VerifyAssertions)
            VM._assert(methOp.isInterface());
        if (VM.VerifyAssertions)
            VM._assert(!Call.hasAddress(v));
        if (VM.BuildForIMTInterfaceInvocation) {
            // SEE ALSO: FinalMIRExpansion (for hidden parameter)
            Operand RHStib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
            InterfaceMethodSignature sig = InterfaceMethodSignature.findOrCreate(methOp.getMemberRef());
            Offset offset = sig.getIMTOffset();
            RegisterOperand address = null;
            RegisterOperand IMT = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.IMT, RHStib.copy(), Offset.fromIntZeroExtend(TIB_INTERFACE_DISPATCH_TABLE_INDEX << LOG_BYTES_IN_ADDRESS));
            address = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, IMT.copyD2U(), offset);
            Call.setAddress(v, address);
        } else {
            int itableIndex = -1;
            if (VM.BuildForITableInterfaceInvocation && methOp.hasTarget()) {
                RVMClass I = methOp.getTarget().getDeclaringClass();
                // search ITable variant
                itableIndex = InterfaceInvocation.getITableIndex(I, methOp.getMemberRef().getName(), methOp.getMemberRef().getDescriptor());
            }
            if (itableIndex == -1) {
                // itable index is not known at compile-time.
                // call "invokeinterface" to resolve the object and method id
                // into a method address
                RegisterOperand realAddrReg = ir.regpool.makeTemp(TypeReference.CodeArray);
                RVMMethod target = Entrypoints.invokeInterfaceMethod;
                Instruction vp = Call.create2(CALL, realAddrReg, AC(target.getOffset()), MethodOperand.STATIC(target), Call.getParam(v, 0).asRegister().copyU2U(), IC(methOp.getMemberRef().getId()));
                vp.setSourcePosition(RUNTIME_SERVICES_BCI, v.position());
                v.insertBefore(vp);
                callHelper(vp, ir);
                Call.setAddress(v, realAddrReg.copyD2U());
                return v;
            } else {
                // itable index is known at compile-time.
                // call "findITable" to resolve object + interface id into
                // itable address
                RegisterOperand iTable = ir.regpool.makeTemp(TypeReference.ITable);
                Operand RHStib = getTIB(v, ir, Call.getParam(v, 0).copy(), Call.getGuard(v).copy());
                RVMMethod target = Entrypoints.findItableMethod;
                Instruction fi = Call.create2(CALL, iTable, AC(target.getOffset()), MethodOperand.STATIC(target), RHStib, IC(methOp.getTarget().getDeclaringClass().getInterfaceId()));
                fi.setSourcePosition(RUNTIME_SERVICES_BCI, v.position());
                v.insertBefore(fi);
                callHelper(fi, ir);
                RegisterOperand address = InsertLoadOffset(v, ir, REF_LOAD, TypeReference.CodeArray, iTable.copyD2U(), Offset.fromIntZeroExtend(itableIndex << LOG_BYTES_IN_ADDRESS));
                Call.setAddress(v, address);
                return v;
            }
        }
    }
    return v;
}
Also used : InterfaceMethodSignature(org.jikesrvm.classloader.InterfaceMethodSignature) RVMMethod(org.jikesrvm.classloader.RVMMethod) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) SpecializedMethod(org.jikesrvm.compilers.opt.specialization.SpecializedMethod) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) Offset(org.vmmagic.unboxed.Offset) RVMClass(org.jikesrvm.classloader.RVMClass)

Aggregations

InterfaceMethodSignature (org.jikesrvm.classloader.InterfaceMethodSignature)1 RVMClass (org.jikesrvm.classloader.RVMClass)1 RVMMethod (org.jikesrvm.classloader.RVMMethod)1 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)1 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)1 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)1 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)1 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)1 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)1 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)1 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)1 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)1 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)1 TIBConstantOperand (org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand)1 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)1 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)1 SpecializedMethod (org.jikesrvm.compilers.opt.specialization.SpecializedMethod)1 Offset (org.vmmagic.unboxed.Offset)1