use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand 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;
}
use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method expandSysCallTarget.
/**
* Expand symbolic SysCall target into a chain of loads from the bootrecord to
* the desired target address.
*
* @param s the call instruction
* @param ir the governing IR
*/
public static void expandSysCallTarget(Instruction s, IR ir) {
MethodOperand sysM = Call.getMethod(s);
if (sysM.getMemberRef().isFieldReference()) {
RegisterOperand t1 = getStatic(s, ir, Entrypoints.the_boot_recordField);
RVMField target = sysM.getMemberRef().asFieldReference().resolve();
Operand ip = getField(s, ir, t1, target);
Call.setAddress(s, ip);
}
}
use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand in project JikesRVM by JikesRVM.
the class TailRecursionElimination method isTailRecursion.
/**
* Is the argument call instruction a tail recursive call?
*
* @param call the call in question
* @param ir the enclosing IR
* @return <code>true</code> if call is tail recursive and
* <code>false</code> if it is not.
*/
boolean isTailRecursion(Instruction call, IR ir) {
if (!Call.hasMethod(call))
return false;
MethodOperand methOp = Call.getMethod(call);
if (!methOp.hasPreciseTarget())
return false;
if (methOp.getTarget() != ir.method)
return false;
RegisterOperand result = Call.getResult(call);
Instruction s = call.nextInstructionInCodeOrder();
while (true) {
if (s.isMove()) {
if (Move.getVal(s).similar(result)) {
result = Move.getResult(s);
if (DEBUG)
VM.sysWriteln("Updating result to " + result);
} else {
// move of a value that isn't the result blocks us
return false;
}
} else if (s.operator() == LABEL || s.operator() == BBEND || s.operator() == UNINT_BEGIN || s.operator() == UNINT_END) {
if (DEBUG)
VM.sysWriteln("Falling through " + s);
// skip over housekeeping instructions and follow the code order.
} else if (s.operator() == GOTO) {
// follow the unconditional branch to its target LABEL
s = s.getBranchTarget().firstInstruction();
if (DEBUG)
VM.sysWriteln("Following goto to " + s);
} else if (s.isReturn()) {
Operand methodResult = Return.getVal(s);
if (DEBUG)
VM.sysWriteln("Found return " + s);
return methodResult == null || methodResult.similar(result);
} else {
// any other instruction blocks us
return false;
}
s = s.nextInstructionInCodeOrder();
}
}
use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand in project JikesRVM by JikesRVM.
the class UnsyncReplacer method transform.
/**
* Perform the transformation for a given register appearance
*
* @param rop The def or use to check
*/
private void transform(RegisterOperand rop) {
final boolean DEBUG = false;
Instruction inst = rop.instruction;
switch(inst.getOpcode()) {
case SYSCALL_opcode:
case CALL_opcode:
RegisterOperand invokee = Call.getParam(inst, 0).asRegister();
if (invokee == rop) {
// replace with equivalent call on the synthetic
// unsynchronized type
MethodOperand mop = Call.getMethod(inst);
if (mop.getTarget().isSynchronized()) {
mop.spMethod = context.findOrCreateSpecializedVersion((NormalMethod) mop.getTarget());
if (DEBUG) {
VM.sysWriteln("Identified call " + inst + " for unsynchronization");
}
}
}
break;
case MONITORENTER_opcode:
if (DEBUG) {
VM.sysWrite("Removing " + inst);
}
inst.insertBefore(Empty.create(READ_CEILING));
DefUse.removeInstructionAndUpdateDU(inst);
break;
case MONITOREXIT_opcode:
if (DEBUG) {
VM.sysWrite("Removing " + inst);
}
inst.insertAfter(Empty.create(WRITE_FLOOR));
DefUse.removeInstructionAndUpdateDU(inst);
break;
default:
// no action necessary
break;
}
}
use of org.jikesrvm.compilers.opt.ir.operand.MethodOperand in project JikesRVM by JikesRVM.
the class GenerationContextTest method basicChildContextsWorkCorrectly.
@Test
public void basicChildContextsWorkCorrectly() throws Exception {
NormalMethod nm = getNormalMethodForTest("methodForInliningTests");
CompiledMethod cm = new OptCompiledMethod(-1, nm);
OptOptions opts = new OptOptions();
InlineOracle io = new DefaultInlineOracle();
GenerationContext gc = new GenerationContext(nm, null, cm, opts, io);
Class<?>[] classArgs = { Object.class };
NormalMethod callee = getNormalMethodForTest("emptyStaticMethodWithObjectParamAndReturnValue", classArgs);
MethodOperand methOp = MethodOperand.STATIC(callee);
RegisterOperand result = createMockRegisterOperand(TypeReference.JavaLangObject);
Instruction callInstr = Call.create(CALL, result, null, methOp, 1);
RegisterOperand objectParam = createMockRegisterOperand(TypeReference.JavaLangObject);
Call.setParam(callInstr, 0, objectParam);
callInstr.setPosition(new InlineSequence(nm));
ExceptionHandlerBasicBlockBag ebag = getMockEbag();
int nodeNumber = 12345;
gc.getCfg().setNumberOfNodes(nodeNumber);
GenerationContext child = gc.createChildContext(ebag, callee, callInstr);
RegisterOperand expectedLocalForObjectParam = child.makeLocal(0, objectParam);
assertThatStateIsCopiedFromParentToChild(gc, callee, child, ebag);
InlineSequence expectedInlineSequence = new InlineSequence(callee, callInstr.position(), callInstr);
assertEquals(expectedInlineSequence, child.getInlineSequence());
RegisterOperand firstArg = child.getArguments()[0].asRegister();
assertTrue(firstArg.sameRegisterPropertiesAs(expectedLocalForObjectParam));
assertSame(result.getRegister(), child.getResultReg());
assertTrue(child.getResultReg().spansBasicBlock());
assertThatPrologueAndEpilogueAreWiredCorrectlyForChildContext(ebag, nodeNumber, child);
Enumeration<Instruction> prologueRealInstr = child.getPrologue().forwardRealInstrEnumerator();
Instruction move = prologueRealInstr.nextElement();
RegisterOperand objectParamInChild = objectParam.copy().asRegister();
assertMoveOperationIsCorrect(callInstr, REF_MOVE, expectedLocalForObjectParam, objectParamInChild, move);
assertThatNoMoreInstructionsExist(prologueRealInstr);
Enumeration<Instruction> epilogueRealInstr = child.getEpilogue().forwardRealInstrEnumerator();
assertThatNoMoreInstructionsExist(epilogueRealInstr);
assertThatNoRethrowBlockExists(child);
assertThatChecksWontBeSkipped(gc);
}
Aggregations