use of org.apache.bcel.generic.Instruction 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.Instruction in project jop by jop-devel.
the class MethodCode method replace.
/**
* Replace instructions in this code with an instruction list or a part of it.
* If the number of instructions to replace differs from the number of source instructions, instruction
* handles will be removed or inserted appropriately and the targets will be updated.
* <p>
* Instruction handles will be reused, so attached values and targets will not be lost if the new length is not
* shorter than the old length. Else instruction handles are removed and the targeters to removed instructions
* are updated to the instruction after the next instruction after the deleted instructions.
* </p>
*
* @param replaceStart the first instruction in this code to replace
* @param replaceCount the number of instructions in this code to replace
* @param sourceInfo the MethodInfo containing the source instruction. If non-null, the instructions will be copied
* using the constant pool from the given MethodInfo. If null, the instructions will not be copied.
* @param sourceStart the first instruction in the source list to use for replacing the code.
* @param sourceCount the number of instructions to use from the source.
* @param copyCustomValues if true copy the custom values from the source.
* @return the first handle in the target list after the inserted code, or null if the last instruction in this
* list has been replaced.
*/
public InstructionHandle replace(InstructionHandle replaceStart, int replaceCount, MethodInfo sourceInfo, InstructionHandle sourceStart, int sourceCount, boolean copyCustomValues) {
InstructionList il = getInstructionList();
InstructionHandle current = replaceStart;
InstructionHandle currSource = sourceStart;
// update the common prefix
int cnt = Math.min(replaceCount, sourceCount);
for (int i = 0; i < cnt; i++) {
Instruction instr;
if (sourceInfo != null) {
instr = copyFrom(sourceInfo.getClassInfo(), currSource.getInstruction());
} else {
instr = currSource.getInstruction();
}
// TODO support branch instructions! need to replace the IH too
current.setInstruction(instr);
if (copyCustomValues) {
copyCustomValues(sourceInfo, current, currSource);
}
current = current.getNext();
currSource = currSource.getNext();
}
InstructionHandle next = current;
// Case 1: delete unused handles, update targets to next instruction
if (replaceCount > sourceCount) {
int rest = replaceCount - sourceCount;
for (int i = 1; i < rest; i++) {
next = next.getNext();
}
InstructionHandle end = next;
next = next.getNext();
try {
// we cannot use next.getPrev, since next might be null
il.delete(current, end);
} catch (TargetLostException e) {
retarget(e, next);
}
}
// Case 2: insert new handles for rest of source
if (replaceCount < sourceCount) {
int rest = sourceCount - replaceCount;
for (int i = 0; i < rest; i++) {
Instruction instr;
if (sourceInfo != null) {
instr = copyFrom(sourceInfo.getClassInfo(), currSource.getInstruction());
} else {
instr = currSource.getInstruction();
}
if (next == null) {
current = il.append(instr);
} else {
current = il.insert(next, instr);
}
if (copyCustomValues) {
copyCustomValues(sourceInfo, current, currSource);
}
currSource = currSource.getNext();
}
}
return next;
}
use of org.apache.bcel.generic.Instruction in project jop by jop-devel.
the class MethodCode method copyFrom.
/**
* Create a copy of an instruction and if it uses the constantpool, copy and update the constantpool
* reference too.
* <p>Note that branch targets are not updated, so they will most likely be incorrect and need to be updated
* manually.</p> d
*
* @param sourceClass the class containing the constantpool the instruction uses.
* @param instruction the instruction to copy
* @return a new copy of the instruction.
*/
public Instruction copyFrom(ClassInfo sourceClass, Instruction instruction) {
Instruction newInstr = instruction.copy();
if (instruction instanceof CPInstruction) {
int oldIndex = ((CPInstruction) instruction).getIndex();
int newIndex = getClassInfo().addConstantInfo(sourceClass.getConstantInfo(oldIndex));
((CPInstruction) newInstr).setIndex(newIndex);
}
return newInstr;
}
use of org.apache.bcel.generic.Instruction in project jop by jop-devel.
the class ReplaceAtomicAnnotation method getModifiedArguments.
protected static SortedSet<Integer> getModifiedArguments(MethodGen method) {
SortedSet<Integer> result = new TreeSet<Integer>();
int arguments = getArgsCount(method);
for (Instruction in : method.getInstructionList().getInstructions()) {
if (in instanceof IndexedInstruction) {
IndexedInstruction i = (IndexedInstruction) in;
if (i.getIndex() < arguments) {
if (i instanceof DSTORE || i instanceof LSTORE) {
result.add(i.getIndex());
result.add(i.getIndex() + 1);
} else if (i instanceof StoreInstruction || i instanceof IINC) {
result.add(i.getIndex());
}
}
}
}
return result;
}
use of org.apache.bcel.generic.Instruction 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