Skip to content

Commit 985af03

Browse files
authored
Merge pull request #128 from ponder-lab/issue_103
Some work on #126.
2 parents 6b0061c + 7c056b4 commit 985af03

File tree

6 files changed

+153
-50
lines changed

6 files changed

+153
-50
lines changed

edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Stream.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ private void inferInitialOrdering() throws IOException, CoreException, ClassHier
593593
try {
594594
possibleTypes = getPossibleTypesInterprocedurally(node, valueNumber,
595595
this.getAnalysisEngine().getHeapGraph().getHeapModel(),
596-
this.getAnalysisEngine().getPointerAnalysis(), this, LOGGER);
596+
this.getAnalysisEngine().getPointerAnalysis(), this);
597597

598598
// Possible types: check each one.
599599
calledMethod = (IMethod) calledMethodBinding.getJavaElement();

edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/StreamStateMachine.java

+8-26
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@
5656
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
5757
import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode;
5858
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
59-
import com.ibm.wala.ipa.callgraph.propagation.cfa.CallStringContext;
60-
import com.ibm.wala.ipa.callgraph.propagation.cfa.CallStringContextSelector;
6159
import com.ibm.wala.ipa.cfg.BasicBlockInContext;
6260
import com.ibm.wala.ipa.cha.IClassHierarchy;
6361
import com.ibm.wala.ipa.modref.ModRef;
@@ -239,6 +237,7 @@ public void start() throws IOException, CoreException, CallGraphBuilderCancelExc
239237
new PropertiesManager.IPropertyDescriptor[] { WholeProgramProperties.Props.LIVE_ANALYSIS });
240238
TypeStateOptions typeStateOptions = new TypeStateOptions(manager);
241239
typeStateOptions.setBooleanValue(WholeProgramProperties.Props.LIVE_ANALYSIS.getName(), false);
240+
// TODO: #127 should also set entry points.
242241

243242
TypeReference typeReference = this.getStream().getTypeReference();
244243
IClass streamClass = engine.getClassHierarchy().lookupClass(typeReference);
@@ -415,7 +414,7 @@ public void start() throws IOException, CoreException, CallGraphBuilderCancelExc
415414
// fill the instance to predecessors map.
416415
for (Iterator<InstanceKey> it = result.iterateInstances(); it.hasNext();) {
417416
InstanceKey instance = it.next();
418-
CallStringWithReceivers callString = getCallString(instance);
417+
CallStringWithReceivers callString = Util.getCallString(instance);
419418
Set<InstanceKey> possibleReceivers = new HashSet<>(callString.getPossibleReceivers());
420419

421420
// get any additional receivers if necessary #36.
@@ -526,7 +525,7 @@ private static Collection<? extends InstanceKey> getAdditionalNecessaryReceivers
526525
Collection<InstanceKey> ret = new HashSet<>();
527526
LOGGER.fine(() -> "Instance is: " + instance);
528527

529-
CallStringWithReceivers callString = getCallString(instance);
528+
CallStringWithReceivers callString = Util.getCallString(instance);
530529

531530
// for each method in the call string.
532531
for (IMethod calledMethod : callString.getMethods()) {
@@ -550,7 +549,7 @@ private static Collection<? extends InstanceKey> getAdditionalNecessaryReceivers
550549
LOGGER.fine(() -> "Found node: " + node);
551550

552551
// try to get its CallStringWithReceivers.
553-
CallStringWithReceivers calledMethodCallString = getCallString(node);
552+
CallStringWithReceivers calledMethodCallString = Util.getCallString(node);
554553

555554
// what are its receivers?
556555
Set<InstanceKey> possibleReceivers = calledMethodCallString.getPossibleReceivers();
@@ -602,7 +601,7 @@ private static void discoverPossibleStatefulIntermediateOperations(AggregateSolv
602601
if (!isStreamCreatedFromIntermediateOperation(instance, hierarchy, callGraph))
603602
continue;
604603

605-
CallStringWithReceivers callString = getCallString(instance);
604+
CallStringWithReceivers callString = Util.getCallString(instance);
606605

607606
boolean found = false;
608607
for (CallSiteReference callSiteReference : callString.getCallSiteRefs()) {
@@ -645,7 +644,7 @@ private void discoverIfReduceOrderingPossiblyMatters(
645644

646645
possibleReturnTypes = Util.getPossibleTypesInterprocedurally(block.getNode(), returnValue,
647646
this.getStream().getAnalysisEngine().getHeapGraph().getHeapModel(),
648-
this.getStream().getAnalysisEngine().getPointerAnalysis(), this.getStream(), LOGGER);
647+
this.getStream().getAnalysisEngine().getPointerAnalysis(), this.getStream());
649648

650649
LOGGER.info("Possible reduce types are: " + possibleReturnTypes);
651650
} else {
@@ -864,7 +863,7 @@ private void discoverPossibleSideEffects(AggregateSolverResult result,
864863
engine.getCallGraph()))
865864
continue;
866865

867-
CallStringWithReceivers callString = getCallString(instance);
866+
CallStringWithReceivers callString = Util.getCallString(instance);
868867
CallSiteReference[] callSiteRefs = callString.getCallSiteRefs();
869868
assert callSiteRefs.length == 2 : "Expecting call sites two-deep.";
870869

@@ -1026,7 +1025,7 @@ private static boolean filterPointerKey(PointerKey pointerKey, EclipseProjectAna
10261025
private static boolean isStreamCreatedFromIntermediateOperation(InstanceKey instance, IClassHierarchy hierarchy,
10271026
CallGraph callGraph) throws IOException, CoreException {
10281027
// Get the immediate possible receivers of the stream instance.
1029-
Set<InstanceKey> receivers = getCallString(instance).getPossibleReceivers();
1028+
Set<InstanceKey> receivers = Util.getCallString(instance).getPossibleReceivers();
10301029

10311030
// Get any additional receivers we need to consider.
10321031
Collection<? extends InstanceKey> additionalReceivers = getAdditionalNecessaryReceiversFromPredecessors(
@@ -1045,23 +1044,6 @@ private static boolean isStreamCreatedFromIntermediateOperation(InstanceKey inst
10451044
});
10461045
}
10471046

1048-
private static CallStringWithReceivers getCallString(InstanceKey instance) {
1049-
NormalAllocationInNode allocationInNode = (NormalAllocationInNode) instance;
1050-
return getCallString(allocationInNode);
1051-
}
1052-
1053-
private static CallStringWithReceivers getCallString(NormalAllocationInNode allocationInNode) {
1054-
CGNode node = allocationInNode.getNode();
1055-
return getCallString(node);
1056-
}
1057-
1058-
private static CallStringWithReceivers getCallString(CGNode node) {
1059-
CallStringContext context = (CallStringContext) node.getContext();
1060-
CallStringWithReceivers callString = (CallStringWithReceivers) context
1061-
.get(CallStringContextSelector.CALL_STRING);
1062-
return callString;
1063-
}
1064-
10651047
/**
10661048
* The typestate rules to use.
10671049
*/

edu.cuny.hunter.streamrefactoring.core/src/edu/cuny/hunter/streamrefactoring/core/analysis/Util.java

+31-9
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@
3636
import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint;
3737
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
3838
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
39+
import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode;
3940
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
4041
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
42+
import com.ibm.wala.ipa.callgraph.propagation.cfa.CallStringContext;
43+
import com.ibm.wala.ipa.callgraph.propagation.cfa.CallStringContextSelector;
4144
import com.ibm.wala.ipa.cha.IClassHierarchy;
4245
import com.ibm.wala.shrikeCT.InvalidClassFileException;
4346
import com.ibm.wala.ssa.IR;
@@ -56,6 +59,7 @@
5659

5760
import edu.cuny.hunter.streamrefactoring.core.utils.LoggerNames;
5861
import edu.cuny.hunter.streamrefactoring.core.wala.AnalysisUtils;
62+
import edu.cuny.hunter.streamrefactoring.core.wala.CallStringWithReceivers;
5963

6064
public final class Util {
6165

@@ -197,22 +201,22 @@ static String getBinaryName(TypeReference typeReference) {
197201
}
198202

199203
public static Collection<TypeAbstraction> getPossibleTypesInterprocedurally(CGNode node, int valueNumber,
200-
HeapModel heapModel, PointerAnalysis<InstanceKey> pointerAnalysis, Stream stream, Logger logger)
204+
HeapModel heapModel, PointerAnalysis<InstanceKey> pointerAnalysis, Stream stream)
201205
throws NoniterableException, NoninstantiableException, CannotExtractSpliteratorException {
202206
Collection<TypeAbstraction> ret = new HashSet<>();
203207

204208
PointerKey valueKey = heapModel.getPointerKeyForLocal(node, valueNumber);
205-
logger.fine(() -> "Value pointer key is: " + valueKey);
209+
LOGGER.fine(() -> "Value pointer key is: " + valueKey);
206210

207211
OrdinalSet<InstanceKey> pointsToSet = pointerAnalysis.getPointsToSet(valueKey);
208212
assert pointsToSet != null;
209-
logger.fine(() -> "PointsTo set is: " + pointsToSet);
213+
LOGGER.fine(() -> "PointsTo set is: " + pointsToSet);
210214

211215
for (InstanceKey instanceKey : pointsToSet) {
212216
IClass concreteClass = instanceKey.getConcreteType();
213217

214218
if (!(concreteClass instanceof SyntheticClass)) {
215-
logger.fine(() -> "Found non-synthetic concrete type: " + concreteClass);
219+
LOGGER.fine(() -> "Found non-synthetic concrete type: " + concreteClass);
216220

217221
// Workaround #38, problem seemingly with generics.
218222
// Due to type erasure, we may have the problem if the return
@@ -409,7 +413,7 @@ private static boolean matches(TypeReference methodDeclaringType, MethodReferenc
409413
public static JDTIdentityMapper getJDTIdentifyMapper(ASTNode node) {
410414
return new JDTIdentityMapper(JavaSourceAnalysisScope.SOURCE, node.getAST());
411415
}
412-
416+
413417
/**
414418
* check whether the annotation is "EntryPoint"
415419
*/
@@ -421,9 +425,10 @@ private static boolean isEntryPointClass(TypeName typeName) {
421425
* Find all annotations in test cases and check whether they are "entry point".
422426
* If yes, call DefaultEntrypoint to get entry point, then, add it into the
423427
* result set.
424-
* @throws InvalidClassFileException
428+
*
429+
* @throws InvalidClassFileException
425430
*/
426-
public static Set<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) throws InvalidClassFileException {
431+
public static Set<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) throws InvalidClassFileException {
427432
final Set<Entrypoint> result = new HashSet<>();
428433
Iterator<IClass> classIterator = classHierarchy.iterator();
429434
while (classIterator.hasNext()) {
@@ -433,7 +438,7 @@ public static Set<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) th
433438
// iterate over all declared methods
434439
for (com.ibm.wala.classLoader.IMethod method : klass.getDeclaredMethods()) {
435440

436-
// if method has an annotation
441+
// if method has an annotation
437442
if (!(method instanceof ShrikeCTMethod)) {
438443
throw new IllegalArgumentException("@EntryPoint only works for byte code.");
439444
}
@@ -448,7 +453,24 @@ public static Set<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) th
448453
}
449454
}
450455
}
451-
456+
452457
return result;
453458
}
459+
460+
public static CallStringWithReceivers getCallString(InstanceKey instance) {
461+
NormalAllocationInNode allocationInNode = (NormalAllocationInNode) instance;
462+
return getCallString(allocationInNode);
463+
}
464+
465+
public static CallStringWithReceivers getCallString(NormalAllocationInNode allocationInNode) {
466+
CGNode node = allocationInNode.getNode();
467+
return getCallString(node);
468+
}
469+
470+
public static CallStringWithReceivers getCallString(CGNode node) {
471+
CallStringContext context = (CallStringContext) node.getContext();
472+
CallStringWithReceivers callString = (CallStringWithReceivers) context
473+
.get(CallStringContextSelector.CALL_STRING);
474+
return callString;
475+
}
454476
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package edu.cuny.hunter.streamrefactoring.core.safe;
2+
3+
import java.util.Collection;
4+
import java.util.Iterator;
5+
import java.util.logging.Logger;
6+
7+
import com.ibm.safe.internal.exceptions.PropertiesException;
8+
import com.ibm.safe.reporting.IReporter;
9+
import com.ibm.safe.typestate.core.BenignOracle;
10+
import com.ibm.safe.typestate.merge.IMergeFunctionFactory;
11+
import com.ibm.safe.typestate.metrics.TypeStateMetrics;
12+
import com.ibm.safe.typestate.mine.TraceReporter;
13+
import com.ibm.safe.typestate.options.TypeStateOptions;
14+
import com.ibm.safe.typestate.rules.ITypeStateDFA;
15+
import com.ibm.safe.typestate.unique.UniqueSolver;
16+
import com.ibm.wala.classLoader.CallSiteReference;
17+
import com.ibm.wala.classLoader.IClass;
18+
import com.ibm.wala.classLoader.IMethod;
19+
import com.ibm.wala.escape.ILiveObjectAnalysis;
20+
import com.ibm.wala.ipa.callgraph.CallGraph;
21+
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
22+
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
23+
import com.ibm.wala.types.MethodReference;
24+
import com.ibm.wala.types.TypeName;
25+
import com.ibm.wala.types.TypeReference;
26+
import com.ibm.wala.util.strings.Atom;
27+
28+
import edu.cuny.hunter.streamrefactoring.core.analysis.Util;
29+
import edu.cuny.hunter.streamrefactoring.core.utils.LoggerNames;
30+
import edu.cuny.hunter.streamrefactoring.core.wala.CallStringWithReceivers;
31+
32+
/**
33+
* A solver that only tracks instances created from client (non-JDK) calls.
34+
*
35+
* @author <a href="mailto:[email protected]">Raffi Khatchadourian</a>
36+
*/
37+
public class ClientSlicingUniqueSolver extends UniqueSolver {
38+
39+
private static final Logger LOGGER = Logger.getLogger(LoggerNames.LOGGER_NAME);
40+
41+
public ClientSlicingUniqueSolver(CallGraph cg, PointerAnalysis pointerAnalysis, ITypeStateDFA dfa,
42+
TypeStateOptions options, ILiveObjectAnalysis live, BenignOracle ora, TypeStateMetrics metrics,
43+
IReporter reporter, TraceReporter traceReporter, IMergeFunctionFactory mergeFactory) {
44+
super(cg, pointerAnalysis, dfa, options, live, ora, metrics, reporter, traceReporter, mergeFactory);
45+
}
46+
47+
@Override
48+
protected Collection<InstanceKey> computeTrackedInstances() throws PropertiesException {
49+
Collection<InstanceKey> instances = super.computeTrackedInstances();
50+
51+
for (Iterator<InstanceKey> iterator = instances.iterator(); iterator.hasNext();) {
52+
InstanceKey instanceKey = iterator.next();
53+
CallStringWithReceivers callString = Util.getCallString(instanceKey);
54+
IMethod[] callingMethods = callString.getMethods();
55+
IMethod outerMostCallingMethod = callingMethods[1];
56+
MethodReference reference = outerMostCallingMethod.getReference();
57+
TypeReference declaringClass = reference.getDeclaringClass();
58+
TypeName name = declaringClass.getName();
59+
Atom classPackage = name.getPackage();
60+
boolean isFromAPI = classPackage.startsWith(Atom.findOrCreateAsciiAtom("java"));
61+
62+
// if it's being called from the API.
63+
if (isFromAPI) {
64+
// remove it.
65+
LOGGER.info(() -> "Removing instance: " + instanceKey);
66+
iterator.remove();
67+
}
68+
}
69+
70+
return instances;
71+
}
72+
73+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package p;
2+
3+
import java.util.HashSet;
4+
import java.util.stream.*;
5+
6+
import edu.cuny.hunter.streamrefactoring.annotations.*;
7+
8+
class A {
9+
10+
@EntryPoint
11+
void n() {
12+
new HashSet<>().stream().sorted().distinct().count();
13+
}
14+
}

0 commit comments

Comments
 (0)