Search in sources :

Example 1 with FIRST_VOLATILE_GPR

use of org.jikesrvm.ppc.RegisterConstants.FIRST_VOLATILE_GPR in project JikesRVM by JikesRVM.

the class JNICompiler method storeParameters.

/**
 * Map the arguments from RVM convention to OS convention,
 * and replace all references with indexes into JNIRefs array.
 * <p>
 * Assumption on entry:
 * <ul>
 *   <li>KLUDGE_TI_REG, THREAD_REGISTER and S1 are available for use as scratch register
 *   <li>the frame has been created, FP points to the new callee frame
 * </ul>
 * <p>
 * Also update the JNIRefs array
 */
private static void storeParameters(Assembler asm, int frameSize, RVMMethod method, RVMClass klass) {
    int nextOSArgReg, nextOSArgFloatReg, nextVMArgReg, nextVMArgFloatReg;
    // offset to the spill area in the callee (OS frame):
    int spillOffsetOS;
    if (VM.BuildForPower64ELF_ABI) {
        // 1st spill = JNIEnv, 2nd spill = class
        spillOffsetOS = NATIVE_FRAME_HEADER_SIZE + 2 * BYTES_IN_STACKSLOT;
    } else {
        if (VM.VerifyAssertions)
            VM._assert(VM.BuildForSVR4ABI);
        spillOffsetOS = NATIVE_FRAME_HEADER_SIZE;
    }
    // offset to the spill area in the caller (RVM frame), relative to the callee's FP
    int spillOffsetVM = frameSize + STACKFRAME_HEADER_SIZE;
    // does NOT include implicit this or class ptr
    TypeReference[] types = method.getParameterTypes();
    // Set up the Reference table for GC
    // TR <- JREFS array base
    asm.emitLAddrOffset(THREAD_REGISTER, S0, Entrypoints.JNIRefsField.getOffset());
    // TI <- JREFS current top
    // JREFS offset for current TOP
    asm.emitLIntOffset(KLUDGE_TI_REG, S0, Entrypoints.JNIRefsTopField.getOffset());
    // convert into address
    asm.emitADD(KLUDGE_TI_REG, THREAD_REGISTER, KLUDGE_TI_REG);
    // TODO - count number of refs
    // TODO - emit overflow check for JNIRefs array
    // start a new JNIRefs frame on each transition from Java to native C
    // push current SavedFP ptr onto top of JNIRefs stack (use available S1 reg as a temp)
    // and make current TOP the new savedFP
    // 
    asm.emitLIntOffset(S1, S0, Entrypoints.JNIRefsSavedFPField.getOffset());
    asm.emitSTWU(S1, BYTES_IN_ADDRESS, // push prev frame ptr onto JNIRefs array
    KLUDGE_TI_REG);
    // compute offset for new TOP
    asm.emitSUBFC(S1, THREAD_REGISTER, KLUDGE_TI_REG);
    asm.emitSTWoffset(S1, S0, // save new TOP as new frame ptr in JNIEnv
    Entrypoints.JNIRefsSavedFPField.getOffset());
    // for static methods: caller has placed args in r3,r4,...
    // for non-static methods:"this" ptr is in r3, and args start in r4,r5,...
    // 
    // for static methods:                for nonstatic methods:
    // Java caller     OS callee         Java caller     OS callee
    // -----------     ----------          -----------     ----------
    // spill = arg11 -> new spill          spill = arg11 -> new spill
    // spill = arg10 -> new spill          spill = arg10 -> new spill
    // spill = arg9  -> new spill
    // spill = arg9  -> new spill
    // spill = arg8  -> new spill          spill = arg8  -> new spill
    // R10 = arg7  -> new spill          spill = arg7  -> new spill
    // R9  = arg6  -> new spill            R10 = arg6  -> new spill
    // 
    // R8  = arg5  -> R10                  R9  = arg5  -> R10
    // R7  = arg4  -> R9                   R8  = arg4  -> R9
    // R6  = arg3  -> R8                   R7  = arg3  -> R8
    // R5  = arg2  -> R7                   R6  = arg2  -> R7
    // R4  = arg1  -> R6                   R5  = arg1  -> R6
    // R3  = arg0  -> R5                   R4  = arg0  -> R5
    // R4 = class           R3  = this  -> R4
    // R3 = JNIenv                         R3 = JNIenv
    // 
    nextOSArgFloatReg = FIRST_OS_PARAMETER_FPR.value();
    nextVMArgFloatReg = FIRST_VOLATILE_FPR.value();
    // 1st reg = JNIEnv, 2nd reg = class/this
    nextOSArgReg = FIRST_OS_PARAMETER_GPR.value() + 2;
    if (method.isStatic()) {
        nextVMArgReg = FIRST_VOLATILE_GPR.value();
    } else {
        // 1st reg = this, to be processed separately
        nextVMArgReg = FIRST_VOLATILE_GPR.value() + 1;
    }
    // The loop below assumes the following relationship:
    if (VM.VerifyAssertions)
        VM._assert(FIRST_OS_PARAMETER_FPR == FIRST_VOLATILE_FPR);
    if (VM.VerifyAssertions)
        VM._assert(LAST_OS_PARAMETER_FPR.value() <= LAST_VOLATILE_FPR.value());
    if (VM.VerifyAssertions)
        VM._assert(FIRST_OS_PARAMETER_GPR == FIRST_VOLATILE_GPR);
    if (VM.VerifyAssertions)
        VM._assert(LAST_OS_PARAMETER_GPR.value() <= LAST_VOLATILE_GPR.value());
    generateParameterPassingCode(asm, types, nextVMArgReg, nextVMArgFloatReg, spillOffsetVM, nextOSArgReg, nextOSArgFloatReg, spillOffsetOS);
    // Now add the 2 JNI parameters:  JNI environment and Class or "this" object
    // if static method, append ref for class, else append ref for "this"
    // and pass offset in JNIRefs array in r4 (as second arg to called native code)
    GPR SECOND_OS_PARAMETER_GPR = GPR.lookup(FIRST_OS_PARAMETER_GPR.value() + 1);
    if (method.isStatic()) {
        // ASSMPTION: JTOC saved above in JNIEnv is still valid,
        // used by following emitLAddrToc
        Offset klassOffset = Offset.fromIntSignExtend(Statics.findOrCreateObjectLiteral(klass.getClassForType()));
        asm.emitLAddrToc(SECOND_OS_PARAMETER_GPR, klassOffset);
        asm.emitSTAddrU(SECOND_OS_PARAMETER_GPR, BYTES_IN_ADDRESS, // append class ptr to end of JNIRefs array
        KLUDGE_TI_REG);
        // pass offset in bytes
        asm.emitSUBFC(SECOND_OS_PARAMETER_GPR, THREAD_REGISTER, KLUDGE_TI_REG);
    } else {
        // append this ptr to end of JNIRefs array
        asm.emitSTAddrU(T0, BYTES_IN_ADDRESS, KLUDGE_TI_REG);
        // pass offset in bytes
        asm.emitSUBFC(SECOND_OS_PARAMETER_GPR, THREAD_REGISTER, KLUDGE_TI_REG);
    }
    // store the new JNIRefs array TOP back into JNIEnv
    // compute offset for the current TOP
    asm.emitSUBFC(KLUDGE_TI_REG, THREAD_REGISTER, KLUDGE_TI_REG);
    asm.emitSTWoffset(KLUDGE_TI_REG, S0, Entrypoints.JNIRefsTopField.getOffset());
}
Also used : LAST_SCRATCH_GPR(org.jikesrvm.ppc.RegisterConstants.LAST_SCRATCH_GPR) LAST_NONVOLATILE_GPR(org.jikesrvm.ppc.RegisterConstants.LAST_NONVOLATILE_GPR) LAST_OS_PARAMETER_GPR(org.jikesrvm.ppc.RegisterConstants.LAST_OS_PARAMETER_GPR) LAST_RVM_RESERVED_NV_GPR(org.jikesrvm.ppc.RegisterConstants.LAST_RVM_RESERVED_NV_GPR) GPR(org.jikesrvm.ppc.RegisterConstants.GPR) FIRST_NONVOLATILE_GPR(org.jikesrvm.ppc.RegisterConstants.FIRST_NONVOLATILE_GPR) FIRST_OS_PARAMETER_GPR(org.jikesrvm.ppc.RegisterConstants.FIRST_OS_PARAMETER_GPR) FIRST_RVM_RESERVED_NV_GPR(org.jikesrvm.ppc.RegisterConstants.FIRST_RVM_RESERVED_NV_GPR) LAST_VOLATILE_GPR(org.jikesrvm.ppc.RegisterConstants.LAST_VOLATILE_GPR) FIRST_VOLATILE_GPR(org.jikesrvm.ppc.RegisterConstants.FIRST_VOLATILE_GPR) TypeReference(org.jikesrvm.classloader.TypeReference) Offset(org.vmmagic.unboxed.Offset)

Aggregations

TypeReference (org.jikesrvm.classloader.TypeReference)1 FIRST_NONVOLATILE_GPR (org.jikesrvm.ppc.RegisterConstants.FIRST_NONVOLATILE_GPR)1 FIRST_OS_PARAMETER_GPR (org.jikesrvm.ppc.RegisterConstants.FIRST_OS_PARAMETER_GPR)1 FIRST_RVM_RESERVED_NV_GPR (org.jikesrvm.ppc.RegisterConstants.FIRST_RVM_RESERVED_NV_GPR)1 FIRST_VOLATILE_GPR (org.jikesrvm.ppc.RegisterConstants.FIRST_VOLATILE_GPR)1 GPR (org.jikesrvm.ppc.RegisterConstants.GPR)1 LAST_NONVOLATILE_GPR (org.jikesrvm.ppc.RegisterConstants.LAST_NONVOLATILE_GPR)1 LAST_OS_PARAMETER_GPR (org.jikesrvm.ppc.RegisterConstants.LAST_OS_PARAMETER_GPR)1 LAST_RVM_RESERVED_NV_GPR (org.jikesrvm.ppc.RegisterConstants.LAST_RVM_RESERVED_NV_GPR)1 LAST_SCRATCH_GPR (org.jikesrvm.ppc.RegisterConstants.LAST_SCRATCH_GPR)1 LAST_VOLATILE_GPR (org.jikesrvm.ppc.RegisterConstants.LAST_VOLATILE_GPR)1 Offset (org.vmmagic.unboxed.Offset)1