new context selector that just checks for recursion instead of bounding it
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4509 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
0d0d2b89a9
commit
d1974d8b54
|
@ -16,6 +16,7 @@ import com.ibm.wala.cast.js.ipa.callgraph.ForInContextSelector;
|
|||
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptFunctionDotCallTargetSelector;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.RecursionBoundContextSelector;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.RecursionCheckContextSelector;
|
||||
import com.ibm.wala.cast.js.ipa.callgraph.correlations.extraction.CorrelatedPairExtractorFactory;
|
||||
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil;
|
||||
import com.ibm.wala.cast.js.test.JSCallGraphBuilderUtil.CGBuilderType;
|
||||
|
@ -92,7 +93,8 @@ public class HTMLCGBuilder {
|
|||
// the code below belongs somewhere else!!!
|
||||
// the bound of 4 is what is needed to pass our current framework tests
|
||||
if (AstTranslator.NEW_LEXICAL) {
|
||||
builder.setContextSelector(new RecursionBoundContextSelector(builder.getContextSelector(), 4));
|
||||
// builder.setContextSelector(new RecursionBoundContextSelector(builder.getContextSelector(), 4));
|
||||
builder.setContextSelector(new RecursionCheckContextSelector(builder.getContextSelector()));
|
||||
}
|
||||
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor());
|
||||
if (timeout > 0) {
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package com.ibm.wala.cast.js.ipa.callgraph;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import com.ibm.wala.analysis.reflection.InstanceKeyWithNode;
|
||||
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys.ScopeMappingInstanceKey;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.ContextKey;
|
||||
import com.ibm.wala.ipa.callgraph.ContextSelector;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey.SingleInstanceFilter;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
|
||||
/**
|
||||
* ensures that no contexts returned by a base context selector are recursive
|
||||
* (assertion failure otherwise)
|
||||
*/
|
||||
public class RecursionCheckContextSelector implements ContextSelector {
|
||||
|
||||
private final ContextSelector base;
|
||||
|
||||
|
||||
/**
|
||||
* the highest parameter index that we'll check . this is a HACK. ideally,
|
||||
* given a context, we'd have some way to know all the {@link ContextKey}s
|
||||
* that it knows about.
|
||||
*
|
||||
* @see ContextKey#PARAMETERS
|
||||
*/
|
||||
private static final int MAX_INTERESTING_PARAM = 5;
|
||||
|
||||
public RecursionCheckContextSelector(ContextSelector base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) {
|
||||
Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters);
|
||||
assert !recursiveContext(baseContext, callee);
|
||||
return baseContext;
|
||||
}
|
||||
|
||||
private boolean recursiveContext(Context baseContext, IMethod callee) {
|
||||
LinkedList<Pair<Context,Collection<IMethod>>> worklist = new LinkedList<Pair<Context,Collection<IMethod>>>();
|
||||
worklist.push(Pair.make(baseContext, (Collection<IMethod>)Collections.singleton(callee)));
|
||||
while (!worklist.isEmpty()) {
|
||||
Pair<Context, Collection<IMethod>> p = worklist.removeFirst();
|
||||
Context curContext = p.fst;
|
||||
Collection<IMethod> curEncountered = p.snd;
|
||||
// we just do a case analysis here. we might have to add cases later to
|
||||
// account for new types of context / recursion.
|
||||
CGNode callerNode = (CGNode) curContext.get(ContextKey.CALLER);
|
||||
if (callerNode != null) {
|
||||
if (!updateForNode(baseContext, curEncountered, worklist, callerNode)) {
|
||||
System.err.println("callee " + callee);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < MAX_INTERESTING_PARAM; i++) {
|
||||
FilteredPointerKey.SingleInstanceFilter filter = (SingleInstanceFilter) curContext.get(ContextKey.PARAMETERS[i]);
|
||||
if (filter != null) {
|
||||
InstanceKey ik = filter.getInstance();
|
||||
if (ik instanceof ScopeMappingInstanceKey) {
|
||||
ik = ((ScopeMappingInstanceKey) ik).getBase();
|
||||
}
|
||||
if (ik instanceof InstanceKeyWithNode) {
|
||||
CGNode node = ((InstanceKeyWithNode)ik).getNode();
|
||||
if (!updateForNode(baseContext, curEncountered, worklist, node)) {
|
||||
System.err.println("callee " + callee);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean updateForNode(Context baseContext, Collection<IMethod> curEncountered, LinkedList<Pair<Context, Collection<IMethod>>> worklist, CGNode callerNode) {
|
||||
final IMethod method = callerNode.getMethod();
|
||||
if (curEncountered.contains(method)) {
|
||||
System.err.println("recursion in context on method " + method);
|
||||
System.err.println("encountered methods: ");
|
||||
for (IMethod m : curEncountered) {
|
||||
System.err.println(" " + m);
|
||||
}
|
||||
System.err.println("context " + baseContext);
|
||||
return false;
|
||||
}
|
||||
Collection<IMethod> newEncountered = new ArrayList<IMethod>(curEncountered);
|
||||
newEncountered.add(method);
|
||||
worklist.add(Pair.make(callerNode.getContext(),newEncountered));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
|
||||
return base.getRelevantParameters(caller, site);
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue