From dc5c4d066a7bd19bd440c2c4b3de1b0ab17c3966 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Fri, 15 Dec 2017 20:00:30 -0500 Subject: [PATCH 1/9] Ignore instances from internal API calls. --- .../core/analysis/StreamStateMachine.java | 31 ++------ .../streamrefactoring/core/analysis/Util.java | 21 ++++++ .../core/safe/ClientSlicingUniqueSolver.java | 71 +++++++++++++++++++ .../core/safe/TypestateSolverFactory.java | 2 +- 4 files changed, 99 insertions(+), 26 deletions(-) create mode 100644 edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/ClientSlicingUniqueSolver.java diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java index 6d626c99..a1ad2862 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java @@ -56,8 +56,6 @@ import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode; import com.ibm.wala.ipa.callgraph.propagation.PointerKey; -import com.ibm.wala.ipa.callgraph.propagation.cfa.CallStringContext; -import com.ibm.wala.ipa.callgraph.propagation.cfa.CallStringContextSelector; import com.ibm.wala.ipa.cfg.BasicBlockInContext; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.modref.ModRef; @@ -415,7 +413,7 @@ public void start() throws IOException, CoreException, CallGraphBuilderCancelExc // fill the instance to predecessors map. for (Iterator it = result.iterateInstances(); it.hasNext();) { InstanceKey instance = it.next(); - CallStringWithReceivers callString = getCallString(instance); + CallStringWithReceivers callString = Util.getCallString(instance); Set possibleReceivers = new HashSet<>(callString.getPossibleReceivers()); // get any additional receivers if necessary #36. @@ -526,7 +524,7 @@ private static Collection getAdditionalNecessaryReceivers Collection ret = new HashSet<>(); LOGGER.fine(() -> "Instance is: " + instance); - CallStringWithReceivers callString = getCallString(instance); + CallStringWithReceivers callString = Util.getCallString(instance); // for each method in the call string. for (IMethod calledMethod : callString.getMethods()) { @@ -550,7 +548,7 @@ private static Collection getAdditionalNecessaryReceivers LOGGER.fine(() -> "Found node: " + node); // try to get its CallStringWithReceivers. - CallStringWithReceivers calledMethodCallString = getCallString(node); + CallStringWithReceivers calledMethodCallString = Util.getCallString(node); // what are its receivers? Set possibleReceivers = calledMethodCallString.getPossibleReceivers(); @@ -602,7 +600,7 @@ private static void discoverPossibleStatefulIntermediateOperations(AggregateSolv if (!isStreamCreatedFromIntermediateOperation(instance, hierarchy, callGraph)) continue; - CallStringWithReceivers callString = getCallString(instance); + CallStringWithReceivers callString = Util.getCallString(instance); boolean found = false; for (CallSiteReference callSiteReference : callString.getCallSiteRefs()) { @@ -864,7 +862,7 @@ private void discoverPossibleSideEffects(AggregateSolverResult result, engine.getCallGraph())) continue; - CallStringWithReceivers callString = getCallString(instance); + CallStringWithReceivers callString = Util.getCallString(instance); CallSiteReference[] callSiteRefs = callString.getCallSiteRefs(); assert callSiteRefs.length == 2 : "Expecting call sites two-deep."; @@ -1026,7 +1024,7 @@ private static boolean filterPointerKey(PointerKey pointerKey, EclipseProjectAna private static boolean isStreamCreatedFromIntermediateOperation(InstanceKey instance, IClassHierarchy hierarchy, CallGraph callGraph) throws IOException, CoreException { // Get the immediate possible receivers of the stream instance. - Set receivers = getCallString(instance).getPossibleReceivers(); + Set receivers = Util.getCallString(instance).getPossibleReceivers(); // Get any additional receivers we need to consider. Collection additionalReceivers = getAdditionalNecessaryReceiversFromPredecessors( @@ -1045,23 +1043,6 @@ private static boolean isStreamCreatedFromIntermediateOperation(InstanceKey inst }); } - private static CallStringWithReceivers getCallString(InstanceKey instance) { - NormalAllocationInNode allocationInNode = (NormalAllocationInNode) instance; - return getCallString(allocationInNode); - } - - private static CallStringWithReceivers getCallString(NormalAllocationInNode allocationInNode) { - CGNode node = allocationInNode.getNode(); - return getCallString(node); - } - - private static CallStringWithReceivers getCallString(CGNode node) { - CallStringContext context = (CallStringContext) node.getContext(); - CallStringWithReceivers callString = (CallStringWithReceivers) context - .get(CallStringContextSelector.CALL_STRING); - return callString; - } - /** * The typestate rules to use. */ diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java index 2f4c7c67..9dfba5e2 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java @@ -36,8 +36,11 @@ import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint; import com.ibm.wala.ipa.callgraph.propagation.HeapModel; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; import com.ibm.wala.ipa.callgraph.propagation.PointerKey; +import com.ibm.wala.ipa.callgraph.propagation.cfa.CallStringContext; +import com.ibm.wala.ipa.callgraph.propagation.cfa.CallStringContextSelector; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.shrikeCT.InvalidClassFileException; import com.ibm.wala.ssa.IR; @@ -56,6 +59,7 @@ import edu.cuny.hunter.streamrefactoring.core.utils.LoggerNames; import edu.cuny.hunter.streamrefactoring.core.wala.AnalysisUtils; +import edu.cuny.hunter.streamrefactoring.core.wala.CallStringWithReceivers; public final class Util { @@ -451,4 +455,21 @@ public static Set findEntryPoints(IClassHierarchy classHierarchy) th return result; } + + public static CallStringWithReceivers getCallString(InstanceKey instance) { + NormalAllocationInNode allocationInNode = (NormalAllocationInNode) instance; + return getCallString(allocationInNode); + } + + public static CallStringWithReceivers getCallString(NormalAllocationInNode allocationInNode) { + CGNode node = allocationInNode.getNode(); + return getCallString(node); + } + + public static CallStringWithReceivers getCallString(CGNode node) { + CallStringContext context = (CallStringContext) node.getContext(); + CallStringWithReceivers callString = (CallStringWithReceivers) context + .get(CallStringContextSelector.CALL_STRING); + return callString; + } } diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/ClientSlicingUniqueSolver.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/ClientSlicingUniqueSolver.java new file mode 100644 index 00000000..e653632c --- /dev/null +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/ClientSlicingUniqueSolver.java @@ -0,0 +1,71 @@ +package edu.cuny.hunter.streamrefactoring.core.safe; + +import java.util.Collection; +import java.util.logging.Logger; + +import com.ibm.safe.internal.exceptions.PropertiesException; +import com.ibm.safe.reporting.IReporter; +import com.ibm.safe.typestate.core.BenignOracle; +import com.ibm.safe.typestate.merge.IMergeFunctionFactory; +import com.ibm.safe.typestate.metrics.TypeStateMetrics; +import com.ibm.safe.typestate.mine.TraceReporter; +import com.ibm.safe.typestate.options.TypeStateOptions; +import com.ibm.safe.typestate.rules.ITypeStateDFA; +import com.ibm.safe.typestate.unique.UniqueSolver; +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.escape.ILiveObjectAnalysis; +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; +import com.ibm.wala.types.MethodReference; +import com.ibm.wala.types.TypeName; +import com.ibm.wala.types.TypeReference; +import com.ibm.wala.util.strings.Atom; + +import edu.cuny.hunter.streamrefactoring.core.analysis.Util; +import edu.cuny.hunter.streamrefactoring.core.utils.LoggerNames; +import edu.cuny.hunter.streamrefactoring.core.wala.CallStringWithReceivers; + +/** + * A solver that only tracks instances created from client (non-JDK) calls. + * + * @author Raffi Khatchadourian + */ +public class ClientSlicingUniqueSolver extends UniqueSolver { + + private static final Logger LOGGER = Logger.getLogger(LoggerNames.LOGGER_NAME); + + public ClientSlicingUniqueSolver(CallGraph cg, PointerAnalysis pointerAnalysis, ITypeStateDFA dfa, + TypeStateOptions options, ILiveObjectAnalysis live, BenignOracle ora, TypeStateMetrics metrics, + IReporter reporter, TraceReporter traceReporter, IMergeFunctionFactory mergeFactory) { + super(cg, pointerAnalysis, dfa, options, live, ora, metrics, reporter, traceReporter, mergeFactory); + } + + @Override + protected Collection computeTrackedInstances() throws PropertiesException { + Collection instances = super.computeTrackedInstances(); + + for (InstanceKey instanceKey : instances) { + CallStringWithReceivers callString = Util.getCallString(instanceKey); + IMethod[] callingMethods = callString.getMethods(); + IMethod outerMostCallingMethod = callingMethods[1]; + MethodReference reference = outerMostCallingMethod.getReference(); + TypeReference declaringClass = reference.getDeclaringClass(); + TypeName name = declaringClass.getName(); + Atom classPackage = name.getPackage(); + boolean isFromAPI = classPackage.startsWith(Atom.findOrCreateAsciiAtom("java")); + + // if it's being called from the API. + if (isFromAPI) { + // remove it. + LOGGER.info(() -> "Removing instance: " + instanceKey); + instances.remove(instanceKey); + } + } + + return instances; + } + +} diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/TypestateSolverFactory.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/TypestateSolverFactory.java index 7f34818b..4fff856c 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/TypestateSolverFactory.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/TypestateSolverFactory.java @@ -49,7 +49,7 @@ public static ISafeSolver getSolver(AnalysisOptions domoOptions, CallGraph cg, throws PropertiesException, CancelException { IMergeFunctionFactory mergeFactory = makeMergeFactory(options, TypeStateSolverKind.UNIQUE); ILiveObjectAnalysis live = getLiveObjectAnalysis(cg, hg, options); - return new UniqueSolver(cg, pointerAnalysis, dfa, options, live, ora, metrics, reporter, traceReporter, mergeFactory); + return new ClientSlicingUniqueSolver(cg, pointerAnalysis, dfa, options, live, ora, metrics, reporter, traceReporter, mergeFactory); } protected static ILiveObjectAnalysis getLiveObjectAnalysis(CallGraph cg, HeapGraph hg, TypeStateOptions options) From f49c6b899fdcb9a07e92c2f840b20ee5bdacc89d Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Fri, 15 Dec 2017 20:01:18 -0500 Subject: [PATCH 2/9] Formatting. --- .../core/analysis/StreamStateMachine.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java index a1ad2862..25a4a7bc 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java @@ -174,8 +174,8 @@ class StreamStateMachine { // @formatter:on /** - * A table mapping an instance and a block to the instance's possible states at - * that block. + * A table mapping an instance and a block to the instance's possible states + * at that block. */ private static Table, Map>> instanceBlockStateTable = HashBasedTable .create(); @@ -987,11 +987,12 @@ private static void discoverLambdaSideEffects(EclipseProjectAnalysisEnginetrue if the given {@link PointerKey} should be filtered - * and false otherwise. - * @apiNote The current filtering mechanism excludes field {@link PointerKey}s - * whose instance is being assigned with the stream package. Basically, - * we are looking for modifications to the client code, + * @return true if the given {@link PointerKey} should be + * filtered and false otherwise. + * @apiNote The current filtering mechanism excludes field + * {@link PointerKey}s whose instance is being assigned with the + * stream package. Basically, we are looking for modifications to + * the client code, */ private static boolean filterPointerKey(PointerKey pointerKey, EclipseProjectAnalysisEngine engine) { Boolean ret = null; @@ -1067,17 +1068,17 @@ protected static StreamAttributeTypestateRule[] createStreamAttributeTypestateRu * represented by the given call graph node in the given supergraph. * * @param block - * The block in which to find the corresponding block in context in - * the supergraph. + * The block in which to find the corresponding block in context + * in the supergraph. * @param cgNode - * The call graph node representing the procedure that contains the - * block. + * The call graph node representing the procedure that contains + * the block. * @param supergraph * The supergraph in which to look up the corresponding block in * context. - * @return The block in context in the given supergraph that corresponds to the - * given block with the procedure represented by the given call graph - * node. + * @return The block in context in the given supergraph that corresponds to + * the given block with the procedure represented by the given call + * graph node. */ private static Optional> getBasicBlockInContextForBlock( ISSABasicBlock block, CGNode cgNode, ICFGSupergraph supergraph) { From b665e722103341e1d1847cfff363d3e475b7a12b Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Fri, 15 Dec 2017 20:01:27 -0500 Subject: [PATCH 3/9] TODO. --- .../streamrefactoring/core/analysis/StreamStateMachine.java | 1 + 1 file changed, 1 insertion(+) diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java index 25a4a7bc..e4999997 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java @@ -237,6 +237,7 @@ public void start() throws IOException, CoreException, CallGraphBuilderCancelExc new PropertiesManager.IPropertyDescriptor[] { WholeProgramProperties.Props.LIVE_ANALYSIS }); TypeStateOptions typeStateOptions = new TypeStateOptions(manager); typeStateOptions.setBooleanValue(WholeProgramProperties.Props.LIVE_ANALYSIS.getName(), false); + // TODO: #127 should also set entry points. TypeReference typeReference = this.getStream().getTypeReference(); IClass streamClass = engine.getClassHierarchy().lookupClass(typeReference); From 95b0ddf0e4ec530c922a11646c06dbff19a11467 Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Sat, 16 Dec 2017 08:33:39 -0500 Subject: [PATCH 4/9] Use iterator. --- .../core/safe/ClientSlicingUniqueSolver.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/ClientSlicingUniqueSolver.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/ClientSlicingUniqueSolver.java index e653632c..4584c17a 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/ClientSlicingUniqueSolver.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/ClientSlicingUniqueSolver.java @@ -1,6 +1,7 @@ package edu.cuny.hunter.streamrefactoring.core.safe; import java.util.Collection; +import java.util.Iterator; import java.util.logging.Logger; import com.ibm.safe.internal.exceptions.PropertiesException; @@ -34,7 +35,7 @@ * @author Raffi Khatchadourian */ public class ClientSlicingUniqueSolver extends UniqueSolver { - + private static final Logger LOGGER = Logger.getLogger(LoggerNames.LOGGER_NAME); public ClientSlicingUniqueSolver(CallGraph cg, PointerAnalysis pointerAnalysis, ITypeStateDFA dfa, @@ -46,8 +47,9 @@ public ClientSlicingUniqueSolver(CallGraph cg, PointerAnalysis pointerAnalysis, @Override protected Collection computeTrackedInstances() throws PropertiesException { Collection instances = super.computeTrackedInstances(); - - for (InstanceKey instanceKey : instances) { + + for (Iterator iterator = instances.iterator(); iterator.hasNext();) { + InstanceKey instanceKey = iterator.next(); CallStringWithReceivers callString = Util.getCallString(instanceKey); IMethod[] callingMethods = callString.getMethods(); IMethod outerMostCallingMethod = callingMethods[1]; @@ -56,15 +58,15 @@ protected Collection computeTrackedInstances() throws PropertiesExc TypeName name = declaringClass.getName(); Atom classPackage = name.getPackage(); boolean isFromAPI = classPackage.startsWith(Atom.findOrCreateAsciiAtom("java")); - + // if it's being called from the API. if (isFromAPI) { // remove it. LOGGER.info(() -> "Removing instance: " + instanceKey); - instances.remove(instanceKey); + iterator.remove(); } } - + return instances; } From 2ac6beacd34d4f3030e8e61c8af6301e6643664c Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Sat, 16 Dec 2017 08:34:36 -0500 Subject: [PATCH 5/9] Add control test. --- .../testNonInternalAPI7/in/A.java | 14 ++++++++++++++ .../ConvertStreamToParallelRefactoringTest.java | 11 +++++++++++ 2 files changed, 25 insertions(+) create mode 100644 edu.cuny.hunter.streamrefactoring.tests/resources/ConvertStreamToParallel/testNonInternalAPI7/in/A.java diff --git a/edu.cuny.hunter.streamrefactoring.tests/resources/ConvertStreamToParallel/testNonInternalAPI7/in/A.java b/edu.cuny.hunter.streamrefactoring.tests/resources/ConvertStreamToParallel/testNonInternalAPI7/in/A.java new file mode 100644 index 00000000..d30ce3c2 --- /dev/null +++ b/edu.cuny.hunter.streamrefactoring.tests/resources/ConvertStreamToParallel/testNonInternalAPI7/in/A.java @@ -0,0 +1,14 @@ +package p; + +import java.util.HashSet; +import java.util.stream.*; + +import edu.cuny.hunter.streamrefactoring.annotations.*; + +class A { + + @EntryPoint + void n() { + new HashSet<>().stream().sorted().distinct().count(); + } +} \ No newline at end of file diff --git a/edu.cuny.hunter.streamrefactoring.tests/test cases/edu/cuny/hunter/streamrefactoring/ui/tests/ConvertStreamToParallelRefactoringTest.java b/edu.cuny.hunter.streamrefactoring.tests/test cases/edu/cuny/hunter/streamrefactoring/ui/tests/ConvertStreamToParallelRefactoringTest.java index 29a9b912..c06308c2 100644 --- a/edu.cuny.hunter.streamrefactoring.tests/test cases/edu/cuny/hunter/streamrefactoring/ui/tests/ConvertStreamToParallelRefactoringTest.java +++ b/edu.cuny.hunter.streamrefactoring.tests/test cases/edu/cuny/hunter/streamrefactoring/ui/tests/ConvertStreamToParallelRefactoringTest.java @@ -507,6 +507,17 @@ public void testNonInternalAPI6() throws Exception { RefactoringStatus.ERROR, EnumSet.of(PreconditionFailure.INCONSISTENT_POSSIBLE_EXECUTION_MODES))); } + /** + * This is a control to testNonInternalAPI4. + */ + public void testNonInternalAPI7() throws Exception { + helper(new StreamAnalysisExpectedResult("new HashSet<>().stream()", + Collections.singleton(ExecutionMode.SEQUENTIAL), EnumSet.of(Ordering.ORDERED), false, true, false, + EnumSet.of(TransformationAction.UNORDER, TransformationAction.CONVERT_TO_PARALLEL), + PreconditionSuccess.P3, Refactoring.CONVERT_SEQUENTIAL_STREAM_TO_PARALLEL, RefactoringStatus.OK, + Collections.emptySet())); + } + public void testCollectionFromParameter() throws Exception { helper(new StreamAnalysisExpectedResult("h.parallelStream()", Collections.singleton(ExecutionMode.PARALLEL), Collections.singleton(Ordering.UNORDERED), false, true, false, null, null, null, From ef42b01a717634f082e6c7733600465453e95edc Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Sat, 16 Dec 2017 08:34:50 -0500 Subject: [PATCH 6/9] Formatting. --- ...onvertStreamToParallelRefactoringTest.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/edu.cuny.hunter.streamrefactoring.tests/test cases/edu/cuny/hunter/streamrefactoring/ui/tests/ConvertStreamToParallelRefactoringTest.java b/edu.cuny.hunter.streamrefactoring.tests/test cases/edu/cuny/hunter/streamrefactoring/ui/tests/ConvertStreamToParallelRefactoringTest.java index c06308c2..ecc2426f 100644 --- a/edu.cuny.hunter.streamrefactoring.tests/test cases/edu/cuny/hunter/streamrefactoring/ui/tests/ConvertStreamToParallelRefactoringTest.java +++ b/edu.cuny.hunter.streamrefactoring.tests/test cases/edu/cuny/hunter/streamrefactoring/ui/tests/ConvertStreamToParallelRefactoringTest.java @@ -59,7 +59,8 @@ public class ConvertStreamToParallelRefactoringTest extends RefactoringTest { /** - * The name of the directory containing resources under the project directory. + * The name of the directory containing resources under the project + * directory. */ private static final String RESOURCE_PATH = "resources"; @@ -223,9 +224,10 @@ private Path getAbsolutionPath(String fileName) { * * @see * org.eclipse.jdt.ui.tests.refactoring.RefactoringTest#getFileContents(java - * .lang.String) Had to override this method because, since this plug-in is a - * fragment (at least I think that this is the reason), it doesn't have an - * activator and the bundle is resolving to the eclipse refactoring test bundle. + * .lang.String) Had to override this method because, since this plug-in is + * a fragment (at least I think that this is the reason), it doesn't have an + * activator and the bundle is resolving to the eclipse refactoring test + * bundle. */ @Override public String getFileContents(String fileName) throws IOException { @@ -452,8 +454,7 @@ public void testHashSetParallelStream2() throws Exception { public void testNonInternalAPI() throws Exception { helper(new StreamAnalysisExpectedResult("new HashSet<>().parallelStream()", Collections.singleton(ExecutionMode.PARALLEL), Collections.singleton(Ordering.UNORDERED), false, false, - false, null, null, null, RefactoringStatus.ERROR, - EnumSet.of(PreconditionFailure.UNORDERED))); + false, null, null, null, RefactoringStatus.ERROR, EnumSet.of(PreconditionFailure.UNORDERED))); } public void testNonInternalAPI2() throws Exception { @@ -462,14 +463,14 @@ public void testNonInternalAPI2() throws Exception { false, Collections.singleton(TransformationAction.CONVERT_TO_PARALLEL), PreconditionSuccess.P1, Refactoring.CONVERT_SEQUENTIAL_STREAM_TO_PARALLEL, RefactoringStatus.OK, Collections.emptySet())); } - + public void testNonInternalAPI3() throws Exception { helper(new StreamAnalysisExpectedResult("new HashSet<>().stream()", - Collections.singleton(ExecutionMode.SEQUENTIAL), Collections.singleton(Ordering.UNORDERED), false, true, + Collections.singleton(ExecutionMode.SEQUENTIAL), Collections.singleton(Ordering.UNORDERED), false, true, false, Collections.singleton(TransformationAction.CONVERT_TO_PARALLEL), PreconditionSuccess.P1, Refactoring.CONVERT_SEQUENTIAL_STREAM_TO_PARALLEL, RefactoringStatus.OK, Collections.emptySet())); } - + /** * related to #126 */ @@ -482,19 +483,19 @@ public void testNonInternalAPI4() throws Exception { Collections.singleton(ExecutionMode.SEQUENTIAL), orderings, false, true, false, null, null, null, RefactoringStatus.ERROR, EnumSet.of(PreconditionFailure.INCONSISTENT_POSSIBLE_ORDERINGS))); } - + /** * related to #126 */ public void testNonInternalAPI5() throws Exception { HashSet executionModes = new HashSet<>(); - executionModes .add(ExecutionMode.PARALLEL); - executionModes .add(ExecutionMode.SEQUENTIAL); + executionModes.add(ExecutionMode.PARALLEL); + executionModes.add(ExecutionMode.SEQUENTIAL); helper(new StreamAnalysisExpectedResult("new HashSet<>().stream()", executionModes, Collections.singleton(Ordering.UNORDERED), false, true, false, null, null, null, RefactoringStatus.ERROR, EnumSet.of(PreconditionFailure.INCONSISTENT_POSSIBLE_EXECUTION_MODES))); } - + /** * related to #126 */ @@ -506,7 +507,7 @@ public void testNonInternalAPI6() throws Exception { Collections.singleton(Ordering.UNORDERED), false, true, false, null, null, null, RefactoringStatus.ERROR, EnumSet.of(PreconditionFailure.INCONSISTENT_POSSIBLE_EXECUTION_MODES))); } - + /** * This is a control to testNonInternalAPI4. */ From ade57b38fc65e5d1eaf7a8bc561e3e70684b5f5a Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Mon, 18 Dec 2017 10:56:26 -0500 Subject: [PATCH 7/9] Use global logger. --- .../core/analysis/Stream.java | 2 +- .../core/analysis/StreamStateMachine.java | 2 +- .../streamrefactoring/core/analysis/Util.java | 21 ++++++++++--------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Stream.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Stream.java index 5ac3f6d9..33da8001 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Stream.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Stream.java @@ -593,7 +593,7 @@ private void inferInitialOrdering() throws IOException, CoreException, ClassHier try { possibleTypes = getPossibleTypesInterprocedurally(node, valueNumber, this.getAnalysisEngine().getHeapGraph().getHeapModel(), - this.getAnalysisEngine().getPointerAnalysis(), this, LOGGER); + this.getAnalysisEngine().getPointerAnalysis(), this); // Possible types: check each one. calledMethod = (IMethod) calledMethodBinding.getJavaElement(); diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java index e4999997..e5607590 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java @@ -644,7 +644,7 @@ private void discoverIfReduceOrderingPossiblyMatters( possibleReturnTypes = Util.getPossibleTypesInterprocedurally(block.getNode(), returnValue, this.getStream().getAnalysisEngine().getHeapGraph().getHeapModel(), - this.getStream().getAnalysisEngine().getPointerAnalysis(), this.getStream(), LOGGER); + this.getStream().getAnalysisEngine().getPointerAnalysis(), this.getStream()); LOGGER.info("Possible reduce types are: " + possibleReturnTypes); } else { diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java index 9dfba5e2..a3358ad5 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java @@ -201,22 +201,22 @@ static String getBinaryName(TypeReference typeReference) { } public static Collection getPossibleTypesInterprocedurally(CGNode node, int valueNumber, - HeapModel heapModel, PointerAnalysis pointerAnalysis, Stream stream, Logger logger) + HeapModel heapModel, PointerAnalysis pointerAnalysis, Stream stream) throws NoniterableException, NoninstantiableException, CannotExtractSpliteratorException { Collection ret = new HashSet<>(); PointerKey valueKey = heapModel.getPointerKeyForLocal(node, valueNumber); - logger.fine(() -> "Value pointer key is: " + valueKey); + LOGGER.fine(() -> "Value pointer key is: " + valueKey); OrdinalSet pointsToSet = pointerAnalysis.getPointsToSet(valueKey); assert pointsToSet != null; - logger.fine(() -> "PointsTo set is: " + pointsToSet); + LOGGER.fine(() -> "PointsTo set is: " + pointsToSet); for (InstanceKey instanceKey : pointsToSet) { IClass concreteClass = instanceKey.getConcreteType(); if (!(concreteClass instanceof SyntheticClass)) { - logger.fine(() -> "Found non-synthetic concrete type: " + concreteClass); + LOGGER.fine(() -> "Found non-synthetic concrete type: " + concreteClass); // Workaround #38, problem seemingly with generics. // Due to type erasure, we may have the problem if the return @@ -413,7 +413,7 @@ private static boolean matches(TypeReference methodDeclaringType, MethodReferenc public static JDTIdentityMapper getJDTIdentifyMapper(ASTNode node) { return new JDTIdentityMapper(JavaSourceAnalysisScope.SOURCE, node.getAST()); } - + /** * check whether the annotation is "EntryPoint" */ @@ -425,9 +425,10 @@ private static boolean isEntryPointClass(TypeName typeName) { * Find all annotations in test cases and check whether they are "entry point". * If yes, call DefaultEntrypoint to get entry point, then, add it into the * result set. - * @throws InvalidClassFileException + * + * @throws InvalidClassFileException */ - public static Set findEntryPoints(IClassHierarchy classHierarchy) throws InvalidClassFileException { + public static Set findEntryPoints(IClassHierarchy classHierarchy) throws InvalidClassFileException { final Set result = new HashSet<>(); Iterator classIterator = classHierarchy.iterator(); while (classIterator.hasNext()) { @@ -437,7 +438,7 @@ public static Set findEntryPoints(IClassHierarchy classHierarchy) th // iterate over all declared methods for (com.ibm.wala.classLoader.IMethod method : klass.getDeclaredMethods()) { - // if method has an annotation + // if method has an annotation if (!(method instanceof ShrikeCTMethod)) { throw new IllegalArgumentException("@EntryPoint only works for byte code."); } @@ -452,10 +453,10 @@ public static Set findEntryPoints(IClassHierarchy classHierarchy) th } } } - + return result; } - + public static CallStringWithReceivers getCallString(InstanceKey instance) { NormalAllocationInNode allocationInNode = (NormalAllocationInNode) instance; return getCallString(allocationInNode); From 6286ed82305c3548d7dbc3484bcd2448aab79dac Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Mon, 18 Dec 2017 10:56:33 -0500 Subject: [PATCH 8/9] Formatting. --- .../core/analysis/StreamStateMachine.java | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java index e5607590..a4262197 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java @@ -174,8 +174,8 @@ class StreamStateMachine { // @formatter:on /** - * A table mapping an instance and a block to the instance's possible states - * at that block. + * A table mapping an instance and a block to the instance's possible states at + * that block. */ private static Table, Map>> instanceBlockStateTable = HashBasedTable .create(); @@ -988,12 +988,11 @@ private static void discoverLambdaSideEffects(EclipseProjectAnalysisEnginetrue if the given {@link PointerKey} should be - * filtered and false otherwise. - * @apiNote The current filtering mechanism excludes field - * {@link PointerKey}s whose instance is being assigned with the - * stream package. Basically, we are looking for modifications to - * the client code, + * @return true if the given {@link PointerKey} should be filtered + * and false otherwise. + * @apiNote The current filtering mechanism excludes field {@link PointerKey}s + * whose instance is being assigned with the stream package. Basically, + * we are looking for modifications to the client code, */ private static boolean filterPointerKey(PointerKey pointerKey, EclipseProjectAnalysisEngine engine) { Boolean ret = null; @@ -1069,17 +1068,17 @@ protected static StreamAttributeTypestateRule[] createStreamAttributeTypestateRu * represented by the given call graph node in the given supergraph. * * @param block - * The block in which to find the corresponding block in context - * in the supergraph. + * The block in which to find the corresponding block in context in + * the supergraph. * @param cgNode - * The call graph node representing the procedure that contains - * the block. + * The call graph node representing the procedure that contains the + * block. * @param supergraph * The supergraph in which to look up the corresponding block in * context. - * @return The block in context in the given supergraph that corresponds to - * the given block with the procedure represented by the given call - * graph node. + * @return The block in context in the given supergraph that corresponds to the + * given block with the procedure represented by the given call graph + * node. */ private static Optional> getBasicBlockInContextForBlock( ISSABasicBlock block, CGNode cgNode, ICFGSupergraph supergraph) { From 7c056b4c5d9bcfa8be1afe6897410515fa2f6aba Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Mon, 18 Dec 2017 11:02:05 -0500 Subject: [PATCH 9/9] Go pack to using the UniqueSolver. Can't get the slicing working. --- .../streamrefactoring/core/safe/TypestateSolverFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/TypestateSolverFactory.java b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/TypestateSolverFactory.java index 4fff856c..7f34818b 100644 --- a/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/TypestateSolverFactory.java +++ b/edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/safe/TypestateSolverFactory.java @@ -49,7 +49,7 @@ public static ISafeSolver getSolver(AnalysisOptions domoOptions, CallGraph cg, throws PropertiesException, CancelException { IMergeFunctionFactory mergeFactory = makeMergeFactory(options, TypeStateSolverKind.UNIQUE); ILiveObjectAnalysis live = getLiveObjectAnalysis(cg, hg, options); - return new ClientSlicingUniqueSolver(cg, pointerAnalysis, dfa, options, live, ora, metrics, reporter, traceReporter, mergeFactory); + return new UniqueSolver(cg, pointerAnalysis, dfa, options, live, ora, metrics, reporter, traceReporter, mergeFactory); } protected static ILiveObjectAnalysis getLiveObjectAnalysis(CallGraph cg, HeapGraph hg, TypeStateOptions options)