delete PointerFlowGraph

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2609 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
sjfink 2008-02-24 00:05:09 +00:00
parent 1482a589d2
commit 58c63a7463
5 changed files with 1 additions and 607 deletions

View File

@ -33,8 +33,6 @@ import com.ibm.wala.ipa.callgraph.CallGraphBuilder;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.Util;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerFlowGraph;
import com.ibm.wala.ipa.callgraph.propagation.PointerFlowGraphFactory;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
@ -122,15 +120,6 @@ public abstract class AbstractAnalysisEngine implements AnalysisEngine {
*/
protected PointerAnalysis pointerAnalysis;
/**
* Factory to create graph view of flow of pointers in the heap.
*/
private PointerFlowGraphFactory pointerFlowGraphFactory;
/**
* Graph view of flow of pointers between heap abstracts
*/
private PointerFlowGraph pointerFlowGraph;
/**
* Graph view of flow of pointers between heap abstractions
@ -151,7 +140,6 @@ public abstract class AbstractAnalysisEngine implements AnalysisEngine {
cg = builder.makeCallGraph(options, monitor);
if (savePointerAnalysis) {
pointerFlowGraphFactory = builder.getPointerFlowGraphFactory();
pointerAnalysis = builder.getPointerAnalysis();
}
@ -265,14 +253,7 @@ public abstract class AbstractAnalysisEngine implements AnalysisEngine {
public PointerAnalysis getPointerAnalysis() {
return pointerAnalysis;
}
public PointerFlowGraph getPointerFlowGraph() {
if (pointerFlowGraph == null) {
pointerFlowGraph = pointerFlowGraphFactory.make(pointerAnalysis, cg);
}
return pointerFlowGraph;
}
public HeapGraph getHeapGraph() {
if (heapGraph == null) {
heapGraph = new BasicHeapGraph(getPointerAnalysis(), cg);

View File

@ -13,7 +13,6 @@ package com.ibm.wala.ipa.callgraph;
import org.eclipse.core.runtime.IProgressMonitor;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerFlowGraphFactory;
/**
*
@ -37,8 +36,6 @@ public interface CallGraphBuilder {
*/
public PointerAnalysis getPointerAnalysis();
public PointerFlowGraphFactory getPointerFlowGraphFactory();
public AnalysisCache getAnalysisCache();
}

View File

@ -1,569 +0,0 @@
/*******************************************************************************
* Copyright (c) 2002 - 2006 IBM Corporation.
* All rights reserved. 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.ibm.wala.ipa.callgraph.propagation;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.classLoader.ProgramCounter;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.ISSABasicBlock;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
import com.ibm.wala.ssa.SSACFG;
import com.ibm.wala.ssa.SSACheckCastInstruction;
import com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction;
import com.ibm.wala.ssa.SSAGetInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
import com.ibm.wala.ssa.SSAPiInstruction;
import com.ibm.wala.ssa.SSAPutInstruction;
import com.ibm.wala.ssa.SSAReturnInstruction;
import com.ibm.wala.ssa.SSAThrowInstruction;
import com.ibm.wala.ssa.SSACFG.BasicBlock;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.Trace;
import com.ibm.wala.util.graph.AbstractGraph;
import com.ibm.wala.util.graph.EdgeManager;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.NodeManager;
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph;
import com.ibm.wala.util.ref.ReferenceCleanser;
/**
* A graphical view that represents the flow of pointers between abstract heap
* locations
*
* Each node in this graph is a PointerKey, representing an abstraction of a
* pointer. There is an edge p -> q iff pointer values flow from p to q via an
* assignment of some kind in the program.
*
* This uses some lazy logic to avoid walking IRs until necessary.
*
* @author Julian Dolby
* @author sfink
*/
public class PointerFlowGraph extends AbstractGraph<PointerKey> {
protected final PointerAnalysis pa;
protected final CallGraph cg;
final protected SlowSparseNumberedGraph<PointerKey> delegate = SlowSparseNumberedGraph.make();
/**
* nodes for which we have processed the statements
*/
private final Collection<CGNode> processedNodes = HashSetFactory.make();
private final EdgeManager<PointerKey> edgeManager = new LazyEdgeManager();
private static int wipeCount = 0;
private final static int WIPE_THRESHOLD = 1000;
protected PointerFlowGraph(PointerAnalysis pa, CallGraph cg) throws IllegalArgumentException {
this.pa = pa;
this.cg = cg;
if (cg == null) {
throw new IllegalArgumentException("cg cannot be null");
}
}
private void processAllNodes() {
for (Iterator it = cg.iterator(); it.hasNext();) {
CGNode node = (CGNode) it.next();
if (!processedNodes.contains(node)) {
processNode(node);
}
}
}
private void processCallers(CGNode node) {
for (Iterator it = cg.getPredNodes(node); it.hasNext();) {
CGNode p = (CGNode) it.next();
if (!processedNodes.contains(p)) {
processNode(p);
}
}
}
@Override
public NodeManager<PointerKey> getNodeManager() {
return delegate.getNodeManager();
}
@Override
protected EdgeManager<PointerKey> getEdgeManager() {
return edgeManager;
}
private class LazyEdgeManager implements EdgeManager<PointerKey> {
private void lazySucc(Object N) {
if (N instanceof AbstractLocalPointerKey) {
AbstractLocalPointerKey lpk = (AbstractLocalPointerKey) N;
CGNode node = lpk.getNode();
if (!processedNodes.contains(node)) {
processNode(node);
}
if (lpk instanceof ReturnValueKey) {
processCallers(node);
}
} else {
// flow to the heap. give up.
// todo: use some smarter logic
processAllNodes();
}
}
private void lazyPred(Object N) {
if (N instanceof AbstractLocalPointerKey) {
AbstractLocalPointerKey lpk = (AbstractLocalPointerKey) N;
CGNode node = lpk.getNode();
if (!processedNodes.contains(node)) {
processNode(node);
}
if (lpk instanceof LocalPointerKey) {
LocalPointerKey p = (LocalPointerKey) lpk;
if (p.isParameter()) {
processCallers(node);
}
}
} else {
// flow to the heap. give up.
// todo: use some smarter logic
processAllNodes();
}
}
public Iterator<? extends PointerKey> getPredNodes(PointerKey N) {
lazyPred(N);
return delegate.getPredNodes(N);
}
public int getPredNodeCount(PointerKey N) {
lazyPred(N);
return delegate.getPredNodeCount(N);
}
public Iterator<? extends PointerKey> getSuccNodes(PointerKey N) {
lazySucc(N);
return delegate.getSuccNodes(N);
}
public int getSuccNodeCount(PointerKey N) {
lazySucc(N);
return delegate.getSuccNodeCount(N);
}
public void addEdge(PointerKey src, PointerKey dst) {
delegate.addEdge(src, dst);
}
public void removeEdge(PointerKey src, PointerKey dst) {
delegate.removeEdge(src, dst);
}
public void removeAllIncidentEdges(PointerKey node) {
Assertions.UNREACHABLE();
}
public void removeIncomingEdges(PointerKey node) {
Assertions.UNREACHABLE();
}
public void removeOutgoingEdges(PointerKey node) {
Assertions.UNREACHABLE();
}
public boolean hasEdge(PointerKey src, PointerKey dst) {
lazySucc(src);
lazyPred(dst);
return delegate.hasEdge(src, dst);
}
};
/**
* Walk the statements in a node and add edges to the graph. Side effect: add
* node to the set of processed nodes.
*/
private void processNode(CGNode node) {
if (Assertions.verifyAssertions) {
Assertions._assert(!processedNodes.contains(node));
}
processedNodes.add(node);
IR ir = getIR(node);
if (ir != null) {
visit(node, ir);
} else {
Trace.println("PointerFlowGraph.build got null ir for " + node);
}
}
private static IR getIR(CGNode node) {
wipeCount++;
if (wipeCount > WIPE_THRESHOLD) {
wipeCount = 0;
ReferenceCleanser.clearSoftCaches();
}
return node.getIR();
}
private void visit(CGNode node, IR ir) {
// add edges induced by individual instructions
for (Iterator it = ir.getControlFlowGraph().iterator(); it.hasNext();) {
SSACFG.BasicBlock bb = (SSACFG.BasicBlock) it.next();
InstructionVisitor v = makeInstructionVisitor(node, ir, bb);
for (Iterator it2 = bb.iterator(); it2.hasNext();) {
SSAInstruction i = (SSAInstruction) it2.next();
if (i != null) {
i.visit(v);
}
}
}
// add edges relating to thrown exceptions that reach the exit block.
List<ProgramCounter> peis = SSAPropagationCallGraphBuilder.getIncomingPEIs(ir, ir.getExitBlock());
PointerKey exception = pa.getHeapModel().getPointerKeyForExceptionalReturnValue(node);
addExceptionEdges(node, delegate, pa, ir, peis, exception);
}
protected InstructionVisitor makeInstructionVisitor(CGNode node, IR ir, BasicBlock bb) {
return new InstructionVisitor(pa, cg, delegate, node,ir, bb);
}
public static class InstructionVisitor extends SSAInstruction.Visitor {
private final CGNode node;
private final IR ir;
private final ISSABasicBlock bb;
private final PointerAnalysis pa;
private final Graph<PointerKey> delegate;
private final CallGraph cg;
public InstructionVisitor(PointerAnalysis pa, CallGraph cg, Graph<PointerKey> delegate, CGNode node, IR ir, BasicBlock bb) {
this.delegate = delegate;
this.node = node;
this.ir = ir;
this.bb = bb;
this.pa = pa;
this.cg = cg;
}
/*
* @see com.ibm.wala.ssa.SSAInstruction.Visitor#visitArrayLoad(com.ibm.wala.ssa.SSAArrayLoadInstruction)
*/
@Override
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
// skip arrays of primitive type
if (instruction.typeIsPrimitive()) {
return;
}
PointerKey result = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getDef());
PointerKey arrayRef = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getArrayRef());
if (result == null) {
// not sure why this happens. give up.
return;
}
delegate.addNode(result);
for (Iterator it = pa.getPointsToSet(arrayRef).iterator(); it.hasNext();) {
InstanceKey ik = (InstanceKey) it.next();
TypeReference C = ik.getConcreteType().getReference().getArrayElementType();
if (C.isPrimitiveType()) {
return;
}
PointerKey p = pa.getHeapModel().getPointerKeyForArrayContents(ik);
if (p == null) {
return;
}
delegate.addNode(p);
delegate.addEdge(p, result);
}
}
/*
* @see com.ibm.wala.ssa.SSAInstruction.Visitor#visitArrayStore(com.ibm.wala.ssa.SSAArrayStoreInstruction)
*/
@Override
public void visitArrayStore(SSAArrayStoreInstruction instruction) {
// skip arrays of primitive type
if (instruction.typeIsPrimitive()) {
return;
}
PointerKey value = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getValue());
PointerKey arrayRef = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getArrayRef());
if (value == null || arrayRef == null) {
// skip operations on null constants
return;
}
delegate.addNode(value);
for (Iterator it = pa.getPointsToSet(arrayRef).iterator(); it.hasNext();) {
InstanceKey ik = (InstanceKey) it.next();
TypeReference C = ik.getConcreteType().getReference().getArrayElementType();
if (C.isPrimitiveType()) {
return;
}
PointerKey p = pa.getHeapModel().getPointerKeyForArrayContents(ik);
if (p == null) {
return;
}
delegate.addNode(p);
delegate.addEdge(value, p);
}
}
/*
* @see com.ibm.wala.ssa.SSAInstruction.Visitor#visitCheckCast(com.ibm.wala.ssa.SSACheckCastInstruction)
*/
@Override
public void visitCheckCast(SSACheckCastInstruction instruction) {
PointerKey result = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getResult());
PointerKey value = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getVal());
if (value != null) {
delegate.addNode(value);
delegate.addNode(result);
delegate.addEdge(value, result);
}
}
/*
* @see com.ibm.wala.ssa.SSAInstruction.Visitor#visitCheckCast(com.ibm.wala.ssa.SSACheckCastInstruction)
*/
@Override
public void visitPi(SSAPiInstruction instruction) {
PointerKey result = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getDef());
PointerKey value = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getVal());
delegate.addNode(value);
delegate.addNode(result);
delegate.addEdge(value, result);
}
/*
* @see com.ibm.wala.ssa.SSAInstruction.Visitor#visitReturn(com.ibm.wala.ssa.SSAReturnInstruction)
*/
@Override
public void visitReturn(SSAReturnInstruction instruction) {
// skip returns of primitive type
if (instruction.returnsPrimitiveType() || instruction.returnsVoid()) {
return;
}
PointerKey returnValue = pa.getHeapModel().getPointerKeyForReturnValue(node);
PointerKey result = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getResult());
if (result == null) {
// this can happen for return of null constant
return;
}
delegate.addNode(returnValue);
delegate.addNode(result);
delegate.addEdge(result, returnValue);
}
/*
* @see com.ibm.wala.ssa.SSAInstruction.Visitor#visitGet(com.ibm.wala.ssa.SSAGetInstruction)
*/
@Override
public void visitGet(SSAGetInstruction instruction) {
FieldReference field = instruction.getDeclaredField();
// skip getfields of primitive type (optimisation)
if (field.getFieldType().isPrimitiveType()) {
return;
}
PointerKey def = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getDef());
delegate.addNode(def);
IField f = cg.getClassHierarchy().resolveField(field);
if (f == null) {
return;
}
if (instruction.isStatic()) {
PointerKey fKey = pa.getHeapModel().getPointerKeyForStaticField(f);
delegate.addNode(fKey);
delegate.addEdge(fKey, def);
} else {
PointerKey ref = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getRef());
for (Iterator it = pa.getPointsToSet(ref).iterator(); it.hasNext();) {
InstanceKey ik = (InstanceKey) it.next();
PointerKey p = pa.getHeapModel().getPointerKeyForInstanceField(ik, f);
delegate.addNode(p);
delegate.addEdge(p, def);
}
}
}
/*
* @see com.ibm.wala.ssa.Instruction.Visitor#visitPut(com.ibm.wala.ssa.PutInstruction)
*/
@Override
public void visitPut(SSAPutInstruction instruction) {
FieldReference field = instruction.getDeclaredField();
// skip putfields of primitive type
if (field.getFieldType().isPrimitiveType()) {
return;
}
IField f = cg.getClassHierarchy().resolveField(field);
if (f == null) {
return;
}
PointerKey val = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getVal());
if (val == null) {
// this can happen if val is a null constant
return;
}
if (instruction.isStatic()) {
PointerKey fKey = pa.getHeapModel().getPointerKeyForStaticField(f);
delegate.addNode(fKey);
delegate.addNode(val);
delegate.addEdge(val, fKey);
} else {
PointerKey ref = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getRef());
for (Iterator it = pa.getPointsToSet(ref).iterator(); it.hasNext();) {
InstanceKey ik = (InstanceKey) it.next();
PointerKey p = pa.getHeapModel().getPointerKeyForInstanceField(ik, f);
if (Assertions.verifyAssertions && p == null) {
Assertions.UNREACHABLE();
}
delegate.addNode(val);
delegate.addNode(p);
delegate.addEdge(val, p);
}
}
}
/*
* @see com.ibm.wala.ssa.Instruction.Visitor#visitInvoke(com.ibm.wala.ssa.InvokeInstruction)
*/
@Override
public void visitInvoke(SSAInvokeInstruction instruction) {
for (Iterator it = cg.getPossibleTargets(node, instruction.getCallSite()).iterator(); it.hasNext();) {
CGNode target = (CGNode) it.next();
// some methods, like unmodelled natives, do not have IR.
if (getIR(target) == null)
continue;
// handle parameter passing
for (int i = 0; i < instruction.getNumberOfUses(); i++) {
// we rely on the invariant that the value number for the ith
// parameter
// is i+1
final int vn = i + 1;
if (target.getMethod().getParameterType(i).isReferenceType()) {
PointerKey actual = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getUse(i));
PointerKey formal = pa.getHeapModel().getPointerKeyForLocal(target, vn);
if (actual != null) {
delegate.addNode(actual);
if (formal != null) {
delegate.addNode(formal);
delegate.addEdge(actual, formal);
}
}
}
}
// handle return value.
if (instruction.hasDef() && instruction.getDeclaredResultType().isReferenceType()) {
PointerKey result = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getDef());
PointerKey ret = pa.getHeapModel().getPointerKeyForReturnValue(target);
delegate.addNode(result);
delegate.addNode(ret);
delegate.addEdge(ret, result);
}
// generate contraints from exception return value.
PointerKey e = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getException());
PointerKey er = pa.getHeapModel().getPointerKeyForExceptionalReturnValue(target);
delegate.addNode(e);
delegate.addNode(er);
delegate.addEdge(er, e);
}
}
/*
* @see com.ibm.wala.ssa.Instruction.Visitor#visitThrow(com.ibm.wala.ssa.ThrowInstruction)
*/
@Override
public void visitThrow(SSAThrowInstruction instruction) {
// don't do anything: we handle exceptional edges
// in a separate pass
}
/*
* @see com.ibm.wala.ssa.Instruction.Visitor#visitGetCaughtException(com.ibm.wala.ssa.GetCaughtExceptionInstruction)
*/
@Override
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {
List<ProgramCounter> peis = SSAPropagationCallGraphBuilder.getIncomingPEIs(ir, bb);
PointerKey def = pa.getHeapModel().getPointerKeyForLocal(node, instruction.getDef());
addExceptionEdges(node, delegate, pa, ir, peis, def);
}
}
/**
* Generate constraints which assign exception values into an exception
* pointer
*
* @param node
* governing node
* @param peis
* list of PEI instructions
* @param exceptionVar
* PointerKey representing a pointer to an exception value
*/
private static void addExceptionEdges(CGNode node, Graph<PointerKey> delegate, PointerAnalysis pa, IR ir, List<ProgramCounter> peis, PointerKey exceptionVar) {
delegate.addNode(exceptionVar);
for (Iterator<ProgramCounter> it = peis.iterator(); it.hasNext();) {
ProgramCounter peiLoc = it.next();
SSAInstruction pei = ir.getPEI(peiLoc);
if (pei instanceof SSAAbstractInvokeInstruction) {
SSAAbstractInvokeInstruction s = (SSAAbstractInvokeInstruction) pei;
PointerKey e = pa.getHeapModel().getPointerKeyForLocal(node, s.getException());
delegate.addNode(e);
delegate.addEdge(e, exceptionVar);
} else if (pei instanceof SSAThrowInstruction) {
SSAThrowInstruction s = (SSAThrowInstruction) pei;
PointerKey e = pa.getHeapModel().getPointerKeyForLocal(node, s.getException());
delegate.addNode(e);
delegate.addEdge(e, exceptionVar);
}
}
}
public PointerAnalysis getPointerAnalysis() {
return pa;
}
@Override
public Iterator<PointerKey> iterator() {
// give up on laziness
processAllNodes();
return super.iterator();
}
}

View File

@ -1,11 +0,0 @@
package com.ibm.wala.ipa.callgraph.propagation;
import com.ibm.wala.ipa.callgraph.CallGraph;
public class PointerFlowGraphFactory {
public PointerFlowGraph make(PointerAnalysis pa, CallGraph cg) {
return new PointerFlowGraph(pa, cg);
}
}

View File

@ -751,10 +751,6 @@ public abstract class PropagationCallGraphBuilder implements CallGraphBuilder {
return system.extractPointerAnalysis(this);
}
public PointerFlowGraphFactory getPointerFlowGraphFactory() {
return new PointerFlowGraphFactory();
}
public PropagationSystem getPropagationSystem() {
return system;
}