use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class DFATool method runAnalysis.
@SuppressWarnings("unchecked")
public Map runAnalysis(Analysis analysis) {
/* use cached results if possible */
Map results;
if ((results = getCachedResults(analysis)) != null) {
logger.warn("Analysis " + analysis.getId() + ": Using cached DFA analysis results");
return results;
}
Interpreter interpreter = new Interpreter(analysis, this);
MethodInfo main = appInfo.getMainMethod();
MethodInfo prologue = main.getClassInfo().getMethodInfo(prologueName + prologueSig);
Context context = new Context();
context.stackPtr = 0;
context.syncLevel = 0;
context.setMethodInfo(prologue);
analysis.initialize(main, context);
InstructionHandle entry = prologue.getCode().getInstructionList().getStart();
interpreter.interpret(context, entry, new LinkedHashMap(), true);
/* cache results if requested */
writeCachedResults(analysis);
return analysis.getResult();
}
use of org.apache.bcel.generic.InstructionHandle 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.InstructionHandle in project jop by jop-devel.
the class CallStringReceiverTypes method doInvokeVirtual.
private void doInvokeVirtual(String receiver, MethodInfo method, InstructionHandle stmt, Context context, ContextMap<CallString, Set<TypeMapping>> input, Interpreter<CallString, Set<TypeMapping>> interpreter, Map<InstructionHandle, ContextMap<CallString, Set<TypeMapping>>> state, ContextMap<CallString, Set<TypeMapping>> result) {
String methodImplName = method.getClassName() + "." + method.getMethodSignature();
recordReceiver(stmt, context, methodImplName);
// LineNumberTable lines = p.getMethods().get(context.method).getLineNumberTable(context.constPool);
// int sourceLine = lines.getSourceLine(stmt.getPosition());
// String invokeId = context.method+"\t"+":"+sourceLine+"."+stmt.getPosition();
// set up new context
int varPtr = context.stackPtr - MethodHelper.getArgSize(method);
Context c = new Context(context);
c.stackPtr = method.getCode().getMaxLocals();
if (method.isSynchronized()) {
c.syncLevel = context.syncLevel + 1;
}
c.setMethodInfo(method);
c.callString = c.callString.push(context.getMethodInfo(), stmt, callStringLength);
boolean threaded = false;
DFATool p = interpreter.getDFATool();
if (p.getAppInfo().getClassInfo(receiver).isSubclassOf(p.getAppInfo().getClassInfo("joprt.RtThread")) && "run()V".equals(method.getMethodSignature())) {
c.createThread();
threaded = true;
}
// carry only minimal information with call
Set<TypeMapping> in = input.get(context.callString);
Set<TypeMapping> out = new LinkedHashSet<TypeMapping>();
ContextMap<CallString, Set<TypeMapping>> tmpresult = new ContextMap<CallString, Set<TypeMapping>>(c, new LinkedHashMap<CallString, Set<TypeMapping>>());
tmpresult.put(c.callString, out);
for (TypeMapping m : in) {
if (m.stackLoc < 0) {
out.add(m);
}
if (m.stackLoc > varPtr) {
out.add(new TypeMapping(m.stackLoc - varPtr, m.type));
}
if (m.stackLoc == varPtr) {
// add "this"
ClassInfo staticClass = p.getAppInfo().getClassInfo(receiver);
ClassInfo dynamicClass = null;
try {
dynamicClass = p.getAppInfo().getClassInfo(m.type.split("@")[0]);
} catch (MissingClassError ex) {
logger.error("doInvokeVirtual - trying to improve type of " + staticClass + ": " + ex);
// TODO: maybe we should throw an exception/error instead?
}
if (dynamicClass != null && dynamicClass.isSubclassOf(staticClass)) {
out.add(new TypeMapping(0, m.type));
}
}
}
InstructionHandle entry = p.getEntryHandle(method);
state.put(entry, join(state.get(entry), tmpresult));
// interpret method
Map<InstructionHandle, ContextMap<CallString, Set<TypeMapping>>> r = interpreter.interpret(c, entry, state, false);
// pull out relevant information from call
InstructionHandle exit = p.getExitHandle(method);
if (r.get(exit) != null) {
Set<TypeMapping> returned = r.get(exit).get(c.callString);
if (returned != null) {
filterReturnSet(returned, result.get(context.callString), varPtr);
}
}
// update all threads
if (threaded) {
threads.put(methodImplName, new ContextMap<CallString, Set<TypeMapping>>(c, result));
updateThreads(result, interpreter, state);
}
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class LoopBounds method copyResults.
@Override
public void copyResults(MethodInfo newContainer, Map<InstructionHandle, InstructionHandle> newHandles) {
for (Map.Entry<InstructionHandle, InstructionHandle> entry : newHandles.entrySet()) {
InstructionHandle oldHandle = entry.getKey();
InstructionHandle newHandle = entry.getValue();
if (newHandle == null)
continue;
// TODO support updating the callstrings too
// TODO this does NOT update stackPtr,.. in the new context!
ContextMap<CallString, Pair<ValueMapping, ValueMapping>> value = bounds.get(oldHandle);
if (value != null)
bounds.put(newHandle, value.copy(newContainer));
ContextMap<CallString, Interval> value1 = arrayIndices.get(oldHandle);
if (value1 != null)
arrayIndices.put(newHandle, value1.copy(newContainer));
ContextMap<CallString, Integer> value2 = scopes.get(oldHandle);
if (value2 != null)
scopes.put(newHandle, value2.copy(newContainer));
ContextMap<CallString, Interval[]> value3 = sizes.get(oldHandle);
if (value3 != null)
sizes.put(newHandle, value3.copy(newContainer));
ContextMap<CallString, Set<FlowEdge>> old = infeasibles.get(oldHandle);
if (old != null) {
Map<CallString, Set<FlowEdge>> map = new LinkedHashMap<CallString, Set<FlowEdge>>(old.size());
for (CallString cs : old.keySet()) {
Set<FlowEdge> newSet = new LinkedHashSet<FlowEdge>();
for (FlowEdge edge : old.get(cs)) {
InstructionHandle newHead = newHandles.get(edge.getHead());
InstructionHandle newTail = newHandles.get(edge.getTail());
if (newHead != null && newTail != null) {
Context ctx = new Context(edge.getContext());
ctx.setMethodInfo(newContainer);
newSet.add(new FlowEdge(newTail, newHead, edge.getType(), ctx));
}
}
map.put(cs, newSet);
}
Context c = old.getContext();
c.setMethodInfo(newContainer);
ContextMap<CallString, Set<FlowEdge>> edges = new ContextMap<CallString, Set<FlowEdge>>(c, map);
infeasibles.put(newHandle, edges);
}
}
}
use of org.apache.bcel.generic.InstructionHandle in project jop by jop-devel.
the class AnalysisResultSerialization method toContextMapResult.
public <T> Map<InstructionHandle, ContextMap<CallString, T>> toContextMapResult(AppInfo appInfo, Serializer<T, R> serializer) throws MethodNotFoundException, IOException, ClassNotFoundException {
/* `context' is a really bad hack in the DFA. In the deserialization,
* we guarantee that context.getMethodInfo() and context.callstring are correct,
* but the rest of context is undefined.
*/
Context currentContext;
Map<InstructionHandle, ContextMap<CallString, T>> resultMap = new LinkedHashMap<InstructionHandle, ContextMap<CallString, T>>();
for (Entry<String, Map<CallStringSerialization, Map<Integer, R>>> miEntry : serializedResults.entrySet()) {
MethodInfo mi = appInfo.getMethodInfo(MemberID.parse(miEntry.getKey()));
for (Entry<CallStringSerialization, Map<Integer, R>> csEntry : miEntry.getValue().entrySet()) {
CallString cs = csEntry.getKey().getCallString(appInfo);
currentContext = new Context();
currentContext.setMethodInfo(mi);
currentContext.callString = cs;
for (Entry<Integer, R> posEntry : csEntry.getValue().entrySet()) {
int pos = posEntry.getKey();
R value = posEntry.getValue();
InstructionHandle instr = mi.getCode().getInstructionList(false, false).findHandle(pos);
ContextMap<CallString, T> ctxMap = resultMap.get(instr);
if (ctxMap == null) {
ctxMap = new ContextMap<CallString, T>(currentContext, new LinkedHashMap<CallString, T>());
resultMap.put(instr, ctxMap);
}
if (serializer == null) {
ctxMap.put(cs, (T) value);
} else {
T origValue = serializer.fromSerializedRepresentation(value, appInfo);
ctxMap.put(cs, origValue);
}
}
}
}
return resultMap;
}
Aggregations