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());
}
Aggregations