Revert "refactor context selectors: extract delegation into ComposedContextSelector"

This reverts commit 7ff1219c5baed388a82d14fcf81d2b1f456c4e95.  That commit broke
a dojo test, and I'm not sure why.

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4491 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
msridhar1 2012-02-17 20:21:18 +00:00
parent 59d602e9b7
commit 92d8dc1e3d
12 changed files with 172 additions and 257 deletions

View File

@ -19,7 +19,6 @@ import com.ibm.wala.cast.js.test.Util;
import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.CallGraphBuilderCancelException;
import com.ibm.wala.ipa.callgraph.ComposedContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.util.ProgressMaster;
@ -83,9 +82,8 @@ public class HTMLCGBuilder {
JSCFABuilder builder = null;
try {
builder = Util.makeHTMLCGBuilder(url);
builder.setContextSelector(new ComposedContextSelector(builder
.getContextSelector(), new ForInContextSelector(2),
new ForInContextSelector(3)));
builder.setContextSelector(new ForInContextSelector(2, builder.getContextSelector()));
builder.setContextSelector(new ForInContextSelector(3, builder.getContextSelector()));
ProgressMaster master = ProgressMaster.make(new NullProgressMonitor());
if (timeout > 0) {
master.setMillisPerWorkItem(timeout * 1000);

View File

@ -11,7 +11,7 @@ import com.ibm.wala.cast.js.html.JSSourceExtractor;
import com.ibm.wala.cast.js.ipa.callgraph.ForInContextSelector;
import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.ComposedContextSelector;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.util.CancelException;
public abstract class TestForInLoopHack extends TestJSCallGraphShape {
@ -161,7 +161,8 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
*/
private void addHackedForInLoopSensitivity(JSCFABuilder builder) {
builder.setContextSelector(new ComposedContextSelector(builder.getContextSelector(), new ForInContextSelector()));
final ContextSelector orig = builder.getContextSelector();
builder.setContextSelector(new ForInContextSelector(orig));
}
}

View File

@ -27,7 +27,6 @@ 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.impl.ContextInsensitiveSelector;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey;
import com.ibm.wala.ipa.callgraph.propagation.ConstantKey;
@ -46,7 +45,6 @@ import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.Iterator2Iterable;
import com.ibm.wala.util.intset.EmptyIntSet;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.MutableIntSet;
@ -105,8 +103,9 @@ public class ForInContextSelector implements ContextSelector {
public static boolean DEPENDENT_THRU_READS = true;
public static class SelectiveCPAContext implements Context {
private final Map<ContextKey, InstanceKey> parameterObjs;
protected final Context base;
private final Map<ContextKey, InstanceKey> parameterObjs;
private final int hashCode;
@ -120,20 +119,21 @@ public class ForInContextSelector implements ContextSelector {
return result;
}
public SelectiveCPAContext(InstanceKey[] x) {
this(makeMap(x));
public SelectiveCPAContext(Context base, InstanceKey[] x) {
this(base, makeMap(x));
}
public SelectiveCPAContext(Map<ContextKey, InstanceKey> parameterObjs) {
public SelectiveCPAContext(Context base, Map<ContextKey, InstanceKey> parameterObjs) {
this.base = base;
this.parameterObjs = parameterObjs;
hashCode = parameterObjs.hashCode();
hashCode = base.hashCode() ^ parameterObjs.hashCode();
}
public ContextItem get(ContextKey name) {
if (parameterObjs.containsKey(name)) {
return new FilteredPointerKey.SingleInstanceFilter(parameterObjs.get(name));
} else {
return null;
return base.get(name);
}
}
@ -145,6 +145,7 @@ public class ForInContextSelector implements ContextSelector {
public boolean equals(Object other) {
return other != null &&
getClass().equals(other.getClass()) &&
base.equals(((SelectiveCPAContext)other).base) &&
parameterObjs.equals(((SelectiveCPAContext)other).parameterObjs);
}
@ -153,8 +154,8 @@ public class ForInContextSelector implements ContextSelector {
public class ForInContext extends SelectiveCPAContext {
ForInContext(InstanceKey obj) {
super(Collections.singletonMap(ContextKey.PARAMETERS[index], obj));
ForInContext(Context base, InstanceKey obj) {
super(base, Collections.singletonMap(ContextKey.PARAMETERS[index], obj));
}
public ContextItem get(ContextKey key) {
@ -169,11 +170,12 @@ public class ForInContextSelector implements ContextSelector {
@Override
public String toString() {
return "for in hack filter for " + get(ContextKey.PARAMETERS[index]);
return "for in hack filter for " + get(ContextKey.PARAMETERS[index]) + " over " + this.base;
}
}
private final ContextSelector base;
private final ContextSelector oneLevel;
private final int index;
@ -210,13 +212,14 @@ public class ForInContextSelector implements ContextSelector {
return dependentParameters;
}
public ForInContextSelector() {
this(2);
public ForInContextSelector(ContextSelector base) {
this(2, base);
}
public ForInContextSelector(int index) {
public ForInContextSelector(int index, ContextSelector base) {
this.index = index;
this.oneLevel = new OneLevelSiteContextSelector(new ContextInsensitiveSelector());
this.base = base;
this.oneLevel = new OneLevelSiteContextSelector(base);
}
private final HashMap<MethodReference, Boolean> forInOnFirstArg_cache = HashMapFactory.make();
@ -315,28 +318,29 @@ public class ForInContextSelector implements ContextSelector {
}
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) {
Context baseContext = base.getCalleeTarget(caller, site, callee, receiver);
String calleeFullName = callee.getDeclaringClass().getName().toString();
String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1);
if(USE_NAME_TO_SELECT_CONTEXT) {
if(calleeShortName.contains(HACK_METHOD_STR) && receiver.length > index) {
// we assume that the argument is only used as a property name, so we can do ToString
return new ForInContext(simulateToString(caller.getClassHierarchy(), receiver[index]));
return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index]));
}
} else if(receiver.length > index) {
Frequency f = usesFirstArgAsPropertyName(callee);
if(f == Frequency.ALWAYS) {
return new ForInContext(simulateToString(caller.getClassHierarchy(), receiver[index]));
return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index]));
} else if(f == Frequency.SOMETIMES) {
if(receiver[index] == null) {
IClass undef = caller.getClassHierarchy().lookupClass(JavaScriptTypes.Undefined);
return new ForInContext(new ConcreteTypeKey(undef));
return new ForInContext(baseContext, new ConcreteTypeKey(undef));
} else {
return new ForInContext(receiver[index]);
return new ForInContext(baseContext, receiver[index]);
}
}
}
if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) {
return new SelectiveCPAContext(receiver);
return new SelectiveCPAContext(baseContext, receiver);
} else if (USE_1LEVEL_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) {
if (! identifyDependentParameters(caller, site).isEmpty()) {
// RECURSION CHECK: only add one level of caller-site contexts if the caller and callee methods are distinct
@ -344,10 +348,10 @@ public class ForInContextSelector implements ContextSelector {
return oneLevel.getCalleeTarget(caller, site, callee, receiver);
}
} else {
return null;
return baseContext;
}
}
return null;
return baseContext;
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
@ -355,9 +359,9 @@ public class ForInContextSelector implements ContextSelector {
// what about base.getRelevantParameters() here?
return identifyDependentParameters(caller, site);
} else if (caller.getIR().getCalls(site)[0].getNumberOfUses() > index) {
return IntSetUtil.make(new int[]{index});
return IntSetUtil.make(new int[]{index}).union(base.getRelevantParameters(caller, site));
} else {
return EmptyIntSet.instance;
return base.getRelevantParameters(caller, site);
}
}

View File

@ -10,15 +10,11 @@
*****************************************************************************/
package com.ibm.wala.cast.js.ipa.callgraph;
import java.util.ArrayList;
import java.util.Collection;
import com.ibm.wala.cast.ipa.callgraph.LexicalScopingResolverContexts;
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingKeysContextSelector;
import com.ibm.wala.cast.ir.translator.AstTranslator;
import com.ibm.wala.ipa.callgraph.AnalysisCache;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.ComposedContextSelector;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.MethodTargetSelector;
import com.ibm.wala.ipa.callgraph.impl.ContextInsensitiveSelector;
@ -42,41 +38,13 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder {
ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) {
super(cha, options, cache);
SSAContextInterpreter contextInterpreter = setupSSAContextInterpreter(cha, options, cache, appContextInterpreter);
setupMethodTargetSelector(cha, options);
setupContextSelector(options, appContextSelector, doOneCFA);
setInstanceKeys(new JavaScriptScopeMappingInstanceKeys(cha, this, new JavaScriptConstructorInstanceKeys(new ZeroXInstanceKeys(
options, cha, contextInterpreter, instancePolicy))));
}
private void setupContextSelector(JSAnalysisOptions options, ContextSelector appContextSelector, boolean doOneCFA) {
Collection<ContextSelector> selectors = new ArrayList<ContextSelector>();
ContextSelector def = new ContextInsensitiveSelector();
ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def);
selectors.add(contextSelector);
// if (!AstTranslator.NEW_LEXICAL) {
selectors.add(new ScopeMappingKeysContextSelector());
// }
selectors.add(new JavaScriptConstructorContextSelector());
if (USE_OBJECT_SENSITIVITY) {
selectors.add(new ObjectSensitivityContextSelector());
}
SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha);
if (options.handleCallApply()) {
selectors.add(new JavaScriptFunctionApplyContextSelector());
contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache),
contextInterpreter);
}
if (!AstTranslator.NEW_LEXICAL) {
selectors.add(new LexicalScopingResolverContexts(this));
}
if (doOneCFA) {
selectors.add(new nCFAContextSelector(1, new ContextInsensitiveSelector()));
}
setContextSelector(new ComposedContextSelector(selectors));
}
setContextInterpreter(contextInterpreter);
private void setupMethodTargetSelector(IClassHierarchy cha, JSAnalysisOptions options) {
MethodTargetSelector targetSelector = new JavaScriptConstructTargetSelector(cha, options
.getMethodTargetSelector());
if (options.handleCallApply()) {
@ -86,17 +54,29 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder {
targetSelector = new LoadFileTargetSelector(targetSelector, this);
}
options.setSelector(targetSelector);
}
private SSAContextInterpreter setupSSAContextInterpreter(IClassHierarchy cha, JSAnalysisOptions options, AnalysisCache cache,
SSAContextInterpreter appContextInterpreter) {
SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha);
if (options.handleCallApply()) {
contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache),
contextInterpreter);
ContextSelector def = new ContextInsensitiveSelector();
ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def);
// if (!AstTranslator.NEW_LEXICAL) {
contextSelector = new ScopeMappingKeysContextSelector(contextSelector);
// }
contextSelector = new JavaScriptConstructorContextSelector(contextSelector);
if (USE_OBJECT_SENSITIVITY) {
contextSelector = new ObjectSensitivityContextSelector(contextSelector);
}
setContextInterpreter(contextInterpreter);
return contextInterpreter;
if (options.handleCallApply()) {
contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector);
}
if (!AstTranslator.NEW_LEXICAL) {
contextSelector = new LexicalScopingResolverContexts(this, contextSelector);
}
if (doOneCFA) {
contextSelector = new nCFAContextSelector(1, contextSelector);
}
setContextSelector(contextSelector);
setInstanceKeys(new JavaScriptScopeMappingInstanceKeys(cha, this, new JavaScriptConstructorInstanceKeys(new ZeroXInstanceKeys(
options, cha, contextInterpreter, instancePolicy))));
}
/**

View File

@ -10,25 +10,32 @@ import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.DelegatingContext;
import com.ibm.wala.ipa.callgraph.impl.ContextInsensitiveSelector;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.cfa.CallerSiteContext;
import com.ibm.wala.ipa.callgraph.propagation.cfa.OneLevelSiteContextSelector;
import com.ibm.wala.ipa.callgraph.propagation.cfa.nCFAContextSelector;
import com.ibm.wala.util.intset.EmptyIntSet;
import com.ibm.wala.util.intset.IntSet;
public class JavaScriptConstructorContextSelector implements ContextSelector {
private nCFAContextSelector oneLevelCallStrings;
private OneLevelSiteContextSelector oneLevelCallerSite;
private final ContextSelector base;
public JavaScriptConstructorContextSelector() {
final ContextInsensitiveSelector dummyBase = new ContextInsensitiveSelector();
this.oneLevelCallStrings = new nCFAContextSelector(1, dummyBase);
this.oneLevelCallerSite = new OneLevelSiteContextSelector(dummyBase);
/**
* for generating contexts with one-level of call strings, to match standard
* Andersen's heap abstraction
*/
private final nCFAContextSelector oneLevelCallStrings;
private final OneLevelSiteContextSelector oneLevelCallerSite;
public JavaScriptConstructorContextSelector(ContextSelector base) {
this.base = base;
this.oneLevelCallStrings = new nCFAContextSelector(1, base);
this.oneLevelCallerSite = new OneLevelSiteContextSelector(base);
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
return EmptyIntSet.instance;
return base.getRelevantParameters(caller, site);
}
public Context getCalleeTarget(final CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) {
@ -38,8 +45,7 @@ public class JavaScriptConstructorContextSelector implements ContextSelector {
if (!AstTranslator.NEW_LEXICAL && callerContext instanceof ScopeMappingContext) {
return new DelegatingContext(callerContext, oneLevelCallStringContext);
} else if (AstTranslator.NEW_LEXICAL && LexicalScopingResolverContexts.hasExposedUses(caller, site)) {
// use a caller-site context, to enable lexical scoping lookups (via
// caller CGNode)
// use a caller-site context, to enable lexical scoping lookups (via caller CGNode)
return oneLevelCallerSite.getCalleeTarget(caller, site, callee, receiver);
} else {
// use at least one-level of call-string sensitivity for constructors
@ -47,7 +53,7 @@ public class JavaScriptConstructorContextSelector implements ContextSelector {
return oneLevelCallStringContext;
}
} else {
return null;
return base.getCalleeTarget(caller, site, callee, receiver);
}
}

View File

@ -10,12 +10,9 @@ 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.DelegatingContext;
import com.ibm.wala.ipa.callgraph.impl.ContextInsensitiveSelector;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.cfa.nCFAContextSelector;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.util.intset.EmptyIntSet;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
@ -26,11 +23,8 @@ import com.ibm.wala.util.intset.IntSetUtil;
* Function.prototype.apply() docs</a>
*/
public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
/*
* whether to use a one-level callstring context in addition to the apply
* context
*/
private static final boolean USE_ONE_LEVEL = true;
/* whether to use a one-level callstring context in addition to the apply context */
private static final boolean USE_ONE_LEVEL = true;
private static final TypeName APPLY_TYPE_NAME = TypeName.findOrCreate("Lprologue.js/functionApply");
@ -73,11 +67,13 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
}
private final ContextSelector base;
private ContextSelector oneLevel;
public JavaScriptFunctionApplyContextSelector() {
this.oneLevel = new nCFAContextSelector(1, new ContextInsensitiveSelector());
// this.oneLevel = new OneLevelSiteContextSelector(base);
public JavaScriptFunctionApplyContextSelector(ContextSelector base) {
this.base = base;
this.oneLevel = new nCFAContextSelector(1, base);
// this.oneLevel = new OneLevelSiteContextSelector(base);
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
@ -85,19 +81,22 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
// for this arg of function being invoked,
// 3 for arguments array
if (caller.getIR().getCalls(site)[0].getNumberOfUses() >= 4) {
return IntSetUtil.make(new int[] { 3 });
return IntSetUtil.make(new int[] { 3 }).union(base.getRelevantParameters(caller, site));
} else {
return EmptyIntSet.instance;
return base.getRelevantParameters(caller, site);
}
}
public static class ApplyContext implements Context {
private final Context delegate;
/**
* was the argsList argument a non-null Array?
*/
private final BooleanContextItem isNonNullArray;
ApplyContext(boolean isNonNullArray) {
ApplyContext(Context delegate, boolean isNonNullArray) {
this.delegate = delegate;
this.isNonNullArray = new BooleanContextItem(isNonNullArray);
}
@ -105,7 +104,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
if (APPLY_NON_NULL_ARGS.equals(name)) {
return isNonNullArray;
} else {
return null;
return delegate.get(name);
}
}
@ -113,7 +112,8 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((isNonNullArray == null) ? 0 : isNonNullArray.hashCode());
result = prime * result + delegate.hashCode();
result = prime * result + isNonNullArray.hashCode();
return result;
}
@ -126,17 +126,16 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
if (getClass() != obj.getClass())
return false;
ApplyContext other = (ApplyContext) obj;
if (isNonNullArray == null) {
if (other.isNonNullArray != null)
return false;
} else if (!isNonNullArray.equals(other.isNonNullArray))
if (!delegate.equals(other.delegate))
return false;
if (!isNonNullArray.equals(other.isNonNullArray))
return false;
return true;
}
@Override
public String toString() {
return "ApplyContext [isNonNullArray=" + isNonNullArray + "]";
return "ApplyContext [delegate=" + delegate + ", isNonNullArray=" + isNonNullArray + "]";
}
}
@ -144,6 +143,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) {
IClass declaringClass = callee.getDeclaringClass();
IMethod method = declaringClass.getMethod(AstMethodReference.fnSelector);
Context baseCtxt = base.getCalleeTarget(caller, site, callee, receiver);
if (method != null) {
TypeName tn = method.getReference().getDeclaringClass().getName();
if (tn.equals(APPLY_TYPE_NAME)) {
@ -154,13 +154,12 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
isNonNullArray = true;
}
}
Context result = new ApplyContext(isNonNullArray);
if (USE_ONE_LEVEL)
result = new DelegatingContext(result, oneLevel.getCalleeTarget(caller, site, callee, receiver));
return result;
baseCtxt = oneLevel.getCalleeTarget(caller, site, callee, receiver);
return new ApplyContext(baseCtxt, isNonNullArray);
}
}
return null;
return baseCtxt;
}
}

View File

@ -17,27 +17,30 @@ import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.ssa.SSAReturnInstruction;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.intset.EmptyIntSet;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
public class ObjectSensitivityContextSelector implements ContextSelector {
private final ContextSelector base;
public ObjectSensitivityContextSelector(ContextSelector base) {
this.base = base;
}
private final HashMap<MethodReference, Boolean> returnsThis_cache = HashMapFactory.make();
// determine whether the method returns "this"
private boolean returnsThis(IMethod method) {
MethodReference mref = method.getReference();
if (method.getNumberOfParameters() < 1)
if(method.getNumberOfParameters() < 1)
return false;
Boolean b = returnsThis_cache.get(mref);
if (b != null)
if(b != null)
return b;
for (SSAInstruction inst : ForInContextSelector.factory.makeIR(method, Everywhere.EVERYWHERE, SSAOptions.defaultOptions())
.getInstructions()) {
if (inst instanceof SSAReturnInstruction) {
SSAReturnInstruction ret = (SSAReturnInstruction) inst;
if (ret.getResult() == 2) {
for(SSAInstruction inst : ForInContextSelector.factory.makeIR(method, Everywhere.EVERYWHERE, SSAOptions.defaultOptions()).getInstructions()) {
if(inst instanceof SSAReturnInstruction) {
SSAReturnInstruction ret = (SSAReturnInstruction)inst;
if(ret.getResult() == 2) {
returnsThis_cache.put(mref, true);
return true;
}
@ -48,46 +51,49 @@ public class ObjectSensitivityContextSelector implements ContextSelector {
}
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] arguments) {
if (returnsThis(callee)) {
if (arguments.length > 1 && arguments[1] != null) {
return new ArgumentInstanceContext(1, arguments[1]);
Context baseContext = base.getCalleeTarget(caller, site, callee, arguments);
if(returnsThis(callee)) {
if(arguments.length > 1 && arguments[1] != null) {
return new ArgumentInstanceContext(baseContext, 1, arguments[1]);
}
}
return null;
return baseContext;
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
if (caller.getIR().getCalls(site)[0].getNumberOfUses() > 1) {
return IntSetUtil.make(new int[] { 1 });
return IntSetUtil.make(new int[]{1}).union(base.getRelevantParameters(caller, site));
} else {
return EmptyIntSet.instance;
return base.getRelevantParameters(caller, site);
}
}
}
class ArgumentInstanceContext implements Context {
private final Context base;
private final int index;
private final InstanceKey instanceKey;
public ArgumentInstanceContext(int index, InstanceKey instanceKey) {
public ArgumentInstanceContext(Context base, int index, InstanceKey instanceKey) {
this.base = base;
this.index = index;
this.instanceKey = instanceKey;
}
public ContextItem get(ContextKey name) {
/*
* if(name == ContextKey.RECEIVER && index == 1) return instanceKey;
*/
if (name == ContextKey.PARAMETERS[index])
/*if(name == ContextKey.RECEIVER && index == 1)
return instanceKey;*/
if(name == ContextKey.PARAMETERS[index])
return new FilteredPointerKey.SingleInstanceFilter(instanceKey);
return null;
return base.get(name);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((base == null) ? 0 : base.hashCode());
result = prime * result + index;
result = prime * result + ((instanceKey == null) ? 0 : instanceKey.hashCode());
return result;
@ -102,6 +108,11 @@ class ArgumentInstanceContext implements Context {
if (getClass() != obj.getClass())
return false;
ArgumentInstanceContext other = (ArgumentInstanceContext) obj;
if (base == null) {
if (other.base != null)
return false;
} else if (!base.equals(other.base))
return false;
if (index != other.index)
return false;
if (instanceKey == null) {
@ -111,5 +122,5 @@ class ArgumentInstanceContext implements Context {
return false;
return true;
}
}

View File

@ -27,7 +27,6 @@ import com.ibm.wala.util.collections.IteratorPlusOne;
import com.ibm.wala.util.collections.MapUtil;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.intset.EmptyIntSet;
import com.ibm.wala.util.intset.IntSet;
public final class LexicalScopingResolverContexts implements ContextSelector {
@ -439,8 +438,10 @@ public final class LexicalScopingResolverContexts implements ContextSelector {
private class LexicalScopingResolverContext implements Context {
private final LexicalScopingResolver governingCallSites;
private final Context base;
public int hashCode() {
return (governingCallSites == null ? 1077651 : governingCallSites.hashCode());
return base.hashCode() * (governingCallSites == null ? 1077651 : governingCallSites.hashCode());
}
public boolean equals(Object o) {
@ -448,35 +449,39 @@ public final class LexicalScopingResolverContexts implements ContextSelector {
return true;
} else if (getClass().equals(o.getClass())) {
LexicalScopingResolverContext c = (LexicalScopingResolverContext) o;
return (governingCallSites == c.governingCallSites);
return (base == null ? c.base == null : base.equals(c.base)) && (governingCallSites == c.governingCallSites);
} else {
return false;
}
}
public ContextItem get(ContextKey name) {
return name.equals(RESOLVER) ? governingCallSites: null;
return name.equals(RESOLVER) ? governingCallSites : base != null ? base.get(name) : null;
}
private LexicalScopingResolverContext(LexicalScopingResolver governingCallSites) {
private LexicalScopingResolverContext(LexicalScopingResolver governingCallSites, Context base) {
this.base = base;
this.governingCallSites = governingCallSites;
}
private LexicalScopingResolverContext(CGNode source, CallSiteReference callSite) {
private LexicalScopingResolverContext(CGNode source, CallSiteReference callSite, Context base) {
this.base = base;
this.governingCallSites = findChild(source, callSite);
}
@Override
public String toString() {
return "LexicalScopingResolverContext [governingCallSites=" + governingCallSites + "]";
return "LexicalScopingResolverContext [governingCallSites=" + governingCallSites + ", base=" + base + "]";
}
}
private final ContextSelector base;
private final PropagationCallGraphBuilder builder;
public LexicalScopingResolverContexts(PropagationCallGraphBuilder builder) {
public LexicalScopingResolverContexts(PropagationCallGraphBuilder builder, ContextSelector base) {
this.base = base;
this.builder = builder;
}
@ -557,11 +562,12 @@ public final class LexicalScopingResolverContexts implements ContextSelector {
}
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) {
Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters);
if (callee instanceof SummarizedMethod) {
final String calleeName = callee.getReference().toString();
// TODO create a sub-class in the cast.js projects so we're not checking strings here
if (calleeName.equals("< JavaScriptLoader, LArray, ctor()LRoot; >") || calleeName.equals("< JavaScriptLoader, LObject, ctor()LRoot; >")) {
return null;
return baseContext;
}
}
LexicalScopingResolver resolver = (LexicalScopingResolver) caller.getContext().get(RESOLVER);
@ -575,23 +581,23 @@ public final class LexicalScopingResolverContexts implements ContextSelector {
}
if (caller.getMethod() instanceof AstMethod && hasExposedUses(caller, site)) {
LexicalScopingResolverContext result = new LexicalScopingResolverContext(caller, site);
LexicalScopingResolverContext result = new LexicalScopingResolverContext(caller, site, baseContext);
MapUtil.findOrCreateList(key2Contexts, key).add(result);
return result;
}
else if (resolver != null) {
LexicalScopingResolverContext result = new LexicalScopingResolverContext(resolver);
LexicalScopingResolverContext result = new LexicalScopingResolverContext(resolver, baseContext);
MapUtil.findOrCreateList(key2Contexts, key).add(result);
return result;
}
else {
return null;
return baseContext;
}
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
return EmptyIntSet.instance;
return base.getRelevantParameters(caller, site);
}
}

View File

@ -9,6 +9,7 @@ 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;
@ -24,9 +25,11 @@ public class ScopeMappingKeysContextSelector implements ContextSelector {
};
public static class ScopeMappingContext implements Context {
private final Context base;
private final ScopeMappingInstanceKey key;
private ScopeMappingContext(ScopeMappingInstanceKey key) {
private ScopeMappingContext(Context base, ScopeMappingInstanceKey key) {
this.base = base;
this.key = key;
}
@ -34,7 +37,7 @@ public class ScopeMappingKeysContextSelector implements ContextSelector {
if (scopeKey.equals(name)) {
return key;
} else {
return null;
return base.get(name);
}
}
@ -42,7 +45,7 @@ public class ScopeMappingKeysContextSelector implements ContextSelector {
public int hashCode() {
if (hashcode == -1) {
hashcode = key.hashCode();
hashcode = base.hashCode() * key.hashCode();
}
return hashcode;
}
@ -52,30 +55,37 @@ public class ScopeMappingKeysContextSelector implements ContextSelector {
}
public boolean equals(Object o) {
return (o instanceof ScopeMappingContext) && key.equals(((ScopeMappingContext) o).key);
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; >")) {
return null;
return bc;
}
}
if (receiver[0] instanceof ScopeMappingInstanceKey) {
final ScopeMappingInstanceKey smik = (ScopeMappingInstanceKey) receiver[0];
if (AstTranslator.NEW_LEXICAL) {
if (detectRecursion(smik.getCreator().getContext(), callee)) {
return null;
return bc;
}
}
final ScopeMappingContext scopeMappingContext = new ScopeMappingContext(smik);
final ScopeMappingContext scopeMappingContext = new ScopeMappingContext(bc, smik);
return scopeMappingContext;
} else {
return null;
return bc;
}
}

View File

@ -1,92 +0,0 @@
/*******************************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.ipa.callgraph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.util.intset.IntSet;
/**
* A ContextSelector that behaves as the composition of a list of child
* selectors. Note that we deliberately do not document what order the
* composition is performed in, with the hope that the {@link ContextKey}s
* understood by the {@link Context}s returned by distinct children do not
* overlap.
*
*/
public class ComposedContextSelector implements ContextSelector {
private final List<ContextSelector> childSelectors;
public ComposedContextSelector(Collection<ContextSelector> childSelectors) {
this.childSelectors = new ArrayList<ContextSelector>(childSelectors);
}
public ComposedContextSelector(ContextSelector... childSelectors) {
this.childSelectors = Arrays.asList(childSelectors);
}
/**
* return a context representing the composition of all the non-null child
* contexts. Elides the {@link Everywhere#EVERYWHERE} context when some child
* returns a context that is not {@link Everywhere#EVERYWHERE}.
*/
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) {
List<Context> childResults = new ArrayList<Context>(1);
boolean sawEverywhere = false;
for (ContextSelector child : childSelectors) {
Context childResult = child.getCalleeTarget(caller, site, callee, actualParameters);
if (childResult != null) {
childResults.add(childResult);
if (sawEverywhere) {
assert !childResult.equals(Everywhere.EVERYWHERE);
} else {
sawEverywhere = childResult.equals(Everywhere.EVERYWHERE);
}
}
}
if (childResults.isEmpty()) {
return null;
}
boolean elideEverywhere = sawEverywhere && childResults.size() > 1;
Context result = null;
for (Context c : childResults) {
if (!elideEverywhere || !c.equals(Everywhere.EVERYWHERE)) {
result = (result == null) ? c : new DelegatingContext(c, result);
}
}
return result;
}
/**
* return the union of the relevant parameters for all children
*/
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
IntSet result = null;
for (ContextSelector child : childSelectors) {
IntSet childResult = child.getRelevantParameters(caller, site);
if (result == null) {
result = childResult;
} else {
result = result.union(childResult);
}
}
return result;
}
}

View File

@ -13,7 +13,6 @@ package com.ibm.wala.ipa.callgraph.propagation.cfa;
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.ComposedContextSelector;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextItem;
import com.ibm.wala.ipa.callgraph.ContextKey;
@ -67,9 +66,6 @@ public abstract class CallStringContextSelector implements ContextSelector {
}
};
/**
* TODO get rid of base selector, and instead use with {@link ComposedContextSelector}
*/
private final ContextSelector base;
public CallStringContextSelector(ContextSelector base) {

View File

@ -13,7 +13,6 @@ package com.ibm.wala.ipa.callgraph.propagation.cfa;
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.ComposedContextSelector;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextSelector;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
@ -25,9 +24,6 @@ import com.ibm.wala.util.intset.IntSet;
*/
public class OneLevelSiteContextSelector implements ContextSelector {
/**
* TODO get rid of base selector, and instead use with {@link ComposedContextSelector}
*/
private final ContextSelector baseSelector;
/**