use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class AnalysisResultSerialization method fromContextMapResult.
/**
* <p>Result Map: MethodInfo -> Instruction Offset -> Callstring -> R</p>
* <p>TODO: More efficient representations are possible</p>
* @param result the result of the DFA analysis
* @param serializer converter for the result domain (if not serializable), or null
* if the results of type T should be serialized directly
*/
public static <T, R> AnalysisResultSerialization<R> fromContextMapResult(Map<InstructionHandle, ContextMap<CallString, T>> result, Serializer<T, R> serializer) {
AnalysisResultSerialization<R> analysisResult = new AnalysisResultSerialization<R>();
/* sort instruction handle by: method, offset */
for (InstructionHandle instr : result.keySet()) {
ContextMap<CallString, T> r = result.get(instr);
Context c = r.getContext();
InstructionList il = c.getMethodInfo().getCode().getInstructionList(true, false);
for (CallString cs : r.keySet()) {
Integer position = instr.getPosition();
// skip stuff that is not used anymore
if (position < 0)
continue;
if (il.findHandle(position) != instr)
continue;
if (serializer != null) {
T rValue = r.get(cs);
R sValue = serializer.serializedRepresentation(rValue);
analysisResult.addResult(c.getMethodInfo(), position, cs, sValue);
} else {
analysisResult.addResult(c.getMethodInfo(), position, cs, (R) r.get(cs));
}
}
}
return analysisResult;
}
use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class InlineHelper method prepareInlining.
/**
* Prepare the invokee for inlining into the invokesite, by widening access restrictions or renaming
* methods to prevent incorrect method resolving.
* <p>
* This may change the code of the invokee, so this needs to be done before inlining the code.
* The CFG of the invokee will be removed.
* </p><p>
* This code assumes that {@link #canInline(CallString, InvokeSite, MethodInfo)} returned true for this invoke.
* </p>
*
* @param invoker the method where the code will be inlined to.
* @param invokee the method to inline.
*/
public void prepareInlining(MethodInfo invoker, MethodInfo invokee) {
MethodCode code = invokee.getCode();
InstructionList il = code.getInstructionList();
for (InstructionHandle ih : il.getInstructionHandles()) {
Instruction instr = ih.getInstruction();
if (instr instanceof InvokeInstruction) {
InvokeSite invokeSite = code.getInvokeSite(ih);
MethodRef ref = invokeSite.getInvokeeRef();
MethodInfo method = ref.getMethodInfo();
// we already checked that everything can be resolved
// nothing special to do for invokespecial here (checkInvokeSpecial only skips, no special return codes)
// check what we need to do
CheckResult rs = checkNeedsPublic(invoker, invokee, ref.getClassInfo(), method);
if (rs == CheckResult.NEEDS_PUBLIC) {
makePublic(method);
}
if (rs == CheckResult.NEEDS_PUBLIC_RENAME) {
if (method.isPrivate()) {
// TODO check the class for invokers, change to invokevirtual
} else {
// if the method is package visible, we need to rename all overriding methods
// too (but not methods from subclasses in different packages which do not override this)
// TODO update overriding methods
// TODO need to update all possible call sites
}
makePublic(method);
throw new AppInfoError("Implement me!");
}
} else if (instr instanceof FieldInstruction) {
FieldRef ref = code.getFieldRef(ih);
FieldInfo field = ref.getFieldInfo();
// we already checked that everything can be resolved
// check if fields need to be set to public
CheckResult rs = checkNeedsPublic(invoker, invokee, ref.getClassInfo(), field);
if (rs == CheckResult.NEEDS_PUBLIC) {
makePublic(field);
}
if (rs == CheckResult.NEEDS_PUBLIC_RENAME) {
throw new AppInfoError("Invalid returncode: renaming of fields not required");
}
}
}
}
use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class InlineHelper method needsNullpointerCheck.
/**
* Check if an exception must be generated if the 'this' reference is null.
* This test can return false if
* <ul><li>There is no 'this' reference</li>
* <li>The DFA analysis showed that the reference is never null</li>
* <li>The inlined code will always generate an exception anyway</li>
* <li>Generating checks has been disabled by configuration</li>
* </ul>
* <p>
* The callstring does not need to start or to end at the method to optimize. However since the callstring is
* used to check the DFA results if available, the callstring must match what the DFA expects, i.e. if
* the DFA-results and -callstrings are updated during inlining, this callstring must not include inlined
* invokes. Contrariwise if the DFA results are not updated during inline, the callstring must contain already
* inlined invokes.
* </p>
*
* @param callString The callstring including the invokesite of the invokee. The top invokesite does not need to
* refer to an invoke instruction, and the referenced invoker method does not need to
* be the method containing the invoke to inline (e.g. if the invoke to inline has
* been inlined itself). However the callstring needs to match what the DFA expects.
* @param invokee the devirtualized invokee.
* @param analyzeCode if false, skip checking the code of the invokee.
* @return true if a nullpointer check code should be generated.
*/
public boolean needsNullpointerCheck(CallString callString, MethodInfo invokee, boolean analyzeCode) {
if (inlineConfig.skipNullpointerChecks())
return false;
InvokeSite invokeSite = callString.top();
// check if we have a 'this' reference anyway
if (invokeSite.isInvokeStatic() || invokeSite.isJVMCall()) {
return false;
}
// TODO check the DFA results if available
if (jcopter.useDFA()) {
} else if ("<init>".equals(invokee.getShortName())) {
// the NP check in this case (and hope that compilers for languages other than Java do the same..)
return false;
}
if (!analyzeCode) {
return true;
}
// check if the code will always throw an exception anyway (without producing any side effects before throwing)
ValueMapAnalysis analysis = new ValueMapAnalysis(invokee);
analysis.loadParameters();
InstructionList list = invokee.getCode().getInstructionList(true, false);
for (InstructionHandle ih : list.getInstructionHandles()) {
Instruction instr = ih.getInstruction();
if (instr instanceof ConstantPushInstruction || instr instanceof LocalVariableInstruction) {
analysis.transfer(instr);
} else if (instr instanceof GETFIELD || instr instanceof PUTFIELD || instr instanceof INVOKEVIRTUAL || instr instanceof INVOKEINTERFACE || instr instanceof INVOKESPECIAL) {
int down = instr.consumeStack(invokee.getConstantPoolGen());
ValueInfo value = analysis.getValueTable().top(down);
// the same way as the inlined invoke
if (value.isThisReference()) {
return false;
}
break;
} else {
// we ignore all other instructions (for now..)
break;
}
}
return true;
}
use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class InlineOptimizer method initialize.
@Override
public void initialize(AnalysisManager analyses, Collection<MethodInfo> roots) {
if (!preciseCycleEstimate) {
ExecutionContext dummy = new ExecutionContext(roots.iterator().next());
WCETProcessorModel pm = analyses.getJCopter().getWCETProcessorModel();
InstructionList il = new InstructionList();
// TODO very messy approximation of exec time
storeCycles = (int) pm.getExecutionTime(dummy, il.append(new ASTORE(10)));
checkNPCycles = 0;
checkNPCycles += (int) pm.getExecutionTime(dummy, il.append(new DUP()));
checkNPCycles += (int) pm.getExecutionTime(dummy, il.append(new IFNONNULL(il.append(new ATHROW()))));
deltaReturnCycles = (int) pm.getExecutionTime(dummy, il.append(new RETURN()));
deltaReturnCycles -= (int) pm.getExecutionTime(dummy, il.append(new GOTO(il.getEnd())));
}
countInvokeSites = 0;
countDevirtualized = 0;
}
use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class SimpleInliner method performSimpleInline.
/**
* Try to inline a simple getter, wrapper or stub method.
* <p>
* If the inlined code is again an invoke, the InvokeSite does not change because
* the InstructionHandle of the invoker's invoke is kept.</p>
*
* @param invokeSite the invoke to replace.
* @param invokee the method to inline.
* @param inlineData the parameters of the invokee and the code to inline.
* @return true if inlining has been performed.
*/
private InvokeSite performSimpleInline(InvokeSite invokeSite, MethodInfo invokee, InlineData inlineData) {
MethodInfo invoker = invokeSite.getInvoker();
MethodCode invokerCode = invoker.getCode();
if (logger.isDebugEnabled()) {
logger.debug("Inlining at " + invokeSite + " using " + invokee);
}
// Prepare code for the actual inlining
helper.prepareInlining(invoker, invokee);
InstructionHandle invoke = invokeSite.getInstructionHandle();
// Perform inlining: update the prologue
if (inlineData.getOldPrologueLength() > 0) {
InstructionHandle start = invoke;
for (int i = 0; i < inlineData.getOldPrologueLength(); i++) {
start = start.getPrev();
}
// invokeSite is not a target in this case, no need to worry about targets here
invokerCode.replace(start, inlineData.getOldPrologueLength(), inlineData.getPrologue(), false);
} else if (inlineData.getPrologue().getLength() > 0) {
// old-prologue is empty, invokeSite may be a target.. Need to update the targets to the new prologue
if (invoke.hasTargeters()) {
invokerCode.retarget(invoke, inlineData.getPrologue().getStart());
}
InstructionList il = invokerCode.getInstructionList();
il.insert(invoke, inlineData.getPrologue());
}
// Replace the invoke
MethodCode invokeeCode = invokee.getCode();
InstructionList il = invokeeCode.getInstructionList();
InstructionHandle start = invokeeCode.getInstructionHandle(inlineData.getInlineStart());
int cnt = il.getLength() - inlineData.getInlineStart();
if (il.getEnd().getInstruction() instanceof ReturnInstruction) {
// do not inline the return
cnt--;
}
InstructionHandle end = invokerCode.replace(invoke, 1, invokee, start, cnt, true);
// the invokee
if (cnt > 0) {
InstructionHandle ih = end;
for (int i = 0; i < cnt; i++) {
ih = ih.getPrev();
}
invokerCode.setLineNumber(ih, invokeeCode.getSourceClassInfo(start), invokeeCode.getLineNumber(start));
}
// insert epilogue
invokerCode.getInstructionList().insert(end, inlineData.getEpilogue());
// If we inlined another invokesite, find the new invokesite and return it
if (inlineData.getInvokeSite() != null) {
end = end.getPrev();
// search backwards from last inlined instruction
while (end != null) {
if (invokerCode.isInvokeSite(end)) {
return invokerCode.getInvokeSite(end);
}
end = end.getPrev();
}
}
return null;
}
Aggregations