use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.
the class FinalMIRExpansion method expandYieldpoint.
private static void expandYieldpoint(Instruction s, IR ir, RVMMethod meth, IA32ConditionOperand ypCond) {
// split the basic block after the yieldpoint, create a new
// block at the end of the IR to hold the yieldpoint,
// remove the yieldpoint (to prepare to out it in the new block at the end)
BasicBlock thisBlock = s.getBasicBlock();
BasicBlock nextBlock = thisBlock.splitNodeWithLinksAt(s, ir);
BasicBlock yieldpoint = thisBlock.createSubBlock(s.getBytecodeIndex(), ir, 0);
thisBlock.insertOut(yieldpoint);
yieldpoint.insertOut(nextBlock);
ir.cfg.addLastInCodeOrder(yieldpoint);
s.remove();
// change thread switch instruction into call to thread switch routine
// NOTE: must make s the call instruction: it is the GC point!
// must also inform the GCMap that s has been moved!!!
Offset offset = meth.getOffset();
LocationOperand loc = new LocationOperand(offset);
Operand guard = TG();
Operand target;
if (JTOC_REGISTER == null) {
target = MemoryOperand.D(Magic.getTocPointer().plus(offset), (byte) BYTES_IN_ADDRESS, loc, guard);
} else {
target = MemoryOperand.BD(ir.regpool.makeTocOp().asRegister(), offset, (byte) BYTES_IN_ADDRESS, loc, guard);
}
MIR_Call.mutate0(s, CALL_SAVE_VOLATILE, null, null, target, MethodOperand.STATIC(meth));
yieldpoint.appendInstruction(s);
ir.MIRInfo.gcIRMap.moveToEnd(s);
yieldpoint.appendInstruction(MIR_Branch.create(IA32_JMP, nextBlock.makeJumpTarget()));
// Check to see if threadSwitch requested
Offset tsr = Entrypoints.takeYieldpointField.getOffset();
MemoryOperand M = MemoryOperand.BD(ir.regpool.makeTROp(), tsr, (byte) 4, null, null);
thisBlock.appendInstruction(MIR_Compare.create(IA32_CMP, M, IC(0)));
thisBlock.appendInstruction(MIR_CondBranch.create(IA32_JCC, ypCond, yieldpoint.makeJumpTarget(), BranchProfileOperand.never()));
}
use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.
the class FinalMIRExpansion method findOrCreateYieldpointBlock.
/**
* Return a basic block holding the call to a runtime yield service.
* Create a new basic block at the end of the code order if necessary.
*
* @param ir the governing IR
* @param whereFrom is this yieldpoint from the PROLOGUE, EPILOGUE, or a
* BACKEDGE?
*/
static BasicBlock findOrCreateYieldpointBlock(IR ir, int whereFrom) {
RVMMethod meth = null;
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
Register zero = phys.getGPR(0);
// state for creating the block
if (whereFrom == RVMThread.PROLOGUE) {
if (ir.MIRInfo.prologueYieldpointBlock != null) {
return ir.MIRInfo.prologueYieldpointBlock;
} else {
meth = Entrypoints.optThreadSwitchFromPrologueMethod;
}
} else if (whereFrom == RVMThread.BACKEDGE) {
if (ir.MIRInfo.backedgeYieldpointBlock != null) {
return ir.MIRInfo.backedgeYieldpointBlock;
} else {
meth = Entrypoints.optThreadSwitchFromBackedgeMethod;
}
} else if (whereFrom == RVMThread.EPILOGUE) {
if (ir.MIRInfo.epilogueYieldpointBlock != null) {
return ir.MIRInfo.epilogueYieldpointBlock;
} else {
meth = Entrypoints.optThreadSwitchFromEpilogueMethod;
}
} else if (whereFrom == RVMThread.OSROPT) {
if (ir.MIRInfo.osrYieldpointBlock != null) {
return ir.MIRInfo.osrYieldpointBlock;
} else {
meth = Entrypoints.optThreadSwitchFromOsrOptMethod;
}
}
// Not found. create new basic block holding the requested yieldpoint
// method
BasicBlock result = new BasicBlock(-1, null, ir.cfg);
ir.cfg.addLastInCodeOrder(result);
Register JTOC = phys.getJTOC();
Register CTR = phys.getCTR();
Offset offset = meth.getOffset();
if (fits(offset, 16)) {
result.appendInstruction(MIR_Load.create(PPC_LAddr, A(zero), A(JTOC), IC(PPCMaskLower16(offset))));
} else {
// not implemented
if (VM.VerifyAssertions)
VM._assert(fits(offset, 32));
result.appendInstruction(MIR_Binary.create(PPC_ADDIS, A(zero), A(JTOC), IC(PPCMaskUpper16(offset))));
result.appendInstruction(MIR_Load.create(PPC_LAddr, A(zero), A(zero), IC(PPCMaskLower16(offset))));
}
result.appendInstruction(MIR_Move.create(PPC_MTSPR, A(CTR), A(zero)));
result.appendInstruction(MIR_Branch.create(PPC_BCTR));
// cache the create block and then return it
if (whereFrom == RVMThread.PROLOGUE) {
ir.MIRInfo.prologueYieldpointBlock = result;
} else if (whereFrom == RVMThread.BACKEDGE) {
ir.MIRInfo.backedgeYieldpointBlock = result;
} else if (whereFrom == RVMThread.EPILOGUE) {
ir.MIRInfo.epilogueYieldpointBlock = result;
} else if (whereFrom == RVMThread.OSROPT) {
ir.MIRInfo.osrYieldpointBlock = result;
}
return result;
}
use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.
the class JNIHelpers method pushVarArgToSpillArea.
/**
* This method supports var args passed from C.<p>
*
* TODO update for AIX removal
*
* In the AIX C convention, the caller keeps the first 8 words in registers and
* the rest in the spill area in the caller frame. The callee will push the values
* in registers out to the spill area of the caller frame and use the beginning
* address of this spill area as the var arg address.<p>
*
* For the JNI functions that takes var args, their prolog code will save the
* var arg in the glue frame because the values in the register may be lost by
* subsequent calls.<p>
*
* This method copies the var arg values that were saved earlier in glue frame into
* the spill area of the original caller, thereby doing the work that the callee
* normally performs in the AIX C convention..<p>
*
* NOTE: this method assumes that it is immediately above the
* invokeWithDotDotVarArg frame, the JNI frame, the glue frame and
* the C caller frame in the respective order.
* Therefore, this method will not work if called from anywhere else
* <pre>
*
* | fp | <- JNIEnvironment.pushVarArgToSpillArea
* | mid |
* | xxx |
* | |
* | |
* |------|
* | fp | <- JNIEnvironment.invokeWithDotDotVarArg frame
* | mid |
* | xxx |
* | |
* | |
* | |
* |------|
* | fp | <- JNI method frame
* | mid |
* | xxx |
* | |
* | |
* | |
* |------|
* | fp | <- glue frame
* | mid |
* + xxx +
* | r3 | volatile save area
* | r4 |
* | r5 |
* | r6 | vararg GPR[6-10]save area <- VARARG_AREA_OFFSET
* | r7 |
* | r8 |
* | r9 |
* | r10 |
* | fpr1 | vararg FPR[1-3] save area (also used as volatile FPR[1-6] save area)
* | fpr2 |
* | fpr3 |
* | fpr4 |
* | fpr5 |
* + fpr6 +
* | r13 | nonvolatile GPR[13-31] save area
* | ... |
* + r31 +
* | fpr14| nonvolatile FPR[14-31] save area
* | ... |
* | fpr31|
* |topjav| offset to preceding Java to C glue frame
* |------|
* | fp | <- Native C caller frame
* | cr |
* | lr |
* | resv |
* | resv |
* + toc +
* | 0 | spill area initially not filled
* | 1 | to be filled by this method
* | 2 |
* | 3 |
* | 4 |
* | 5 |
* | 6 |
* | 7 |
* | 8 | spill area already filled by caller
* | 9 |
* | |
* | |
* | |
* </pre>
*
* @param methodID a MemberReference id
* @param skip4Args if true, the calling JNI function has 4 args before the vararg
* if false, the calling JNI function has 3 args before the vararg
* @return the starting address of the vararg in the caller stack frame
*/
@NoInline
private static Address pushVarArgToSpillArea(int methodID, boolean skip4Args) throws Exception {
if (!(VM.BuildForPower64ELF_ABI || VM.BuildForSVR4ABI)) {
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
return Address.zero();
}
int glueFrameSize = JNI_GLUE_FRAME_SIZE;
// get the FP for this stack frame and traverse 3 frames to get to the glue frame
Address gluefp = // *.ppc.JNIHelpers.invoke*
Magic.getFramePointer().plus(StackFrameLayout.getStackFramePointerOffset()).loadAddress();
// architecture.JNIHelpers.invoke*
gluefp = gluefp.plus(StackFrameLayout.getStackFramePointerOffset()).loadAddress();
// JNIFunctions
gluefp = gluefp.plus(StackFrameLayout.getStackFramePointerOffset()).loadAddress();
// glue frame
gluefp = gluefp.plus(StackFrameLayout.getStackFramePointerOffset()).loadAddress();
// compute the offset into the area where the vararg GPR[6-10] and FPR[1-3] are saved
// skipping the args which are not part of the arguments for the target method
// For Call<type>Method functions and NewObject, skip 3 args
// For CallNonvirtual<type>Method functions, skip 4 args
Offset varargGPROffset = Offset.fromIntSignExtend(VARARG_AREA_OFFSET + (skip4Args ? BYTES_IN_ADDRESS : 0));
Offset varargFPROffset = varargGPROffset.plus(5 * BYTES_IN_ADDRESS);
// compute the offset into the spill area of the native caller frame,
// skipping the args which are not part of the arguments for the target method
// For Call<type>Method functions, skip 3 args
// For CallNonvirtual<type>Method functions, skip 4 args
Offset spillAreaLimit = Offset.fromIntSignExtend(glueFrameSize + NATIVE_FRAME_HEADER_SIZE + 8 * BYTES_IN_ADDRESS);
Offset spillAreaOffset = Offset.fromIntSignExtend(glueFrameSize + NATIVE_FRAME_HEADER_SIZE + (skip4Args ? 4 * BYTES_IN_ADDRESS : 3 * BYTES_IN_ADDRESS));
// address to return pointing to the var arg list
Address varargAddress = gluefp.plus(spillAreaOffset);
// VM.sysWrite("pushVarArgToSpillArea: var arg at " +
// Services.intAsHexString(varargAddress) + "\n");
RVMMethod targetMethod = MemberReference.getMethodRef(methodID).resolve();
TypeReference[] argTypes = targetMethod.getParameterTypes();
int argCount = argTypes.length;
for (int i = 0; i < argCount && spillAreaOffset.sLT(spillAreaLimit); i++) {
Word hiword, loword;
if (argTypes[i].isFloatingPointType()) {
// move 2 words from the vararg FPR save area into the spill area of the caller
hiword = gluefp.loadWord(varargFPROffset);
varargFPROffset = varargFPROffset.plus(BYTES_IN_ADDRESS);
if (VM.BuildFor32Addr) {
loword = gluefp.loadWord(varargFPROffset);
varargFPROffset = varargFPROffset.plus(BYTES_IN_ADDRESS);
}
gluefp.store(hiword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
if (VM.BuildFor32Addr) {
gluefp.store(loword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
}
} else if (argTypes[i].isLongType()) {
// move 2 words from the vararg GPR save area into the spill area of the caller
hiword = gluefp.loadWord(varargGPROffset);
varargGPROffset = varargGPROffset.plus(BYTES_IN_ADDRESS);
gluefp.store(hiword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
// this covers the case when the long value straddles the spill boundary
if (VM.BuildFor32Addr && spillAreaOffset.sLT(spillAreaLimit)) {
loword = gluefp.loadWord(varargGPROffset);
varargGPROffset = varargGPROffset.plus(BYTES_IN_ADDRESS);
gluefp.store(loword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
}
} else {
hiword = gluefp.loadWord(varargGPROffset);
varargGPROffset = varargGPROffset.plus(BYTES_IN_ADDRESS);
gluefp.store(hiword, spillAreaOffset);
spillAreaOffset = spillAreaOffset.plus(BYTES_IN_ADDRESS);
}
}
// return the address of the beginning of the vararg to use in invoking the target method
return varargAddress;
}
use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.
the class Barriers method floatArrayRead.
/**
* Barrier for loads of floats from fields of arrays (i.e. faload).
*
* @param ref the array containing the reference.
* @param index the index into the array were the reference resides.
* @return the value read from the array
*/
@Inline
@Entrypoint
public static float floatArrayRead(float[] ref, int index) {
if (NEEDS_FLOAT_GC_READ_BARRIER) {
ObjectReference array = ObjectReference.fromObject(ref);
Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT);
return Selected.Mutator.get().floatRead(array, array.toAddress().plus(offset), offset.toWord(), Word.zero(), ARRAY_ELEMENT);
} else if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
return 0;
}
use of org.vmmagic.unboxed.Offset in project JikesRVM by JikesRVM.
the class Barriers method floatArrayWrite.
/**
* Barrier for writes of floats into arrays (i.e. fastore).
*
* @param ref the array which is the subject of the astore
* @param index the index into the array where the new reference
* resides. The index is the "natural" index into the array, for
* example a[index].
* @param value the value to be stored.
*/
@Inline
@Entrypoint
public static void floatArrayWrite(float[] ref, int index, float value) {
if (NEEDS_FLOAT_GC_WRITE_BARRIER) {
ObjectReference array = ObjectReference.fromObject(ref);
Offset offset = Offset.fromIntZeroExtend(index << LOG_BYTES_IN_FLOAT);
Selected.Mutator.get().floatWrite(array, array.toAddress().plus(offset), value, offset.toWord(), Word.zero(), ARRAY_ELEMENT);
} else if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
}
Aggregations