public class ArrayBoundsGraph extends DirectedHyperGraph<java.lang.Integer>
As it is written The paper describes, that the distance is equal to the shortest hyper path. But what if we don't know anything about a variable (i.e. it is returned by a method)? There will be no path at all, the distance should be unlimited.
Initializing all nodes with -infinity instead of infinity, seems to work at first glance, as we also have hyper edges with more than one source, which cause the maximum to be propagated instead of minimum. However, this will not work, as loops will not get updated properly.
We need to make sure, that only nodes, which are not connected to the source of shortest path computation are set to infinity. To do so, it is enough to set nodes, which don't have a predecessor to infinity. (Nodes in cycles will always have an ancestor, which is not part of the cycle. So all nodes are either connected to the source, or a node with no predecessor.)
In this implementation this is done, by adding an infinity node and connect all lose ends to
it (see ArrayBoundsGraphBuilder.bundleDeadEnds(ArrayBoundsGraph)). Note, that array
length and the zero node are dead ends, if they are not the source of a shortest path
computation. To prevent changing the inequality graph, depending on which source is used, a kind
of trap door construct is used (See createSourceVar(Integer)).
There are some variations, but these are minor changes to improve results:
addConstant(Integer, Integer))
addPhi(Integer))
arrayLength)
| Modifier and Type | Field and Description |
|---|---|
static java.lang.Integer |
UNLIMITED
We need a ssa variable representing unlimited (values we don't know anything about).
|
static java.lang.Integer |
ZERO
We need a ssa variable representing zero.
|
static java.lang.Integer |
ZERO_HELPER |
| Constructor and Description |
|---|
ArrayBoundsGraph() |
| Modifier and Type | Method and Description |
|---|---|
void |
addAdditionEdge(java.lang.Integer src,
java.lang.Integer dst,
java.lang.Integer value) |
void |
addArray(java.lang.Integer array) |
void |
addConstant(java.lang.Integer variable,
java.lang.Integer value)
Add variable as constant with value value.
|
void |
addEdge(java.lang.Integer src,
java.lang.Integer dst) |
HyperNode<java.lang.Integer> |
addNode(java.lang.Integer value) |
void |
addPhi(java.lang.Integer dst) |
void |
addPi(java.lang.Integer dst,
java.lang.Integer src1,
java.lang.Integer src2) |
void |
createSourceVar(java.lang.Integer var)
Adds var as source var.
|
java.lang.Integer |
generateNewVar() |
java.util.HashMap<java.lang.Integer,java.util.Set<java.lang.Integer>> |
getArrayAccess() |
java.util.HashMap<java.lang.Integer,java.lang.Integer> |
getArrayLength() |
java.lang.Integer |
getArrayNode(java.lang.Integer array) |
java.util.HashSet<java.lang.Integer> |
getPhis() |
Weight |
getVariableWeight(java.lang.Integer variable) |
void |
markAsArrayAccess(java.lang.Integer array,
java.lang.Integer index) |
void |
markAsArrayLength(java.lang.Integer array,
java.lang.Integer variable)
Mark variable as length for array.
|
void |
markAsDeadEnd(java.lang.Integer variable) |
void |
postProcessConstants() |
void |
reset()
Resets the weight of all nodes.
|
getEdges, getNodes, toString, updateNodeEdgespublic static final java.lang.Integer ZERO
public static final java.lang.Integer ZERO_HELPER
public static final java.lang.Integer UNLIMITED
public void postProcessConstants()
public void addAdditionEdge(java.lang.Integer src,
java.lang.Integer dst,
java.lang.Integer value)
public void addArray(java.lang.Integer array)
public void addConstant(java.lang.Integer variable,
java.lang.Integer value)
This will create the following construct: [zero] -(value)-> [h1] -0- > [variable] -(-value)-> [h2] -0-> [zero].
The bidirectional linking, allows things like
int[] a = new int[2](); a[0] = 1;to work properly. h1, h2 are helper nodes: [zero] and [variable] may have other predecessors, this will cause their in edges to be merged to a single hyper edge with weight zero. The helper nodes are inserted to keep the proper distance from [zero].
public void addEdge(java.lang.Integer src,
java.lang.Integer dst)
public HyperNode<java.lang.Integer> addNode(java.lang.Integer value)
public void addPhi(java.lang.Integer dst)
public void addPi(java.lang.Integer dst,
java.lang.Integer src1,
java.lang.Integer src2)
public void createSourceVar(java.lang.Integer var)
This will create the following construct: [unlimited] -> [var] -> [var] -(unlimited)-> [unlimited]
This is a trap door construct: if [var] is not set to 0 it will get the value unlimited, if [var] is set to 0 it will stay 0.
public java.lang.Integer generateNewVar()
public java.util.HashMap<java.lang.Integer,java.util.Set<java.lang.Integer>> getArrayAccess()
public java.util.HashMap<java.lang.Integer,java.lang.Integer> getArrayLength()
public java.lang.Integer getArrayNode(java.lang.Integer array)
public java.util.HashSet<java.lang.Integer> getPhis()
public void markAsArrayAccess(java.lang.Integer array,
java.lang.Integer index)
public void markAsArrayLength(java.lang.Integer array,
java.lang.Integer variable)
public void markAsDeadEnd(java.lang.Integer variable)
public Weight getVariableWeight(java.lang.Integer variable)
public void reset()
DirectedHyperGraphreset in class DirectedHyperGraph<java.lang.Integer>