Skip to content

Commit

Permalink
Merge pull request #128 from ponder-lab/issue_103
Browse files Browse the repository at this point in the history
Some work on #126.
  • Loading branch information
khatchad authored Dec 18, 2017
2 parents 6b0061c + 7c056b4 commit 985af03
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -239,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);
Expand Down Expand Up @@ -415,7 +414,7 @@ public void start() throws IOException, CoreException, CallGraphBuilderCancelExc
// fill the instance to predecessors map.
for (Iterator<InstanceKey> it = result.iterateInstances(); it.hasNext();) {
InstanceKey instance = it.next();
CallStringWithReceivers callString = getCallString(instance);
CallStringWithReceivers callString = Util.getCallString(instance);
Set<InstanceKey> possibleReceivers = new HashSet<>(callString.getPossibleReceivers());

// get any additional receivers if necessary #36.
Expand Down Expand Up @@ -526,7 +525,7 @@ private static Collection<? extends InstanceKey> getAdditionalNecessaryReceivers
Collection<InstanceKey> 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()) {
Expand All @@ -550,7 +549,7 @@ private static Collection<? extends InstanceKey> 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<InstanceKey> possibleReceivers = calledMethodCallString.getPossibleReceivers();
Expand Down Expand Up @@ -602,7 +601,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()) {
Expand Down Expand Up @@ -645,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 {
Expand Down Expand Up @@ -864,7 +863,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.";

Expand Down Expand Up @@ -1026,7 +1025,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<InstanceKey> receivers = getCallString(instance).getPossibleReceivers();
Set<InstanceKey> receivers = Util.getCallString(instance).getPossibleReceivers();

// Get any additional receivers we need to consider.
Collection<? extends InstanceKey> additionalReceivers = getAdditionalNecessaryReceiversFromPredecessors(
Expand All @@ -1045,23 +1044,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.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {

Expand Down Expand Up @@ -197,22 +201,22 @@ static String getBinaryName(TypeReference typeReference) {
}

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

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

OrdinalSet<InstanceKey> 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
Expand Down Expand Up @@ -409,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"
*/
Expand All @@ -421,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<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) throws InvalidClassFileException {
public static Set<Entrypoint> findEntryPoints(IClassHierarchy classHierarchy) throws InvalidClassFileException {
final Set<Entrypoint> result = new HashSet<>();
Iterator<IClass> classIterator = classHierarchy.iterator();
while (classIterator.hasNext()) {
Expand All @@ -433,7 +438,7 @@ public static Set<Entrypoint> 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.");
}
Expand All @@ -448,7 +453,24 @@ public static Set<Entrypoint> 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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;
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 <a href="mailto:rk1424@hunter.cuny.edu">Raffi Khatchadourian</a>
*/
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<InstanceKey> computeTrackedInstances() throws PropertiesException {
Collection<InstanceKey> instances = super.computeTrackedInstances();

for (Iterator<InstanceKey> iterator = instances.iterator(); iterator.hasNext();) {
InstanceKey instanceKey = iterator.next();
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);
iterator.remove();
}
}

return instances;
}

}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Loading

0 comments on commit 985af03

Please sign in to comment.