refactoring

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2531 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
sjfink 2008-02-04 20:42:25 +00:00
parent adef205942
commit 84e00a667a
4 changed files with 164 additions and 141 deletions

View File

@ -0,0 +1,105 @@
/*******************************************************************************
* 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.dataflow.IFDS;
/**
*
* an individual edge <entry, d1> -> <target, d2>
*
* @author sfink
*/
public final class PathEdge<T> {
final T entry;
final int d1;
final T target;
final int d2;
public static <T> PathEdge<T> createPathEdge(T s_p, int d1, T n, int d2) {
return new PathEdge<T>(s_p, d1, n, d2);
}
private PathEdge(T s_p, int d1, T n, int d2) {
this.entry = s_p;
this.d1 = d1;
this.target = n;
this.d2 = d2;
}
@Override
public String toString() {
StringBuffer result = new StringBuffer();
result.append("<");
result.append(entry.toString());
result.append(",");
result.append(d1);
result.append("> -> <");
result.append(target.toString());
result.append(",");
result.append(d2);
result.append(">");
return result.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + d1;
result = prime * result + d2;
result = prime * result + ((target == null) ? 0 : target.hashCode());
result = prime * result + ((entry == null) ? 0 : entry.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final PathEdge other = (PathEdge) obj;
if (d1 != other.d1)
return false;
if (d2 != other.d2)
return false;
if (target == null) {
if (other.target != null)
return false;
} else if (!target.equals(other.target))
return false;
if (entry == null) {
if (other.entry != null)
return false;
} else if (!entry.equals(other.entry))
return false;
return true;
}
public int getD1() {
return d1;
}
public int getD2() {
return d2;
}
public T getEntry() {
return entry;
}
public T getTarget() {
return target;
}
}

View File

@ -208,11 +208,11 @@ public class TabulationSolver<T, P> {
tendToSoftCaches();
}
final PathEdge edge = popFromWorkList();
final PathEdge<T> edge = popFromWorkList();
if (DEBUG_LEVEL > 0) {
System.err.println("TABULATE " + edge);
}
int j = merge(edge.s_p, edge.d1, edge.n, edge.d2);
int j = merge(edge.entry, edge.d1, edge.target, edge.d2);
if (j == -1 && DEBUG_LEVEL > 0) {
System.err.println("merge -1: DROPPING");
}
@ -221,12 +221,12 @@ public class TabulationSolver<T, P> {
// this means that we don't want to push the edge. instead,
// we'll push the merged fact. a little tricky, but i think should
// work.
propagate(edge.s_p, edge.d1, edge.n, j);
propagate(edge.entry, edge.d1, edge.target, j);
} else {
if (supergraph.isCall(edge.n)) {
if (supergraph.isCall(edge.target)) {
// [13]
processCall(edge);
} else if (supergraph.isExit(edge.n)) {
} else if (supergraph.isExit(edge.target)) {
// [21]
processExit(edge);
} else {
@ -274,16 +274,16 @@ public class TabulationSolver<T, P> {
*
* @param edge
*/
private void processNormal(final PathEdge edge) {
private void processNormal(final PathEdge<T> edge) {
if (DEBUG_LEVEL > 0) {
System.err.println("process normal: " + edge);
}
for (Iterator<? extends T> it = supergraph.getSuccNodes(edge.n); it.hasNext();) {
for (Iterator<? extends T> it = supergraph.getSuccNodes(edge.target); it.hasNext();) {
final T m = it.next();
if (DEBUG_LEVEL > 0) {
System.err.println("normal successor: " + m);
}
IUnaryFlowFunction f = flowFunctionMap.getNormalFlowFunction(edge.n, m);
IUnaryFlowFunction f = flowFunctionMap.getNormalFlowFunction(edge.target, m);
IntSet D3 = computeFlow(edge.d2, f);
if (DEBUG_LEVEL > 0) {
System.err.println(" reached: " + D3);
@ -291,7 +291,7 @@ public class TabulationSolver<T, P> {
if (D3 != null) {
D3.foreach(new IntSetAction() {
public void act(int d3) {
propagate(edge.s_p, edge.d1, m, d3);
propagate(edge.entry, edge.d1, m, d3);
}
});
}
@ -304,13 +304,13 @@ public class TabulationSolver<T, P> {
* Note that we've changed the way we record summary edges. Summary edges are now associated with a callee (s_p,exit),
* where the original algorithm used a call, return pair in the caller.
*/
protected void processExit(final PathEdge edge) {
protected void processExit(final PathEdge<T> edge) {
if (DEBUG_LEVEL > 0) {
System.err.println("process exit: " + edge);
}
// succ:= successor nodes of edge.n (the return block in the callee)
IntSet succ = supergraph.getSuccNodeNumbers(edge.n);
IntSet succ = supergraph.getSuccNodeNumbers(edge.target);
if (succ == null) {
// This should only happen for return from the entry point of the supergraph
// (fake root method for whole-program analysis).
@ -321,17 +321,17 @@ public class TabulationSolver<T, P> {
return;
}
final LocalSummaryEdges summaries = findOrCreateLocalSummaryEdges(supergraph.getProcOf(edge.n));
int s_p_n = supergraph.getLocalBlockNumber(edge.s_p);
int x = supergraph.getLocalBlockNumber(edge.n);
final LocalSummaryEdges summaries = findOrCreateLocalSummaryEdges(supergraph.getProcOf(edge.target));
int s_p_n = supergraph.getLocalBlockNumber(edge.entry);
int x = supergraph.getLocalBlockNumber(edge.target);
if (!summaries.contains(s_p_n, x, edge.d1, edge.d2)) {
summaries.insertSummaryEdge(s_p_n, x, edge.d1, edge.d2);
}
final CallFlowEdges callFlow = findOrCreateCallFlowEdges(edge.s_p);
final CallFlowEdges callFlow = findOrCreateCallFlowEdges(edge.entry);
// [22] for each c /in callers(p)
for (Iterator<? extends T> it = supergraph.getPredNodes(edge.s_p); it.hasNext();) {
for (Iterator<? extends T> it = supergraph.getPredNodes(edge.entry); it.hasNext();) {
final T c = it.next();
final int cNum = supergraph.getLocalBlockNumber(c);
if (DEBUG_LEVEL > 0) {
@ -359,7 +359,7 @@ public class TabulationSolver<T, P> {
* @param c a call site of edge.s_p
* @param D4 set of d1 s.t. <c, d1> -> <edge.s_p, edge.d2> was recorded as call flow
*/
private void propagateToReturnSites(final PathEdge edge, IntSet succ, final T c, final IntSet D4) {
private void propagateToReturnSites(final PathEdge<T> edge, IntSet succ, final T c, final IntSet D4) {
if (DEBUG_LEVEL > 1) {
System.err.println("Successor nodes: " + succ);
@ -396,7 +396,7 @@ public class TabulationSolver<T, P> {
if (DEBUG_LEVEL > 1) {
System.err.println("feasible return site: " + retSite);
}
final IFlowFunction retf = flowFunctionMap.getReturnFlowFunction(c, edge.n, retSite);
final IFlowFunction retf = flowFunctionMap.getReturnFlowFunction(c, edge.target, retSite);
if (retf instanceof IBinaryReturnFlowFunction) {
propagateToReturnSiteWithBinaryFlowFunction(edge, c, D4, entries, retSite, retf);
} else {
@ -515,23 +515,23 @@ public class TabulationSolver<T, P> {
/**
* Handle lines [14 - 19] of the algorithm, propagating information into and across a call site.
*/
protected void processCall(final PathEdge edge) {
protected void processCall(final PathEdge<T> edge) {
if (DEBUG_LEVEL > 0) {
System.err.println("process call: " + edge);
}
// c:= number of the call node
final int c = supergraph.getNumber(edge.n);
final int c = supergraph.getNumber(edge.target);
final Collection<T> returnSites = Iterator2Collection.toCollection(supergraph.getReturnSites(edge.n));
final Collection<T> returnSites = Iterator2Collection.toCollection(supergraph.getReturnSites(edge.target));
// [14 - 16]
for (Iterator<? extends T> it = supergraph.getCalledNodes(edge.n); it.hasNext();) {
for (Iterator<? extends T> it = supergraph.getCalledNodes(edge.target); it.hasNext();) {
final T callee = it.next();
if (DEBUG_LEVEL > 0) {
System.err.println(" process callee: " + callee);
}
IUnaryFlowFunction f = flowFunctionMap.getCallFlowFunction(edge.n, callee);
IUnaryFlowFunction f = flowFunctionMap.getCallFlowFunction(edge.target, callee);
// reached := {d1} that reach the callee
IntSet reached = computeFlow(edge.d2, f);
if (DEBUG_LEVEL > 0) {
@ -569,7 +569,7 @@ public class TabulationSolver<T, P> {
// was recorded as a summary edge
IntSet reachedBySummary = summaries.getSummaryEdges(s_p_num, x_num, d1);
if (reachedBySummary != null) {
final IFlowFunction retf = flowFunctionMap.getReturnFlowFunction(edge.n, exit, returnSite);
final IFlowFunction retf = flowFunctionMap.getReturnFlowFunction(edge.target, exit, returnSite);
reachedBySummary.foreach(new IntSetAction() {
public void act(int d2) {
if (retf instanceof IBinaryReturnFlowFunction) {
@ -577,7 +577,7 @@ public class TabulationSolver<T, P> {
if (D5 != null) {
D5.foreach(new IntSetAction() {
public void act(int d5) {
propagate(edge.s_p, edge.d1, returnSite, d5);
propagate(edge.entry, edge.d1, returnSite, d5);
}
});
}
@ -586,7 +586,7 @@ public class TabulationSolver<T, P> {
if (D5 != null) {
D5.foreach(new IntSetAction() {
public void act(int d5) {
propagate(edge.s_p, edge.d1, returnSite, d5);
propagate(edge.entry, edge.d1, returnSite, d5);
}
});
}
@ -604,17 +604,17 @@ public class TabulationSolver<T, P> {
}
// special logic: in backwards problems, a "call" node can have
// "normal" successors as well. deal with these.
for (Iterator<? extends T> it = supergraph.getNormalSuccessors(edge.n); it.hasNext();) {
for (Iterator<? extends T> it = supergraph.getNormalSuccessors(edge.target); it.hasNext();) {
final T m = it.next();
if (DEBUG_LEVEL > 0) {
System.err.println("normal successor: " + m);
}
IUnaryFlowFunction f = flowFunctionMap.getNormalFlowFunction(edge.n, m);
IUnaryFlowFunction f = flowFunctionMap.getNormalFlowFunction(edge.target, m);
IntSet D3 = computeFlow(edge.d2, f);
if (D3 != null) {
D3.foreach(new IntSetAction() {
public void act(int d3) {
propagate(edge.s_p, edge.d1, m, d3);
propagate(edge.entry, edge.d1, m, d3);
}
});
}
@ -628,9 +628,9 @@ public class TabulationSolver<T, P> {
}
IUnaryFlowFunction f = null;
if (hasCallee(returnSite)) {
f = flowFunctionMap.getCallToReturnFlowFunction(edge.n, returnSite);
f = flowFunctionMap.getCallToReturnFlowFunction(edge.target, returnSite);
} else {
f = flowFunctionMap.getCallNoneToReturnFlowFunction(edge.n, returnSite);
f = flowFunctionMap.getCallNoneToReturnFlowFunction(edge.target, returnSite);
}
IntSet reached = computeFlow(edge.d2, f);
if (DEBUG_LEVEL > 0) {
@ -643,7 +643,7 @@ public class TabulationSolver<T, P> {
Assertions._assert(x >= 0);
Assertions._assert(edge.d1 >= 0);
}
propagate(edge.s_p, edge.d1, returnSite, x);
propagate(edge.entry, edge.d1, returnSite, x);
}
});
}
@ -700,13 +700,13 @@ public class TabulationSolver<T, P> {
return f.getSources(d2);
}
protected PathEdge popFromWorkList() {
return (PathEdge) worklist.take();
protected PathEdge<T> popFromWorkList() {
return worklist.take() ;
}
private PathEdge peekFromWorkList() {
// horrible. don't use in performance-critical
PathEdge result = (PathEdge) worklist.take();
PathEdge<T> result = worklist.take();
worklist.insert(result);
return result;
}
@ -784,7 +784,7 @@ public class TabulationSolver<T, P> {
}
protected void addToWorkList(T s_p, int i, T n, int j) {
worklist.insert(new PathEdge(s_p, i, n, j));
worklist.insert(PathEdge.createPathEdge(s_p, i, n, j));
}
protected LocalPathEdges findOrCreateLocalPathEdges(T s_p) {
@ -818,82 +818,6 @@ public class TabulationSolver<T, P> {
return result;
}
/**
* @author sfink
*
* an individual edge <s_p, d1> -> <n, d2>
*/
public final class PathEdge {
final T s_p;
final int d1;
final T n;
final int d2;
PathEdge(T s_p, int d1, T n, int d2) {
this.s_p = s_p;
this.d1 = d1;
this.n = n;
this.d2 = d2;
if (DEBUG_LEVEL > 0 && Assertions.verifyAssertions) {
if (!supergraph.containsNode(s_p)) {
Assertions._assert(false, s_p.toString());
}
if (!supergraph.containsNode(n)) {
Assertions._assert(false, n.toString());
}
}
}
@Override
public String toString() {
StringBuffer result = new StringBuffer();
result.append("<");
result.append(s_p.toString());
result.append(",");
result.append(d1);
result.append("> -> <");
result.append(n.toString());
result.append(",");
result.append(d2);
result.append(">");
return result.toString();
}
@Override
public int hashCode() {
return s_p.hashCode() + d1 * 401 + n.hashCode() * 409 + d2 * 419;
}
@Override
public boolean equals(Object arg0) {
if (getClass().equals(arg0.getClass())) {
PathEdge that = (PathEdge) arg0;
return d1 == that.d1 && d2 == that.d2 && s_p.equals(that.s_p) && (n.equals(that.n));
} else {
return false;
}
}
public int getD1() {
return d1;
}
public int getD2() {
return d2;
}
public Object getSp() {
return s_p;
}
public Object getN() {
return n;
}
}
public class Result implements TabulationResult<T, P> {
/**
@ -1011,16 +935,14 @@ public class TabulationSolver<T, P> {
return supergraph;
}
protected class Worklist extends Heap {
protected class Worklist extends Heap<PathEdge<T>> {
Worklist() {
super(100);
}
@Override
protected boolean compareElements(Object elt1, Object elt2) {
PathEdge p1 = (PathEdge) elt1;
PathEdge p2 = (PathEdge) elt2;
protected boolean compareElements(PathEdge<T> p1, PathEdge<T> p2) {
if (p1.d2 != p2.d2) {
if (problem.getDomain().isWeakerThan(p1.d2, p2.d2)) {
return true;

View File

@ -19,7 +19,7 @@ import com.ibm.wala.util.collections.Heap;
/**
* Worklist for fixed-point solver implementation
*/
public class Worklist extends Heap {
public class Worklist extends Heap<AbstractStatement> {
private final HashSet<AbstractStatement> contents = HashSetFactory.make();
@ -28,14 +28,12 @@ public class Worklist extends Heap {
}
@Override
protected final boolean compareElements(Object o1, Object o2) {
AbstractStatement eq1 = (AbstractStatement) o1;
AbstractStatement eq2 = (AbstractStatement) o2;
protected final boolean compareElements(AbstractStatement eq1, AbstractStatement eq2) {
return (eq1.getOrderNumber() < eq2.getOrderNumber());
}
public AbstractStatement takeStatement() throws NoSuchElementException {
AbstractStatement result = (AbstractStatement)super.take();
AbstractStatement result = super.take();
contents.remove(result);
return result;
}

View File

@ -18,16 +18,16 @@ import java.util.NoSuchElementException;
* @author Julian Dolby
*/
public abstract class Heap {
public abstract class Heap<T> {
/**
* @return true iff elt1 is considered < elt2
*/
abstract protected boolean compareElements(Object elt1, Object elt2);
abstract protected boolean compareElements(T elt1, T elt2);
private int numberOfElements;
private Object[] backingStore;
private T[] backingStore;
/**
* @return number of elements in this heap
@ -36,9 +36,10 @@ public abstract class Heap {
return numberOfElements;
}
@SuppressWarnings("unchecked")
public Heap(int initialCapacity) {
numberOfElements = 0;
backingStore = new Object[initialCapacity];
backingStore = (T[])new Object[initialCapacity];
}
/**
@ -48,10 +49,8 @@ public abstract class Heap {
return numberOfElements == 0;
}
/**
* @param elt
*/
public void insert(Object elt) {
public void insert(T elt) {
ensureCapacity(numberOfElements + 1);
bubbleUp(elt, numberOfElements);
numberOfElements++;
@ -60,11 +59,11 @@ public abstract class Heap {
/**
* @return the first object in the priority queue
*/
public Object take() throws NoSuchElementException {
public T take() throws NoSuchElementException {
if (numberOfElements == 0) {
throw new NoSuchElementException();
}
Object result = backingStore[0];
T result = backingStore[0];
removeElement(0);
return result;
}
@ -81,12 +80,11 @@ public abstract class Heap {
return index * 2 + 2;
}
/**
* @param min
*/
@SuppressWarnings("unchecked")
final private void ensureCapacity(int min) {
if (backingStore.length < min) {
Object newStore[] = new Object[2 * min];
T newStore[] = (T[])new Object[2 * min];
System.arraycopy(backingStore, 0, newStore, 0, backingStore.length);
backingStore = newStore;
}
@ -100,14 +98,14 @@ public abstract class Heap {
*/
final private void removeElement(int index) {
int ne = numberOfElements;
Object[] bs = backingStore;
T[] bs = backingStore;
while (true) {
int leftIndex = heapLeftChild(index);
if (leftIndex < ne) {
int rightIndex = heapRightChild(index);
if (rightIndex < ne) {
Object leftObject = bs[leftIndex];
Object rightObject = bs[rightIndex];
T leftObject = bs[leftIndex];
T rightObject = bs[rightIndex];
if (compareElements(leftObject, rightObject)) {
bs[index] = leftObject;
index = leftIndex;
@ -138,15 +136,15 @@ public abstract class Heap {
* @param elt
* @param index
*/
final private void bubbleUp(Object elt, int index) {
Object[] bs = backingStore;
final private void bubbleUp(T elt, int index) {
T[] bs = backingStore;
while (true) {
if (index == 0) {
bs[index] = elt;
return;
}
int hpIndex = heapParent(index);
Object parent = bs[hpIndex];
T parent = bs[hpIndex];
if (compareElements(parent, elt)) {
bs[index] = elt;
return;