use of org.apache.bcel.generic.ReturnInstruction in project jop by jop-devel.
the class SimpleInliner method analyzeCodeSize.
/**
* Check if the resulting code will not be larger than the older code.
* @param invokeSite the invokesite to inline.
* @param invokee the invoked method.
* @param inlineData the map to store the analyzer results
* @return true if the new code will not violate any size constrains
*/
private boolean analyzeCodeSize(InvokeSite invokeSite, MethodInfo invokee, InlineData inlineData) {
ProcessorModel pm = AppInfo.getSingleton().getProcessorModel();
MethodInfo invoker = invokeSite.getInvoker();
// delta = new prologue + inlined code + epilogue - old prologue - invokesite
int delta = 0;
InstructionHandle[] il = invokee.getCode().getInstructionList().getInstructionHandles();
InstructionHandle ih = il[inlineData.getInlineStart()];
while (ih != null) {
Instruction instr = ih.getInstruction();
if (instr instanceof ReturnInstruction) {
break;
}
delta += pm.getNumberOfBytes(invokee, instr);
ih = ih.getNext();
}
for (InstructionHandle instr : inlineData.getPrologue().getInstructionHandles()) {
delta += pm.getNumberOfBytes(invoker, instr.getInstruction());
}
for (InstructionHandle instr : inlineData.getEpilogue().getInstructionHandles()) {
delta += pm.getNumberOfBytes(invoker, instr.getInstruction());
}
ih = invokeSite.getInstructionHandle();
for (int i = 0; i <= inlineData.getOldPrologueLength(); i++) {
Instruction instr = ih.getInstruction();
delta -= pm.getNumberOfBytes(invoker, instr);
ih = ih.getPrev();
}
// TODO we could allow for some slack, especially if we decreased the codesize before..
return delta <= 0;
}
use of org.apache.bcel.generic.ReturnInstruction 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;
}
use of org.apache.bcel.generic.ReturnInstruction in project jop by jop-devel.
the class InstructionInterpreter method getInEdges.
private List<Edge> getInEdges(InstructionList il, InstructionHandle ih) {
List<Edge> edges = new LinkedList<Edge>();
InstructionHandle prev = ih.getPrev();
if (prev != null) {
// check if we can fall through from prev instruction
Instruction instr = prev.getInstruction();
if (!(instr instanceof UnconditionalBranch || instr instanceof Select || instr instanceof ReturnInstruction)) {
if (instr instanceof BranchInstruction) {
edges.add(new Edge(prev, ih, EdgeType.FALSE_EDGE));
} else {
edges.add(new Edge(prev, ih, EdgeType.NORMAL_EDGE));
}
}
}
// flow graph explicitly
for (InstructionHandle targeter = il.getStart(); targeter != null; targeter = targeter.getNext()) {
// for the instruction for the exception handler
if (!(targeter.getInstruction() instanceof BranchInstruction))
continue;
BranchInstruction bi = (BranchInstruction) targeter.getInstruction();
if (bi.containsTarget(ih)) {
edges.add(new Edge(targeter, ih, EdgeType.TRUE_EDGE));
}
}
return edges;
}
use of org.apache.bcel.generic.ReturnInstruction in project jop by jop-devel.
the class InstructionInterpreter method getOutEdges.
private List<Edge> getOutEdges(InstructionHandle ih) {
List<Edge> edges = new LinkedList<Edge>();
Instruction instr = ih.getInstruction();
if (instr instanceof BranchInstruction) {
if (instr instanceof Select) {
Select s = (Select) instr;
InstructionHandle[] target = s.getTargets();
for (InstructionHandle aTarget : target) {
edges.add(new Edge(ih, aTarget, EdgeType.TRUE_EDGE));
}
edges.add(new Edge(ih, s.getTarget(), EdgeType.FALSE_EDGE));
} else {
BranchInstruction b = (BranchInstruction) instr;
edges.add(new Edge(ih, b.getTarget(), EdgeType.TRUE_EDGE));
}
}
// Check if we can fall through to the next instruction
if (ih.getNext() != null && !(instr instanceof UnconditionalBranch || instr instanceof Select || instr instanceof ReturnInstruction)) {
if (instr instanceof BranchInstruction) {
edges.add(new Edge(ih, ih.getNext(), EdgeType.FALSE_EDGE));
} else {
edges.add(new Edge(ih, ih.getNext(), EdgeType.NORMAL_EDGE));
}
}
if (instr instanceof ReturnInstruction) {
edges.add(new Edge(ih, getExitInstruction(), EdgeType.EXIT_EDGE));
}
if (instr instanceof ATHROW) {
// TODO should we handle this somehow? Insert edges to the exception handlers or to an return-by-exception
// exit instruction?
// for now, just ignore them
}
// but for now, we just ignore them too.. in a safe way :)
if (instr instanceof RET || instr instanceof JSR || instr instanceof JSR_W) {
throw new JavaClassFormatError("Unsupported instruction " + instr + " in " + methodInfo);
}
return edges;
}
use of org.apache.bcel.generic.ReturnInstruction in project jop by jop-devel.
the class DFATool method loadMethod.
private void loadMethod(MethodInfo method) {
MethodCode mcode = method.getCode();
// TODO is there a better way to get an instruction handle? Do we need to keep the list somehow?
InstructionHandle exit;
exit = (InstructionHandle) method.getCustomValue(KEY_NOP);
// we reuse the NOP if it exists, so that we can have multiple DFAs running at the same time
if (exit == null) {
exit = new InstructionList(new NOP()).getStart();
// We do not really want to modify the REAL instruction list and append exit
// (SH) Fixed :) Yep, we need the NOP somewhere, else doInvoke() will collect the wrong result state.
// But we can eliminate the NOP by adding the instruction not to the list, but instead to the
// MethodInfo, and also retrieve it from there.
method.setCustomValue(KEY_NOP, exit);
}
this.getStatements().add(exit);
// We do not modify the code, so we leave existing CFGs alone, just make sure the instruction list is uptodate
InstructionList il = mcode.getInstructionList(true, false);
// we need correct positions for the DFA cache serialization stuff
il.setPositions();
for (Iterator<?> l = il.iterator(); l.hasNext(); ) {
InstructionHandle handle = (InstructionHandle) l.next();
this.getStatements().add(handle);
Instruction instr = handle.getInstruction();
if (instr instanceof BranchInstruction) {
if (instr instanceof Select) {
Select s = (Select) instr;
InstructionHandle[] target = s.getTargets();
for (InstructionHandle aTarget : target) {
this.getFlow().addEdge(new FlowEdge(handle, aTarget, FlowEdge.TRUE_EDGE));
}
this.getFlow().addEdge(new FlowEdge(handle, s.getTarget(), FlowEdge.FALSE_EDGE));
} else {
BranchInstruction b = (BranchInstruction) instr;
this.getFlow().addEdge(new FlowEdge(handle, b.getTarget(), FlowEdge.TRUE_EDGE));
}
}
if (handle.getNext() != null && !(instr instanceof UnconditionalBranch || instr instanceof Select || instr instanceof ReturnInstruction)) {
if (instr instanceof BranchInstruction) {
this.getFlow().addEdge(new FlowEdge(handle, handle.getNext(), FlowEdge.FALSE_EDGE));
} else {
this.getFlow().addEdge(new FlowEdge(handle, handle.getNext(), FlowEdge.NORMAL_EDGE));
}
}
if (instr instanceof ReturnInstruction) {
this.getFlow().addEdge(new FlowEdge(handle, exit, FlowEdge.NORMAL_EDGE));
}
}
}
Aggregations