use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class CFGCallgraphBuilder method findInvokeSites.
@Override
protected Set<InvokeSite> findInvokeSites(MethodCode code) {
ControlFlowGraph cfg = code.getControlFlowGraph(false);
Set<InvokeSite> invokeSites = new LinkedHashSet<InvokeSite>();
// Basic blocks however are not removed from the block list..
for (CFGNode node : cfg.vertexSet()) {
BasicBlock bb = node.getBasicBlock();
if (bb == null)
continue;
// but hey, invokeSites is a set anyway..
for (InstructionHandle ih : bb.getInstructions()) {
if (code.isInvokeSite(ih)) {
invokeSites.add(code.getInvokeSite(ih));
}
}
}
return invokeSites;
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class ReplaceNativeAndCPIdx method replace.
private Method replace(Method method) {
MethodGen mg = new MethodGen(method, clazz.getClassName(), cpoolgen);
InstructionList il = mg.getInstructionList();
InstructionFinder f = new InstructionFinder(il);
String methodId = method.getName() + method.getSignature();
OldMethodInfo mi = getCli().getMethodInfo(methodId);
// find invokes first and replace call to Native by
// JOP native instructions.
String invokeStr = "InvokeInstruction";
for (Iterator i = f.search(invokeStr); i.hasNext(); ) {
InstructionHandle[] match = (InstructionHandle[]) i.next();
InstructionHandle first = match[0];
InvokeInstruction ii = (InvokeInstruction) first.getInstruction();
if (ii.getClassName(cpoolgen).equals(JOPizer.nativeClass)) {
short opid = (short) JopInstr.getNative(ii.getMethodName(cpoolgen));
if (opid == -1) {
System.err.println(method.getName() + ": cannot locate " + ii.getMethodName(cpoolgen) + ". Replacing with NOP.");
first.setInstruction(new NOP());
} else {
first.setInstruction(new NativeInstruction(opid, (short) 1));
((JOPizer) ai).outTxt.println("\t" + first.getPosition());
// then we remove pc+2 and pc+1 from the MGCI info
if (JOPizer.dumpMgci) {
il.setPositions();
int pc = first.getPosition();
// important: take the high one first
GCRTMethodInfo.removePC(pc + 2, mi);
GCRTMethodInfo.removePC(pc + 1, mi);
}
}
}
if (ii instanceof INVOKESPECIAL) {
// not an initializer
if (!ii.getMethodName(cpoolgen).equals("<init>")) {
// check if this is a super invoke
// TODO this is just a hack, use InvokeSite.isInvokeSuper() when this is ported to the new framework!
boolean isSuper = false;
String declaredType = ii.getClassName(cpoolgen);
JopClassInfo cls = getCli();
OldClassInfo superClass = cls.superClass;
while (superClass != null) {
if (superClass.clazz.getClassName().equals(declaredType)) {
isSuper = true;
break;
}
if ("java.lang.Object".equals(superClass.clazz.getClassName())) {
break;
}
superClass = superClass.superClass;
}
if (isSuper) {
Integer idx = ii.getIndex();
int new_index = getCli().cpoolUsed.indexOf(idx) + 1;
first.setInstruction(new JOPSYS_INVOKESUPER((short) new_index));
// System.err.println("invokesuper "+ii.getClassName(cpoolgen)+"."+ii.getMethodName(cpoolgen));
}
}
}
}
if (JOPizer.CACHE_INVAL) {
f = new InstructionFinder(il);
// find volatile reads and insert cache invalidation bytecode
String fieldInstr = "GETFIELD|GETSTATIC|PUTFIELD|PUTSTATIC";
for (Iterator i = f.search(fieldInstr); i.hasNext(); ) {
InstructionHandle[] match = (InstructionHandle[]) i.next();
InstructionHandle ih = match[0];
FieldInstruction fi = (FieldInstruction) ih.getInstruction();
JavaClass jc = JOPizer.jz.cliMap.get(fi.getClassName(cpoolgen)).clazz;
Field field = null;
while (field == null) {
Field[] fields = jc.getFields();
for (int k = 0; k < fields.length; k++) {
if (fields[k].getName().equals(fi.getFieldName(cpoolgen))) {
field = fields[k];
break;
}
}
if (field == null) {
try {
jc = jc.getSuperClass();
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new Error();
}
}
}
if (field.isVolatile()) {
if (field.getType().getSize() < 2) {
if (fi instanceof GETFIELD || fi instanceof GETSTATIC) {
ih.setInstruction(new InvalidateInstruction());
ih = il.append(ih, fi);
}
} else {
// this only works because we do not throw a
// NullPointerException for monitorenter/-exit!
ih.setInstruction(new ACONST_NULL());
ih = il.append(ih, new MONITORENTER());
ih = il.append(ih, fi);
ih = il.append(ih, new ACONST_NULL());
ih = il.append(ih, new MONITOREXIT());
}
}
}
}
f = new InstructionFinder(il);
// find instructions that access the constant pool
// and replace the index by the new value from ClassInfo
String cpInstr = "CPInstruction";
for (Iterator it = f.search(cpInstr); it.hasNext(); ) {
InstructionHandle[] match = (InstructionHandle[]) it.next();
InstructionHandle ih = match[0];
CPInstruction cpii = (CPInstruction) ih.getInstruction();
int index = cpii.getIndex();
// we have to grab the information before we change
// the CP index.
FieldInstruction fi = null;
Type ft = null;
if (cpii instanceof FieldInstruction) {
fi = (FieldInstruction) ih.getInstruction();
ft = fi.getFieldType(cpoolgen);
}
Integer idx = new Integer(index);
// pos is the new position in the reduced constant pool
// idx is the position in the 'original' unresolved cpool
int pos = getCli().cpoolUsed.indexOf(idx);
int new_index = pos + 1;
// and putfield and by address for getstatic and putstatic
if (cpii instanceof GETFIELD || cpii instanceof PUTFIELD || cpii instanceof GETSTATIC || cpii instanceof PUTSTATIC) {
// we use the offset instead of the CP index
new_index = getFieldOffset(cp, index);
} else {
if (pos == -1) {
System.out.println("Error: constant " + index + " " + cpoolgen.getConstant(index) + " not found");
System.out.println("new cpool: " + getCli().cpoolUsed);
System.out.println("original cpool: " + cpoolgen);
System.exit(-1);
}
}
// set new index, position starts at
// 1 as cp points to the length of the pool
cpii.setIndex(new_index);
if (cpii instanceof FieldInstruction) {
boolean isRef = ft instanceof ReferenceType;
boolean isLong = ft == BasicType.LONG || ft == BasicType.DOUBLE;
if (fi instanceof GETSTATIC) {
if (isRef) {
ih.setInstruction(new GETSTATIC_REF((short) new_index));
} else if (isLong) {
ih.setInstruction(new GETSTATIC_LONG((short) new_index));
}
} else if (fi instanceof PUTSTATIC) {
if (isRef) {
if (!com.jopdesign.build.JOPizer.USE_RTTM) {
ih.setInstruction(new PUTSTATIC_REF((short) new_index));
}
} else if (isLong) {
ih.setInstruction(new PUTSTATIC_LONG((short) new_index));
}
} else if (fi instanceof GETFIELD) {
if (isRef) {
ih.setInstruction(new GETFIELD_REF((short) new_index));
} else if (isLong) {
ih.setInstruction(new GETFIELD_LONG((short) new_index));
}
} else if (fi instanceof PUTFIELD) {
if (isRef) {
if (!com.jopdesign.build.JOPizer.USE_RTTM) {
ih.setInstruction(new PUTFIELD_REF((short) new_index));
}
} else if (isLong) {
ih.setInstruction(new PUTFIELD_LONG((short) new_index));
}
}
}
}
Method m = mg.getMethod();
il.dispose();
return m;
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class MethodCode method getLineNumber.
/**
* Get the line number of the instruction. This may refer to a line number in another file.
* To get the correct source file for this instruction, use {@link #getSourceFileName(InstructionHandle)}.
*
* @see #getSourceFileName(InstructionHandle)
* @param ih the instruction to check.
* @return the line number of the instruction, or -1 if unknown.
*/
public int getLineNumber(InstructionHandle ih) {
InstructionHandle handle = findLineNumberHandle(ih);
if (handle == null)
return -1;
Integer line = (Integer) handle.getAttribute(KEY_LINENUMBER);
if (line != null) {
return line;
}
LineNumberGen entry = getLineNumberEntry(handle, false);
return entry != null ? entry.getSourceLine() : -1;
}
use of org.apache.bcel.generic.InstructionHandle 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.InstructionHandle in project jop by jop-devel.
the class MethodCode method getLineString.
public String getLineString(InstructionHandle ih) {
InstructionHandle handle = findLineNumberHandle(ih);
if (handle == null) {
return "<none>";
}
String className = getSourceClassAttribute(handle);
if (className != null) {
return className + ":" + getLineNumber(handle);
}
LineNumberGen lg = getLineNumberEntry(handle, false);
return String.valueOf(lg.getSourceLine());
}
Aggregations