better recursion check

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4484 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
msridhar1 2012-02-17 20:19:22 +00:00
parent 3b5ba61cc0
commit 1ac2dc110e
2 changed files with 47 additions and 23 deletions

View File

@ -170,6 +170,10 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
public InstanceKey getBase() {
return base;
}
public CGNode getCreator() {
return creator;
}
}
public InstanceKey getInstanceKeyForAllocation(CGNode creatorNode, NewSiteReference allocationSite) {

View File

@ -9,21 +9,25 @@ import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextItem;
import com.ibm.wala.ipa.callgraph.ContextKey;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.AllocationSiteInNode;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.cfa.CallerSiteContext;
import com.ibm.wala.ipa.summaries.SummarizedMethod;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
public class ScopeMappingKeysContextSelector implements ContextSelector {
public static final ContextKey scopeKey = new ContextKey() {
public String toString() { return "SCOPE KEY"; }
public String toString() {
return "SCOPE KEY";
}
};
public static class ScopeMappingContext implements Context {
private final Context base;
private final ScopeMappingInstanceKey key;
private ScopeMappingContext(Context base, ScopeMappingInstanceKey key) {
this.base = base;
this.key = key;
@ -36,61 +40,77 @@ public class ScopeMappingKeysContextSelector implements ContextSelector {
return base.get(name);
}
}
private int hashcode = -1;
public int hashCode() {
if (hashcode == -1) {
hashcode = base.hashCode()*key.hashCode();
hashcode = base.hashCode() * key.hashCode();
}
return hashcode;
}
public String toString() {
return "context for " + key;
}
public boolean equals(Object o) {
return (o instanceof ScopeMappingContext) &&
key.equals(((ScopeMappingContext)o).key) &&
base.equals(((ScopeMappingContext)o).base);
return (o instanceof ScopeMappingContext) && key.equals(((ScopeMappingContext) o).key)
&& base.equals(((ScopeMappingContext) o).base);
}
}
private final ContextSelector base;
public ScopeMappingKeysContextSelector(ContextSelector base) {
this.base = base;
}
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) {
Context bc = base.getCalleeTarget(caller, site, callee, receiver);
if (callee instanceof SummarizedMethod) {
final String calleeName = callee.getReference().toString();
if (calleeName.equals("< JavaScriptLoader, LArray, ctor()LRoot; >") || calleeName.equals("< JavaScriptLoader, LObject, ctor()LRoot; >")) {
if (calleeName.equals("< JavaScriptLoader, LArray, ctor()LRoot; >")
|| calleeName.equals("< JavaScriptLoader, LObject, ctor()LRoot; >")) {
return bc;
}
}
if (receiver[0] instanceof ScopeMappingInstanceKey) {
final ScopeMappingInstanceKey smik = (ScopeMappingInstanceKey) receiver[0];
if (AstTranslator.NEW_LEXICAL) {
// need a recursion check; for now, very coarse
ContextItem contextItem = caller.getContext().get(scopeKey);
if (contextItem != null) {
if (detectRecursion(smik.getCreator().getContext(), callee)) {
return bc;
}
}
final ScopeMappingContext scopeMappingContext = new ScopeMappingContext(bc, (ScopeMappingInstanceKey) receiver[0]);
final ScopeMappingContext scopeMappingContext = new ScopeMappingContext(bc, smik);
return scopeMappingContext;
} else {
return bc;
}
}
private static final IntSet thisParameter = IntSetUtil.make(new int[]{0});
/**
* we need this check due a potentially nasty interaction between
* ScopeMappingContexts and CGNode-based contexts like
* {@link CallerSiteContext}s. It's unclear where exactly this check should
* go; since ScopeMappingContexts are less common, putting it here for now.
*/
private boolean detectRecursion(Context context, IMethod callee) {
CGNode caller = (CGNode) context.get(ContextKey.CALLER);
if (caller != null) {
if (caller.getMethod().equals(callee)) {
return true;
} else {
return detectRecursion(caller.getContext(), callee);
}
}
return false;
}
private static final IntSet thisParameter = IntSetUtil.make(new int[] { 0 });
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
return thisParameter;
}
}