refactor context selectors: extract delegation into ComposedContextSelector

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4489 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
msridhar1 2012-02-17 20:20:26 +00:00
parent fa3264bade
commit edd300cf00
12 changed files with 258 additions and 173 deletions

View File

@ -19,6 +19,7 @@ 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;
@ -82,8 +83,9 @@ public class HTMLCGBuilder {
JSCFABuilder builder = null;
try {
builder = Util.makeHTMLCGBuilder(url);
builder.setContextSelector(new ForInContextSelector(2, builder.getContextSelector()));
builder.setContextSelector(new ForInContextSelector(3, builder.getContextSelector()));
builder.setContextSelector(new ComposedContextSelector(builder
.getContextSelector(), new ForInContextSelector(2),
new ForInContextSelector(3)));
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.ContextSelector;
import com.ibm.wala.ipa.callgraph.ComposedContextSelector;
import com.ibm.wala.util.CancelException;
public abstract class TestForInLoopHack extends TestJSCallGraphShape {
@ -161,8 +161,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape {
*/
private void addHackedForInLoopSensitivity(JSCFABuilder builder) {
final ContextSelector orig = builder.getContextSelector();
builder.setContextSelector(new ForInContextSelector(orig));
builder.setContextSelector(new ComposedContextSelector(builder.getContextSelector(), new ForInContextSelector()));
}
}

View File

@ -27,6 +27,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.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;
@ -45,6 +46,7 @@ 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;
@ -103,9 +105,8 @@ public class ForInContextSelector implements ContextSelector {
public static boolean DEPENDENT_THRU_READS = true;
public static class SelectiveCPAContext implements Context {
protected final Context base;
private final Map<ContextKey, InstanceKey> parameterObjs;
private final Map<ContextKey, InstanceKey> parameterObjs;
private final int hashCode;
@ -119,21 +120,20 @@ public class ForInContextSelector implements ContextSelector {
return result;
}
public SelectiveCPAContext(Context base, InstanceKey[] x) {
this(base, makeMap(x));
public SelectiveCPAContext(InstanceKey[] x) {
this(makeMap(x));
}
public SelectiveCPAContext(Context base, Map<ContextKey, InstanceKey> parameterObjs) {
this.base = base;
public SelectiveCPAContext(Map<ContextKey, InstanceKey> parameterObjs) {
this.parameterObjs = parameterObjs;
hashCode = base.hashCode() ^ parameterObjs.hashCode();
hashCode = parameterObjs.hashCode();
}
public ContextItem get(ContextKey name) {
if (parameterObjs.containsKey(name)) {
return new FilteredPointerKey.SingleInstanceFilter(parameterObjs.get(name));
} else {
return base.get(name);
return null;
}
}
@ -145,7 +145,6 @@ 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);
}
@ -154,8 +153,8 @@ public class ForInContextSelector implements ContextSelector {
public class ForInContext extends SelectiveCPAContext {
ForInContext(Context base, InstanceKey obj) {
super(base, Collections.singletonMap(ContextKey.PARAMETERS[index], obj));
ForInContext(InstanceKey obj) {
super(Collections.singletonMap(ContextKey.PARAMETERS[index], obj));
}
public ContextItem get(ContextKey key) {
@ -170,12 +169,11 @@ public class ForInContextSelector implements ContextSelector {
@Override
public String toString() {
return "for in hack filter for " + get(ContextKey.PARAMETERS[index]) + " over " + this.base;
return "for in hack filter for " + get(ContextKey.PARAMETERS[index]);
}
}
private final ContextSelector base;
private final ContextSelector oneLevel;
private final int index;
@ -212,14 +210,13 @@ public class ForInContextSelector implements ContextSelector {
return dependentParameters;
}
public ForInContextSelector(ContextSelector base) {
this(2, base);
public ForInContextSelector() {
this(2);
}
public ForInContextSelector(int index, ContextSelector base) {
public ForInContextSelector(int index) {
this.index = index;
this.base = base;
this.oneLevel = new OneLevelSiteContextSelector(base);
this.oneLevel = new OneLevelSiteContextSelector(new ContextInsensitiveSelector());
}
private final HashMap<MethodReference, Boolean> forInOnFirstArg_cache = HashMapFactory.make();
@ -318,37 +315,36 @@ 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(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index]));
return new ForInContext(simulateToString(caller.getClassHierarchy(), receiver[index]));
}
} else if(receiver.length > index) {
Frequency f = usesFirstArgAsPropertyName(callee);
if(f == Frequency.ALWAYS) {
return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index]));
return new ForInContext(simulateToString(caller.getClassHierarchy(), receiver[index]));
} else if(f == Frequency.SOMETIMES) {
if(receiver[index] == null) {
IClass undef = caller.getClassHierarchy().lookupClass(JavaScriptTypes.Undefined);
return new ForInContext(baseContext, new ConcreteTypeKey(undef));
return new ForInContext(new ConcreteTypeKey(undef));
} else {
return new ForInContext(baseContext, receiver[index]);
return new ForInContext(receiver[index]);
}
}
}
if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) {
return new SelectiveCPAContext(baseContext, receiver);
return new SelectiveCPAContext(receiver);
} else if (USE_1LEVEL_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) {
if (! identifyDependentParameters(caller, site).isEmpty()) {
return oneLevel.getCalleeTarget(caller, site, callee, receiver);
} else {
return baseContext;
return null;
}
}
return baseContext;
return null;
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
@ -356,9 +352,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}).union(base.getRelevantParameters(caller, site));
return IntSetUtil.make(new int[]{index});
} else {
return base.getRelevantParameters(caller, site);
return EmptyIntSet.instance;
}
}

View File

@ -10,11 +10,15 @@
*****************************************************************************/
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;
@ -38,13 +42,41 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder {
ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) {
super(cha, options, cache);
SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha);
if (options.handleCallApply()) {
contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache),
contextInterpreter);
}
setContextInterpreter(contextInterpreter);
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());
}
if (options.handleCallApply()) {
selectors.add(new JavaScriptFunctionApplyContextSelector());
}
if (!AstTranslator.NEW_LEXICAL) {
selectors.add(new LexicalScopingResolverContexts(this));
}
if (doOneCFA) {
selectors.add(new nCFAContextSelector(1, new ContextInsensitiveSelector()));
}
setContextSelector(new ComposedContextSelector(selectors));
}
private void setupMethodTargetSelector(IClassHierarchy cha, JSAnalysisOptions options) {
MethodTargetSelector targetSelector = new JavaScriptConstructTargetSelector(cha, options
.getMethodTargetSelector());
if (options.handleCallApply()) {
@ -54,29 +86,17 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder {
targetSelector = new LoadFileTargetSelector(targetSelector, this);
}
options.setSelector(targetSelector);
}
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);
}
private SSAContextInterpreter setupSSAContextInterpreter(IClassHierarchy cha, JSAnalysisOptions options, AnalysisCache cache,
SSAContextInterpreter appContextInterpreter) {
SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha);
if (options.handleCallApply()) {
contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector);
contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache),
contextInterpreter);
}
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))));
setContextInterpreter(contextInterpreter);
return contextInterpreter;
}
/**

View File

@ -10,32 +10,25 @@ 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.Everywhere;
import com.ibm.wala.ipa.callgraph.impl.ContextInsensitiveSelector;
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 final ContextSelector base;
private nCFAContextSelector oneLevelCallStrings;
private OneLevelSiteContextSelector oneLevelCallerSite;
/**
* 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 JavaScriptConstructorContextSelector() {
final ContextInsensitiveSelector dummyBase = new ContextInsensitiveSelector();
this.oneLevelCallStrings = new nCFAContextSelector(1, dummyBase);
this.oneLevelCallerSite = new OneLevelSiteContextSelector(dummyBase);
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
return base.getRelevantParameters(caller, site);
return EmptyIntSet.instance;
}
public Context getCalleeTarget(final CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) {
@ -45,7 +38,8 @@ 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
@ -53,7 +47,7 @@ public class JavaScriptConstructorContextSelector implements ContextSelector {
return oneLevelCallStringContext;
}
} else {
return base.getCalleeTarget(caller, site, callee, receiver);
return null;
}
}

View File

@ -10,9 +10,12 @@ 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;
@ -23,8 +26,11 @@ 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");
@ -67,13 +73,11 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
}
private final ContextSelector base;
private ContextSelector oneLevel;
public JavaScriptFunctionApplyContextSelector(ContextSelector base) {
this.base = base;
this.oneLevel = new nCFAContextSelector(1, base);
// this.oneLevel = new OneLevelSiteContextSelector(base);
public JavaScriptFunctionApplyContextSelector() {
this.oneLevel = new nCFAContextSelector(1, new ContextInsensitiveSelector());
// this.oneLevel = new OneLevelSiteContextSelector(base);
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
@ -81,22 +85,19 @@ 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 }).union(base.getRelevantParameters(caller, site));
return IntSetUtil.make(new int[] { 3 });
} else {
return base.getRelevantParameters(caller, site);
return EmptyIntSet.instance;
}
}
public static class ApplyContext implements Context {
private final Context delegate;
/**
* was the argsList argument a non-null Array?
*/
private final BooleanContextItem isNonNullArray;
ApplyContext(Context delegate, boolean isNonNullArray) {
this.delegate = delegate;
ApplyContext(boolean isNonNullArray) {
this.isNonNullArray = new BooleanContextItem(isNonNullArray);
}
@ -104,7 +105,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
if (APPLY_NON_NULL_ARGS.equals(name)) {
return isNonNullArray;
} else {
return delegate.get(name);
return null;
}
}
@ -112,8 +113,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + delegate.hashCode();
result = prime * result + isNonNullArray.hashCode();
result = prime * result + ((isNonNullArray == null) ? 0 : isNonNullArray.hashCode());
return result;
}
@ -126,16 +126,17 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
if (getClass() != obj.getClass())
return false;
ApplyContext other = (ApplyContext) obj;
if (!delegate.equals(other.delegate))
return false;
if (!isNonNullArray.equals(other.isNonNullArray))
if (isNonNullArray == null) {
if (other.isNonNullArray != null)
return false;
} else if (!isNonNullArray.equals(other.isNonNullArray))
return false;
return true;
}
@Override
public String toString() {
return "ApplyContext [delegate=" + delegate + ", isNonNullArray=" + isNonNullArray + "]";
return "ApplyContext [isNonNullArray=" + isNonNullArray + "]";
}
}
@ -143,7 +144,6 @@ 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,12 +154,13 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector {
isNonNullArray = true;
}
}
Context result = new ApplyContext(isNonNullArray);
if (USE_ONE_LEVEL)
baseCtxt = oneLevel.getCalleeTarget(caller, site, callee, receiver);
return new ApplyContext(baseCtxt, isNonNullArray);
result = new DelegatingContext(result, oneLevel.getCalleeTarget(caller, site, callee, receiver));
return result;
}
}
return baseCtxt;
return null;
}
}

View File

@ -17,30 +17,27 @@ 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;
}
@ -51,49 +48,46 @@ public class ObjectSensitivityContextSelector implements ContextSelector {
}
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] arguments) {
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]);
if (returnsThis(callee)) {
if (arguments.length > 1 && arguments[1] != null) {
return new ArgumentInstanceContext(1, arguments[1]);
}
}
return baseContext;
return null;
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
if (caller.getIR().getCalls(site)[0].getNumberOfUses() > 1) {
return IntSetUtil.make(new int[]{1}).union(base.getRelevantParameters(caller, site));
return IntSetUtil.make(new int[] { 1 });
} else {
return base.getRelevantParameters(caller, site);
return EmptyIntSet.instance;
}
}
}
class ArgumentInstanceContext implements Context {
private final Context base;
private final int index;
private final InstanceKey instanceKey;
public ArgumentInstanceContext(Context base, int index, InstanceKey instanceKey) {
this.base = base;
public ArgumentInstanceContext(int index, InstanceKey instanceKey) {
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 base.get(name);
return null;
}
@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;
@ -108,11 +102,6 @@ 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) {
@ -122,5 +111,5 @@ class ArgumentInstanceContext implements Context {
return false;
return true;
}
}

View File

@ -27,6 +27,7 @@ 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 {
@ -438,10 +439,8 @@ public final class LexicalScopingResolverContexts implements ContextSelector {
private class LexicalScopingResolverContext implements Context {
private final LexicalScopingResolver governingCallSites;
private final Context base;
public int hashCode() {
return base.hashCode() * (governingCallSites == null ? 1077651 : governingCallSites.hashCode());
return (governingCallSites == null ? 1077651 : governingCallSites.hashCode());
}
public boolean equals(Object o) {
@ -449,39 +448,35 @@ public final class LexicalScopingResolverContexts implements ContextSelector {
return true;
} else if (getClass().equals(o.getClass())) {
LexicalScopingResolverContext c = (LexicalScopingResolverContext) o;
return (base == null ? c.base == null : base.equals(c.base)) && (governingCallSites == c.governingCallSites);
return (governingCallSites == c.governingCallSites);
} else {
return false;
}
}
public ContextItem get(ContextKey name) {
return name.equals(RESOLVER) ? governingCallSites : base != null ? base.get(name) : null;
return name.equals(RESOLVER) ? governingCallSites: null;
}
private LexicalScopingResolverContext(LexicalScopingResolver governingCallSites, Context base) {
this.base = base;
private LexicalScopingResolverContext(LexicalScopingResolver governingCallSites) {
this.governingCallSites = governingCallSites;
}
private LexicalScopingResolverContext(CGNode source, CallSiteReference callSite, Context base) {
this.base = base;
private LexicalScopingResolverContext(CGNode source, CallSiteReference callSite) {
this.governingCallSites = findChild(source, callSite);
}
@Override
public String toString() {
return "LexicalScopingResolverContext [governingCallSites=" + governingCallSites + ", base=" + base + "]";
return "LexicalScopingResolverContext [governingCallSites=" + governingCallSites + "]";
}
}
private final ContextSelector base;
private final PropagationCallGraphBuilder builder;
public LexicalScopingResolverContexts(PropagationCallGraphBuilder builder, ContextSelector base) {
this.base = base;
public LexicalScopingResolverContexts(PropagationCallGraphBuilder builder) {
this.builder = builder;
}
@ -562,12 +557,11 @@ 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 baseContext;
return null;
}
}
LexicalScopingResolver resolver = (LexicalScopingResolver) caller.getContext().get(RESOLVER);
@ -581,23 +575,23 @@ public final class LexicalScopingResolverContexts implements ContextSelector {
}
if (caller.getMethod() instanceof AstMethod && hasExposedUses(caller, site)) {
LexicalScopingResolverContext result = new LexicalScopingResolverContext(caller, site, baseContext);
LexicalScopingResolverContext result = new LexicalScopingResolverContext(caller, site);
MapUtil.findOrCreateList(key2Contexts, key).add(result);
return result;
}
else if (resolver != null) {
LexicalScopingResolverContext result = new LexicalScopingResolverContext(resolver, baseContext);
LexicalScopingResolverContext result = new LexicalScopingResolverContext(resolver);
MapUtil.findOrCreateList(key2Contexts, key).add(result);
return result;
}
else {
return baseContext;
return null;
}
}
public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) {
return base.getRelevantParameters(caller, site);
return EmptyIntSet.instance;
}
}

View File

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

View File

@ -0,0 +1,92 @@
/*******************************************************************************
* 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,6 +13,7 @@ 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;
@ -66,6 +67,9 @@ 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,6 +13,7 @@ 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;
@ -24,6 +25,9 @@ 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;
/**