use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class ReplaceIinc method replace.
private void replace(MethodInfo method) {
MethodCode mc = method.getCode();
InstructionList il = mc.getInstructionList();
InstructionFinder f = new InstructionFinder(il);
for (Iterator i = f.search("IINC"); i.hasNext(); ) {
InstructionHandle[] match = (InstructionHandle[]) i.next();
InstructionHandle ih = match[0];
IINC ii = (IINC) ih.getInstruction();
int idx = ii.getIndex();
int inc = ii.getIncrement();
// IINC rep = new IINC(idx, inc);
ih.setInstruction(new ILOAD(idx));
if (inc >= -1 && inc <= 5) {
ih = il.append(ih, new ICONST(inc));
} else if (inc >= -128 && inc < 127) {
ih = il.append(ih, new BIPUSH((byte) inc));
} else if (inc >= -32768 && inc < 32767) {
ih = il.append(ih, new SIPUSH((short) inc));
} else {
System.out.println("IINC constant too big");
System.exit(-1);
}
ih = il.append(ih, new IADD());
ih = il.append(ih, new ISTORE(idx));
}
method.compile();
}
use of org.apache.bcel.generic.InstructionList 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));
}
}
}
use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class SimpleInliner method analyzeInvokee.
/**
* @param cs the callstring from the invoker to the invoke to inline (if recursive). Used to check DFA results.
* @param invokee the invoked method to analyze
* @param inlineData the map to populate with the parameters and the instructions to inline.
* @return true if inlining is possible
*/
private boolean analyzeInvokee(CallString cs, MethodInfo invokee, InlineData inlineData) {
// we allow loading of parameters, loading of constants, some instruction, and a return
ValueMapAnalysis values = new ValueMapAnalysis(invokee);
values.loadParameters();
InstructionList il = invokee.getCode().getInstructionList(true, false);
InstructionHandle ih = il.getStart();
// we should at least have a return instruction, so even for empty methods we should fall through
// generate the parameter mapping
int count = 0;
while (true) {
Instruction instruction = ih.getInstruction();
if (instruction instanceof PushInstruction || instruction instanceof NOP) {
values.transfer(instruction);
ih = ih.getNext();
count++;
} else {
break;
}
}
// store the mapping
for (ValueInfo value : values.getValueTable().getStack()) {
inlineData.addParam(value);
}
inlineData.setInlineStart(count);
// if we do not need an NP check, we can also inline code which does not throw an exception in the same way
boolean needsNPCheck = helper.needsNullpointerCheck(cs, invokee, false);
boolean hasNPCheck = false;
// we allow up to 5 instructions and one return before assuming that the resulting code will be too large
for (int i = 0; i < 6; i++) {
// now lets see what we have here as non-push instructions
Instruction instruction = ih.getInstruction();
if (instruction instanceof InvokeInstruction) {
if (inlineData.getInvokeSite() != null) {
// only inline at most one invoke
return false;
}
InvokeSite is = invokee.getCode().getInvokeSite(ih);
inlineData.setInvokeSite(is);
hasNPCheck |= !is.isInvokeStatic();
} else if (instruction instanceof FieldInstruction) {
if (instruction instanceof GETFIELD) {
hasNPCheck |= values.getValueTable().top().isThisReference();
}
if (instruction instanceof PUTFIELD) {
int down = values.getValueTable().top().isContinued() ? 2 : 1;
hasNPCheck |= values.getValueTable().top(down).isThisReference();
}
} else if (instruction instanceof ArithmeticInstruction || instruction instanceof ConversionInstruction || instruction instanceof StackInstruction || instruction instanceof LDC || instruction instanceof LDC2_W || instruction instanceof ARRAYLENGTH || instruction instanceof CHECKCAST || instruction instanceof NOP) {
// nothing to do, just copy them
} else if (instruction instanceof ReturnInstruction) {
if (needsNPCheck && !hasNPCheck) {
// We were nearly finished.. but NP check test failed
this.requiresNPCheck++;
if (logger.isTraceEnabled()) {
logger.trace("Not inlining " + invokee + " because it requires a NP check.");
}
return false;
}
// else we need to add pop instructions
if (instruction instanceof RETURN) {
// we do not return anything, so we must empty the stack
while (values.getValueTable().getStackSize() > 0) {
Instruction pop;
if (values.getValueTable().top().isContinued()) {
pop = new POP2();
} else {
pop = new POP();
}
inlineData.addEpilogue(pop);
values.transfer(pop);
}
return true;
} else {
Type type = ((ReturnInstruction) instruction).getType();
// javac anyway)
return values.getValueTable().getStackSize() == type.getSize();
}
} else {
// if we encounter an instruction which we do not handle, we do not inline
unhandledInstructions++;
if (logger.isTraceEnabled()) {
logger.trace("Not inlining " + invokee + " because of unhandled instruction " + instruction.toString(invokee.getClassInfo().getConstantPoolGen().getConstantPool()));
}
return false;
}
// update the stack map since we need it to handle RETURN
values.transfer(instruction);
ih = ih.getNext();
}
// too many instructions, do not inline
return false;
}
use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class PeepholeOptimizer method optimizeMethod.
@Override
public void optimizeMethod(MethodInfo method) {
InstructionList il = method.getCode().getInstructionList();
// BCEL Example optimization
optimizeBoolExpressions(il);
}
use of org.apache.bcel.generic.InstructionList in project jop by jop-devel.
the class HashTest method main.
public static void main(String[] args) {
TestFramework test = new TestFramework();
AppSetup setup = test.setupAppSetup();
AppInfo appInfo = test.setupAppInfo("common.code.HashTest", false);
ClassInfo testClass = appInfo.loadClass("common.TestFramework");
MethodInfo mainMethod = appInfo.getMainMethod();
MethodCode code = mainMethod.getCode();
InstructionHandle[] ih = code.getInstructionList().getInstructionHandles();
InvokeSite i1 = code.getInvokeSite(ih[1]);
InvokeSite i2 = code.getInvokeSite(ih[2]);
InvokeSite i3 = code.getInvokeSite(ih[3]);
InvokeSite i11 = code.getInvokeSite(ih[1]);
check(i1 == i11);
CallString c1 = new CallString(i1);
CallString c2 = new CallString(i2);
CallString c11 = new CallString(i1);
check(c1.equals(c11));
check(!c1.equals(c2));
ExecutionContext e1 = new ExecutionContext(mainMethod, c1);
ExecutionContext e2 = new ExecutionContext(mainMethod, c2);
ExecutionContext e11 = new ExecutionContext(mainMethod, c11);
check(e1.equals(e11));
check(!e1.equals(e2));
// TODO put stuff into maps, check contains() and get()
// modify instruction list, check if everything still works
InstructionList il = code.getInstructionList();
il.insert(new ILOAD(0));
il.insert(ih[2], new ILOAD(1));
ih = il.getInstructionHandles();
InvokeSite i12 = code.getInvokeSite(ih[2]);
InvokeSite i22 = code.getInvokeSite(ih[4]);
check(i12 == i1);
check(i22 == i2);
check(e1.equals(e11));
check(!e1.equals(e2));
il.setPositions();
check(c1.equals(c11));
check(!c1.equals(c2));
check(e1.equals(e11));
check(!e1.equals(e2));
}
Aggregations