From fbbd401c9a95091bd3b6dcbc738e596243406d3d Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:42:47 +0000 Subject: [PATCH] Added optional object sensitivity for functions returning 'this'. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4384 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 4 + .../ObjectSensitivityContextSelector.java | 95 +++++++++++++++++++ 2 files changed, 99 insertions(+) mode change 100644 => 100755 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java create mode 100755 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java old mode 100644 new mode 100755 index 0c296b2e7..f6500096a --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -31,6 +31,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; public class JSZeroOrOneXCFABuilder extends JSCFABuilder { private static final boolean HANDLE_FUNCTION_APPLY = true; + private static final boolean USE_OBJECT_SENSITIVITY = true; public JSZeroOrOneXCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) { @@ -51,6 +52,9 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); contextSelector = new ScopeMappingKeysContextSelector(contextSelector); contextSelector = new JavaScriptConstructorContextSelector(contextSelector); + if (USE_OBJECT_SENSITIVITY) { + contextSelector = new ObjectSensitivityContextSelector(contextSelector); + } if (HANDLE_FUNCTION_APPLY) { contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java new file mode 100755 index 000000000..64e57b86d --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java @@ -0,0 +1,95 @@ +package com.ibm.wala.cast.js.ipa.callgraph; + +import java.util.HashMap; + +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.ContextItem; +import com.ibm.wala.ipa.callgraph.ContextKey; +import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.impl.Everywhere; +import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ssa.SSAInstruction; +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.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 returnsThis_cache = HashMapFactory.make(); + + // determine whether the method returns "this" + private boolean returnsThis(IMethod method) { + MethodReference mref = method.getReference(); + if(method.getNumberOfParameters() < 1) + return false; + Boolean b = returnsThis_cache.get(mref); + 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) { + returnsThis_cache.put(mref, true); + return true; + } + } + } + returnsThis_cache.put(mref, false); + return false; + } + + @Override + 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]); + } + } + return baseContext; + } + + @Override + 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)); + } else { + return base.getRelevantParameters(caller, site); + } + } + +} + +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; + this.index = index; + this.instanceKey = instanceKey; + } + + @Override + public ContextItem get(ContextKey name) { + /*if(name == ContextKey.RECEIVER && index == 1) + return instanceKey;*/ + if(name == ContextKey.PARAMETERS[index]) + return new FilteredPointerKey.SingleInstanceFilter(instanceKey); + return base.get(name); + } + +} \ No newline at end of file