From d22ee36b09b8c0b473a95c31c7f25e3a96a7538c Mon Sep 17 00:00:00 2001 From: Karim Ali Date: Mon, 23 Oct 2017 17:43:28 -0600 Subject: [PATCH 1/2] adding some support for averroes - adding multi-flow AnalysisOption - enable/disable special handling of zero-length arrays Both are required to enable precise analysis of some Dacapo benchmarks when using the Averroes-generated summaries --- .../wala/ipa/callgraph/AnalysisOptions.java | 24 ++++++++++++-- .../AllocationSiteInNodeFactory.java | 32 ++++++++++++------- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/AnalysisOptions.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/AnalysisOptions.java index 36a0c7463..6d6264cb0 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/AnalysisOptions.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/AnalysisOptions.java @@ -71,7 +71,8 @@ public class AnalysisOptions { NO_METHOD_INVOKE("no_method_invoke", Integer.MAX_VALUE, true, false, false), NO_FLOW_TO_CASTS_NO_METHOD_INVOKE("no_flow_to_casts_no_method_invoke", 0, true, false, false), ONE_FLOW_TO_CASTS_NO_METHOD_INVOKE("one_flow_to_casts_no_method_invoke", 1, true, false, false), - ONE_FLOW_TO_CASTS_APPLICATION_GET_METHOD("one_flow_to_casts_application_get_method", 1, false, false, true), + ONE_FLOW_TO_CASTS_APPLICATION_GET_METHOD("one_flow_to_casts_application_get_method", 1, false, false, true), + MULTI_FLOW_TO_CASTS_APPLICATION_GET_METHOD("multi_flow_to_casts_application_get_method", 100, false, false, true), NO_STRING_CONSTANTS("no_string_constants", Integer.MAX_VALUE, false, true, false), NONE("none", 0, true, true, true); @@ -190,7 +191,12 @@ public class AnalysisOptions { * {@link ExplicitCallGraph}. */ private long maxNumberOfNodes = -1; - + + /** + * Should call graph construction handle arrays of zero-length differently? + */ + private boolean handleZeroLengthArray = true; + // SJF: I'm not sure these factories and caches belong here. // TODO: figure out how to clean this up. @@ -418,4 +424,18 @@ public class AnalysisOptions { public void setHandleStaticInit(boolean handleStaticInit) { this.handleStaticInit = handleStaticInit; } + + /** + * Should call graph construction handle arrays of zero-length differently? + */ + public boolean getHandleZeroLengthArray() { + return handleZeroLengthArray; + } + + /** + * Should call graph construction handle arrays of zero-length differently? + */ + public void setHandleZeroLengthArray(boolean handleZeroLengthArray) { + this.handleZeroLengthArray = handleZeroLengthArray; + } } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/AllocationSiteInNodeFactory.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/AllocationSiteInNodeFactory.java index e4e51b2da..93caa43c3 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/AllocationSiteInNodeFactory.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/AllocationSiteInNodeFactory.java @@ -25,15 +25,20 @@ import com.ibm.wala.ssa.SSANewInstruction; import com.ibm.wala.types.TypeReference; /** - * A factory which tries by default to create {@link InstanceKey}s which are {@link AllocationSiteInNode}s. + * A factory which tries by default to create {@link InstanceKey}s which are + * {@link AllocationSiteInNode}s. * * Notes: * */ public class AllocationSiteInNodeFactory implements InstanceKeyFactory { @@ -51,7 +56,8 @@ public class AllocationSiteInNodeFactory implements InstanceKeyFactory { private final ClassBasedInstanceKeys classBased; /** - * @param options Governing call graph construction options + * @param options + * Governing call graph construction options */ public AllocationSiteInNodeFactory(AnalysisOptions options, IClassHierarchy cha) { this.options = options; @@ -67,7 +73,7 @@ public class AllocationSiteInNodeFactory implements InstanceKeyFactory { } CGNode nodeToUse = node; - + // disallow recursion in contexts. if (node.getContext() instanceof ReceiverInstanceContext || node.getContext() instanceof CallerContext) { IMethod m = node.getMethod(); @@ -85,11 +91,15 @@ public class AllocationSiteInNodeFactory implements InstanceKeyFactory { if (ir.getSymbolTable().isIntegerConstant(lengthVN)) { Integer c = (Integer) ir.getSymbolTable().getConstantValue(lengthVN); if (c.intValue() == 0) { - return new ZeroLengthArrayInNode(nodeToUse, allocation, type); + if (options.getHandleZeroLengthArray()) { + return new ZeroLengthArrayInNode(nodeToUse, allocation, type); + } else { + return new NormalAllocationInNode(nodeToUse, allocation, type); + } } - } + } } - + InstanceKey key = new NormalAllocationInNode(nodeToUse, allocation, type); return key; From 423db824b33bec7b5a6119bc25e73d4c0785739f Mon Sep 17 00:00:00 2001 From: Karim Ali Date: Mon, 23 Oct 2017 17:54:01 -0600 Subject: [PATCH 2/2] adding support for the dynamic call graph experiments currentSite should be ThreadLocal because not having this screws up a lot of the instrumentation-based dynamic call graphs we generate for the shootout benchmarks. I have also conditionally changed how the string of the currentSite is created based on the output format that Julian came up with for the dynamic call graph. This support is necessary, because the Java std libraries are not instrumented. Therefore, they would appear as if calls from them show up from nowhere in the log that WALA generates for the dynamic call graph. This fix make those calls originate from a fake library BLOB node in the call graph. --- .../src/com/ibm/wala/shrike/cg/Runtime.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/Runtime.java b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/Runtime.java index acc0ff218..2244d9292 100644 --- a/com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/Runtime.java +++ b/com.ibm.wala.shrike/src/com/ibm/wala/shrike/cg/Runtime.java @@ -53,7 +53,7 @@ public class Runtime { private PrintWriter output; private SetOfClasses filter; private Policy handleCallback; - private String currentSite; + private ThreadLocal currentSite = new ThreadLocal<>(); private ThreadLocal> callStacks = new ThreadLocal>() { @@ -120,7 +120,7 @@ public class Runtime { } public static void execution(String klass, String method, Object receiver) { - runtime.currentSite = null; + runtime.currentSite.set(null); if (runtime.filter == null || ! runtime.filter.contains(bashToDescriptor(klass))) { if (runtime.output != null) { String caller = runtime.callStacks.get().peek(); @@ -164,23 +164,26 @@ public class Runtime { } public static void pop() { - if (runtime.currentSite != null) { + if (runtime.currentSite.get() != null) { synchronized (runtime) { if (runtime.output != null) { - runtime.output.printf("return from " + runtime.currentSite + "\n"); + runtime.output.printf("return from " + runtime.currentSite.get() + "\n"); runtime.output.flush(); } } - runtime.currentSite = null; + runtime.currentSite.set(null); } } public static void addToCallStack(String klass, String method, Object receiver) { - runtime.currentSite = klass + "\t" + method + "\t" + receiver; + String callerClass = runtime.callStacks.get().isEmpty() ? "BLOB" : runtime.callStacks.get().peek().split("\t")[0]; + String callerMethod = runtime.callStacks.get().isEmpty() ? "BLOB" : runtime.callStacks.get().peek().split("\t")[1]; + runtime.currentSite.set(callerClass + "\t" + callerMethod + "\t" + klass + "\t" + method + "\t" + receiver); +// runtime.currentSite = klass + "\t" + method + "\t" + receiver; synchronized (runtime) { if (runtime.output != null) { - runtime.output.printf("call to " + runtime.currentSite + "\n"); + runtime.output.printf("call to " + runtime.currentSite.get() + "\n"); runtime.output.flush(); } }