various refactorings for demand points-to analysis

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2758 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
msridhar1 2008-04-12 21:58:39 +00:00
parent a8b09bef6b
commit 3f293dcc60
11 changed files with 54 additions and 235 deletions

View File

@ -46,7 +46,6 @@ import junit.framework.TestCase;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
import com.ibm.wala.demandpa.alg.DemandRefinementPointsTo;
import com.ibm.wala.demandpa.alg.IDemandPointerAnalysis;
import com.ibm.wala.demandpa.alg.ThisFilteringHeapModel;
import com.ibm.wala.demandpa.alg.statemachine.DummyStateMachine;
import com.ibm.wala.demandpa.alg.statemachine.StateMachineFactory;
@ -176,7 +175,7 @@ public abstract class AbstractPtrTest extends TestCase {
protected Collection<InstanceKey> getPointsToSetToTest(String scopeFile, String mainClass) throws ClassHierarchyException,
IllegalArgumentException, CancelException, IOException {
final IDemandPointerAnalysis dmp = makeDemandPointerAnalysis(scopeFile, mainClass);
final DemandRefinementPointsTo dmp = makeDemandPointerAnalysis(scopeFile, mainClass);
// find the testThisVar call, and check the parameter's points-to set
CGNode mainMethod = AbstractPtrTest.findMainMethod(dmp.getBaseCallGraph());

View File

@ -265,7 +265,7 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
curP2Set = computer.getP2Set(queriedPk);
if (DEBUG) {
System.err.println("traversed " + getNumNodesTraversed() + " nodes");
System.err.println("POINTS-TO SET " + lastP2Set);
System.err.println("POINTS-TO SET " + curP2Set);
}
break;
} catch (StatesMergedException e) {
@ -278,8 +278,17 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
}
if (curP2Set != null) {
lastP2Set = curP2Set;
if (p2setPred.test(curP2Set)) {
if (lastP2Set == null) {
lastP2Set = curP2Set;
} else if (lastP2Set.size() > curP2Set.size()) {
// got a more precise set
assert lastP2Set.containsAll(curP2Set);
lastP2Set = curP2Set;
} else {
// new set size is >= lastP2Set, so don't update
assert curP2Set.containsAll(lastP2Set);
}
if (curP2Set.isEmpty() || p2setPred.test(curP2Set)) {
// we did it!
succeeded = true;
break;
@ -911,7 +920,7 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
public void visitGetField(GetFieldLabel label, Object dst) {
IField field = (label).getField();
PointerKey loadBase = (PointerKey) dst;
if (refineFieldAccesses(field, loadBase, curPk, curState)) {
if (refineFieldAccesses(field, loadBase, curPk, label, curState)) {
// if (Assertions.verifyAssertions) {
// Assertions._assert(stateMachine.transition(curState, label) ==
// curState);
@ -1106,8 +1115,8 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
}
}
private boolean refineFieldAccesses(IField field, PointerKey basePtr, PointerKey val, State state) {
boolean shouldRefine = refinementPolicy.getFieldRefinePolicy().shouldRefine(field, basePtr, val, state);
private boolean refineFieldAccesses(IField field, PointerKey basePtr, PointerKey val, IFlowLabel label, State state) {
boolean shouldRefine = refinementPolicy.getFieldRefinePolicy().shouldRefine(field, basePtr, val, label, state);
if (DEBUG) {
if (shouldRefine) {
System.err.println("refining access to " + field);
@ -1180,7 +1189,7 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
public void visitPutField(PutFieldLabel label, Object dst) {
IField field = label.getField();
PointerKey storeBase = (PointerKey) dst;
if (refineFieldAccesses(field, storeBase, curPk, curState)) {
if (refineFieldAccesses(field, storeBase, curPk, label, curState)) {
// statements x.f = y, Y updated (X' not empty required)
// update Z.f for all z in X'
PointerKeyAndState storeBaseAndState = new PointerKeyAndState(storeBase, curState);
@ -1201,7 +1210,7 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
public void visitGetField(GetFieldLabel label, Object dst) {
IField field = (label).getField();
PointerKey dstPtrKey = (PointerKey) dst;
if (refineFieldAccesses(field, curPk, dstPtrKey, curState)) {
if (refineFieldAccesses(field, curPk, dstPtrKey, label, curState)) {
// statements x = y.f, Y updated
// if X queried, start tracking Y.f
PointerKeyAndState loadDefAndState = new PointerKeyAndState(dstPtrKey, curState);
@ -1232,7 +1241,8 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
public void visitPutField(PutFieldLabel label, Object dst) {
IField field = (label).getField();
PointerKey dstPtrKey = (PointerKey) dst;
if (refineFieldAccesses(field, curPk, dstPtrKey, curState)) {
// pass barred label since this is for tracked points-to sets
if (refineFieldAccesses(field, curPk, dstPtrKey, label.bar(), curState)) {
// x.f = y, X updated
// if Y' non-empty, then update
// tracked set of X.f, to trace flow
@ -1428,7 +1438,7 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
// z in X'
IField field = label.getField();
PointerKey dstPtrKey = (PointerKey) dst;
if (refineFieldAccesses(field, curPk, dstPtrKey, curState)) {
if (refineFieldAccesses(field, curPk, dstPtrKey, label, curState)) {
for (InstanceKeyAndState ikAndState : makeOrdinalSet(trackedSet)) {
boolean needField = forwInstKeyToFields.get(ikAndState).contains(field);
PointerKeyAndState storeDst = new PointerKeyAndState(dstPtrKey, curState);
@ -1468,7 +1478,8 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
public void visitPutField(PutFieldLabel label, Object dst) {
IField field = label.getField();
PointerKey storeBase = (PointerKey) dst;
if (refineFieldAccesses(field, storeBase, curPk, curState)) {
// bar label since this is for tracked points-to sets
if (refineFieldAccesses(field, storeBase, curPk, label.bar(), curState)) {
PointerKeyAndState storeBaseAndState = new PointerKeyAndState(storeBase, curState);
encounteredStores.add(new StoreEdge(storeBaseAndState, field, curPkAndState));
if (!addToInitWorklist(storeBaseAndState)) {
@ -1503,7 +1514,8 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
IField field = label.getField();
PointerKey dstPtrKey = (PointerKey) dst;
// x = y.f, Y' updated
if (refineFieldAccesses(field, curPk, dstPtrKey, curState)) {
// bar label since this is for tracked points-to sets
if (refineFieldAccesses(field, curPk, dstPtrKey, label.bar(), curState)) {
for (InstanceKeyAndState ikAndState : makeOrdinalSet(trackedSet)) {
// tracking value written into ik.field
boolean needField = backInstKeyToFields.get(ikAndState).contains(field);
@ -1602,7 +1614,8 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
// System.err.println("QUERIED: " + queriedPkAndStates);
// }
if (!basePointerOkay) {
Assertions._assert(false, "queried " + loadedValAndState + " but not " + baseAndStateToHandle);
// TEMPORARY --MS
//Assertions._assert(false, "queried " + loadedValAndState + " but not " + baseAndStateToHandle);
}
}
final IntSet curP2Set = find(pkToP2Set, baseAndStateToHandle);

View File

@ -1,208 +0,0 @@
/*******************************************************************************
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html.
*
* This file is a derivative of code released by the University of
* California under the terms listed below.
*
* Refinement Analysis Tools is Copyright ©2007 The Regents of the
* University of California (Regents). Provided that this notice and
* the following two paragraphs are included in any distribution of
* Refinement Analysis Tools or its derivative work, Regents agrees
* not to assert any of Regents' copyright rights in Refinement
* Analysis Tools against recipient for recipients reproduction,
* preparation of derivative works, public display, public
* performance, distribution or sublicensing of Refinement Analysis
* Tools and derivative works, in source code and object code form.
* This agreement not to assert does not confer, by implication,
* estoppel, or otherwise any license or rights in any intellectual
* property of Regents, including, but not limited to, any patents
* of Regents or Regents employees.
*
* IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
* INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE
* AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY
* WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING
* DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT,
* UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
package com.ibm.wala.demandpa.alg;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.demandpa.flowgraph.AbstractFlowGraph;
import com.ibm.wala.demandpa.flowgraph.AbstractFlowLabelVisitor;
import com.ibm.wala.demandpa.flowgraph.AssignGlobalLabel;
import com.ibm.wala.demandpa.flowgraph.AssignLabel;
import com.ibm.wala.demandpa.flowgraph.DemandPointerFlowGraph;
import com.ibm.wala.demandpa.flowgraph.GetFieldLabel;
import com.ibm.wala.demandpa.flowgraph.NewLabel;
import com.ibm.wala.demandpa.flowgraph.IFlowLabel.IFlowLabelVisitor;
import com.ibm.wala.demandpa.util.MemoryAccessMap;
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.UnimplementedError;
/**
* Simple field-based points-to analysis using {@link DemandPointerFlowGraph}.
* Primarily for testing purposes.
*
* @author Manu Sridharan
*
*/
public class TestNewGraphPointsTo extends AbstractDemandPointsTo {
public TestNewGraphPointsTo(CallGraph cg, HeapModel model, MemoryAccessMap fam, ClassHierarchy cha, AnalysisOptions options) {
super(cg, model, fam, cha, options);
}
public Collection<InstanceKey> getPointsTo(PointerKey pk) throws UnimplementedError {
Assertions._assert(pk instanceof LocalPointerKey, "we only handle locals");
LocalPointerKey queriedPk = (LocalPointerKey) pk;
// Create an (initially empty) dependence graph
final AbstractFlowGraph g = new DemandPointerFlowGraph(cg, heapModel, fam, cha);
// initialize the graph with the subgraph of x's method
g.addSubgraphForNode(queriedPk.getNode());
// do a DFS traversal of the assign and match edges
// in the graph, adding instance keys to the points-to set
final HashSet<InstanceKey> p2set = HashSetFactory.make();
final HashSet<PointerKey> marked = HashSetFactory.make();
final Stack<PointerKey> worklist = new Stack<PointerKey>();
class Helper {
void prop(PointerKey thePk) {
if (!marked.contains(thePk)) {
marked.add(thePk);
worklist.push(thePk);
}
}
void propAll(Iterator<? extends Object> keys) {
while (keys.hasNext()) {
prop((PointerKey) keys.next());
}
}
}
final Helper h = new Helper();
// final Mapper pkExtractor = new Mapper() {
//
// public Object map(Object obj_) {
// return ((PointerKeyAndCallSite) obj_).getKey();
// }
//
// };
h.prop(queriedPk);
final IFlowLabelVisitor v = new AbstractFlowLabelVisitor() {
@Override
public void visitNew(NewLabel label, Object dst) {
p2set.add((InstanceKey) dst);
}
@Override
public void visitGetField(GetFieldLabel label, Object dst) {
h.propAll(g.getWritesToInstanceField(null, label.getField()));
}
@Override
public void visitAssignGlobal(AssignGlobalLabel label, Object dst) {
h.propAll(g.getWritesToStaticField((StaticFieldKey) dst));
}
@Override
public void visitAssign(AssignLabel label, Object dst) {
h.prop((PointerKey) dst);
}
};
while (!worklist.isEmpty()) {
PointerKey curPk = worklist.pop();
g.visitSuccs(curPk, v);
// interprocedural edges
if (curPk instanceof LocalPointerKey) {
LocalPointerKey localPk = (LocalPointerKey) curPk;
if (g.isParam(localPk)) {
CGNode cgNode = localPk.getNode();
int paramPos = localPk.getValueNumber() - 1;
for (Iterator<? extends CGNode> iter = cg.getPredNodes(cgNode); iter.hasNext();) {
CGNode caller = iter.next();
IR ir = caller.getIR();
for (Iterator<CallSiteReference> iterator = ir.iterateCallSites(); iterator.hasNext();) {
CallSiteReference call = iterator.next();
// TODO on-the-fly call graph
if (cg.getPossibleTargets(caller, call).contains(cgNode)) {
g.addSubgraphForNode(caller);
SSAAbstractInvokeInstruction[] callInstrs = ir.getCalls(call);
for (int i = 0; i < callInstrs.length; i++) {
SSAAbstractInvokeInstruction callInstr = callInstrs[i];
PointerKey actualPk = heapModel.getPointerKeyForLocal(caller, callInstr.getUse(paramPos));
if (Assertions.verifyAssertions) {
Assertions._assert(g.containsNode(actualPk));
Assertions._assert(g.containsNode(localPk));
}
h.prop(actualPk);
}
}
}
}
}
SSAInvokeInstruction callInstr = g.getInstrReturningTo(localPk);
if (callInstr != null) {
boolean isExceptional = localPk.getValueNumber() == callInstr.getException();
CallSiteReference callSiteRef = callInstr.getCallSite();
// get call targets
Set<CGNode> possibleCallees = cg.getPossibleTargets(localPk.getNode(), callSiteRef);
// construct graph for each target
for (CGNode callee : possibleCallees) {
// TODO on-the-fly call graph stuff
g.addSubgraphForNode(callee);
PointerKey retVal = isExceptional ? heapModel.getPointerKeyForExceptionalReturnValue(callee) : heapModel
.getPointerKeyForReturnValue(callee);
if (Assertions.verifyAssertions) {
Assertions._assert(g.containsNode(retVal));
}
h.prop(retVal);
}
}
// Assertions._assert(sameContents(orig, newRets), "orig " + orig +
// "\nnew " + newRets);
// h.propAll(new IteratorMapper(pkExtractor,
// g.getReturnSuccs((LocalPointerKey) curPk)));
// h.propAll(new IteratorMapper(pkExtractor,
// g.getParamSuccs((LocalPointerKey) curPk)));
}
}
return p2set;
}
}

View File

@ -18,9 +18,9 @@ package com.ibm.wala.demandpa.alg.refinepolicy;
*/
public abstract class AbstractRefinementPolicy implements RefinementPolicy {
private static final int DEFAULT_NUM_PASSES = 3;
private static final int DEFAULT_NUM_PASSES = 4;
private static final int[] DEFAULT_BUDGET_PER_PASS = { 1000, 12000, 12000 };
private static final int[] DEFAULT_BUDGET_PER_PASS = { 1000, 12000, 12000, 12000 };
protected final FieldRefinePolicy fieldRefinePolicy;

View File

@ -40,6 +40,7 @@ package com.ibm.wala.demandpa.alg.refinepolicy;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.demandpa.alg.statemachine.StateMachine;
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
/**
@ -51,7 +52,7 @@ import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
*/
public class AlwaysRefineFieldsPolicy implements FieldRefinePolicy {
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, StateMachine.State state) {
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, IFlowLabel label, StateMachine.State state) {
return true;
}

View File

@ -39,6 +39,7 @@ package com.ibm.wala.demandpa.alg.refinepolicy;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.demandpa.alg.statemachine.StateMachine;
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
/**
@ -58,7 +59,7 @@ public interface FieldRefinePolicy {
* @return <code>true</code> if match edges for the field access should be refined. Otherwise, <code>false</code>
* is returned, indicating that the field can be handled with match edges.
*/
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, StateMachine.State state);
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, IFlowLabel label, StateMachine.State state);
/**
*

View File

@ -43,6 +43,7 @@ import java.util.regex.Pattern;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.demandpa.alg.statemachine.StateMachine;
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
import com.ibm.wala.demandpa.util.ArrayContents;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.cha.ClassHierarchy;
@ -70,7 +71,7 @@ public class ManualFieldPolicy implements FieldRefinePolicy {
final private IClass[] encounteredClasses = new IClass[NUM_DECISIONS_TO_TRACK];
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, StateMachine.State state) {
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, IFlowLabel label, StateMachine.State state) {
if (field == ArrayContents.v())
return true;
final IClass declaringClass = field.getDeclaringClass();

View File

@ -39,11 +39,12 @@ package com.ibm.wala.demandpa.alg.refinepolicy;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.demandpa.alg.statemachine.StateMachine;
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
public class NeverRefineFieldsPolicy implements FieldRefinePolicy {
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, StateMachine.State state) {
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, IFlowLabel label, StateMachine.State state) {
return false;
}

View File

@ -15,6 +15,7 @@ import java.util.Collection;
import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.demandpa.alg.statemachine.StateMachine;
import com.ibm.wala.demandpa.flowgraph.IFlowLabel;
import com.ibm.wala.demandpa.util.ArrayContents;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.cha.ClassHierarchy;
@ -24,7 +25,9 @@ import com.ibm.wala.util.collections.HashSetFactory;
public class TunedFieldRefinementPolicy implements FieldRefinePolicy {
private final ClassHierarchy cha;
private static final boolean DEBUG = true;
private final ClassHierarchy cha;
private final Collection<IClass> typesToRefine = HashSetFactory.make();
@ -33,6 +36,9 @@ public class TunedFieldRefinementPolicy implements FieldRefinePolicy {
public boolean nextPass() {
if (firstSkippedClass != null) {
typesToRefine.add(firstSkippedClass);
if (DEBUG) {
System.err.println("now refining " + firstSkippedClass);
}
firstSkippedClass = null;
return true;
} else {
@ -40,7 +46,7 @@ public class TunedFieldRefinementPolicy implements FieldRefinePolicy {
}
}
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, StateMachine.State state) {
public boolean shouldRefine(IField field, PointerKey basePtr, PointerKey val, IFlowLabel label, StateMachine.State state) {
if (field == ArrayContents.v()) {
return true;
}
@ -67,8 +73,8 @@ public class TunedFieldRefinementPolicy implements FieldRefinePolicy {
/**
*
* @param klass
* @return the top-level {@link IClass} where klass is declared, or klass
* itself if klass is top-level or if top-level class not loaded
* @return the top-level {@link IClass} where klass is declared, or klass itself if klass is top-level or if top-level
* class not loaded
*/
private IClass removeInner(IClass klass) {
ClassLoaderReference cl = klass.getClassLoader().getReference();

View File

@ -354,10 +354,10 @@ public abstract class AbstractDemandFlowGraph extends AbstractFlowGraph {
private void debugPrintIR(IR ir) {
if (DEBUG) {
if (ir == null) {
Trace.println("\n No statements\n");
System.err.println("\n No statements\n");
} else {
try {
Trace.println(ir.toString());
System.err.println(ir.toString());
} catch (Error e) {
// TODO Auto-generated catch block
e.printStackTrace();

View File

@ -107,4 +107,9 @@ public class PutFieldBarLabel implements IFlowLabel {
return true;
}
@Override
public String toString() {
return "putfield_bar[" + field + "]";
}
}