Skip to content

Issue 126 #128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Dec 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:[email protected]">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