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