2012-09-04 22:56:05 +00:00
|
|
|
/*******************************************************************************
|
|
|
|
* 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.analysis.pointers;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.Comparator;
|
|
|
|
import java.util.Iterator;
|
2017-11-12 01:29:04 +00:00
|
|
|
import java.util.function.IntFunction;
|
2012-09-04 22:56:05 +00:00
|
|
|
|
|
|
|
import com.ibm.wala.classLoader.IClass;
|
|
|
|
import com.ibm.wala.classLoader.IField;
|
|
|
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
|
|
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
|
|
|
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
|
|
|
|
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
|
|
|
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
|
|
|
import com.ibm.wala.types.TypeReference;
|
|
|
|
import com.ibm.wala.util.collections.CompoundIterator;
|
|
|
|
import com.ibm.wala.util.collections.EmptyIterator;
|
|
|
|
import com.ibm.wala.util.collections.IntMapIterator;
|
|
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
|
|
import com.ibm.wala.util.debug.UnimplementedError;
|
|
|
|
import com.ibm.wala.util.graph.AbstractNumberedGraph;
|
|
|
|
import com.ibm.wala.util.graph.NumberedEdgeManager;
|
|
|
|
import com.ibm.wala.util.graph.NumberedGraph;
|
|
|
|
import com.ibm.wala.util.graph.NumberedNodeManager;
|
|
|
|
import com.ibm.wala.util.graph.impl.NumberedNodeIterator;
|
|
|
|
import com.ibm.wala.util.intset.BasicNaturalRelation;
|
|
|
|
import com.ibm.wala.util.intset.IBinaryNaturalRelation;
|
|
|
|
import com.ibm.wala.util.intset.IntSet;
|
|
|
|
import com.ibm.wala.util.intset.IntSetUtil;
|
|
|
|
import com.ibm.wala.util.intset.MutableMapping;
|
|
|
|
import com.ibm.wala.util.intset.MutableSparseIntSet;
|
|
|
|
import com.ibm.wala.util.intset.MutableSparseIntSetFactory;
|
|
|
|
import com.ibm.wala.util.intset.OrdinalSet;
|
|
|
|
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
|
|
|
import com.ibm.wala.util.intset.SparseIntSet;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Basic implementation of {@link HeapGraph}
|
|
|
|
*/
|
2016-08-19 02:43:12 +00:00
|
|
|
public class BasicHeapGraph<T extends InstanceKey> extends HeapGraphImpl<T> {
|
2012-09-04 22:56:05 +00:00
|
|
|
|
|
|
|
private final static boolean VERBOSE = false;
|
|
|
|
|
|
|
|
private final static int VERBOSE_INTERVAL = 10000;
|
|
|
|
|
|
|
|
private final static MutableSparseIntSetFactory factory = new MutableSparseIntSetFactory();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The backing graph
|
|
|
|
*/
|
|
|
|
private final NumberedGraph<Object> G;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* governing call graph
|
|
|
|
*/
|
|
|
|
private final CallGraph callGraph;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param P governing pointer analysis
|
|
|
|
* @throws NullPointerException if P is null
|
|
|
|
*/
|
2016-08-19 02:43:12 +00:00
|
|
|
public BasicHeapGraph(final PointerAnalysis<T> P, final CallGraph callGraph) throws NullPointerException {
|
2012-09-04 22:56:05 +00:00
|
|
|
super(P);
|
|
|
|
this.callGraph = callGraph;
|
|
|
|
|
|
|
|
final OrdinalSetMapping<PointerKey> pointerKeys = getPointerKeys();
|
|
|
|
final NumberedNodeManager<Object> nodeMgr = new NumberedNodeManager<Object>() {
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Iterator<Object> iterator() {
|
|
|
|
return new CompoundIterator<Object>(pointerKeys.iterator(), P.getInstanceKeyMapping().iterator());
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getNumberOfNodes() {
|
|
|
|
return pointerKeys.getSize() + P.getInstanceKeyMapping().getSize();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void addNode(Object n) {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeNode(Object n) {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getNumber(Object N) {
|
|
|
|
if (N instanceof PointerKey) {
|
2017-03-15 05:04:21 +00:00
|
|
|
return pointerKeys.getMappedIndex(N);
|
2012-09-04 22:56:05 +00:00
|
|
|
} else {
|
|
|
|
if (!(N instanceof InstanceKey)) {
|
|
|
|
Assertions.UNREACHABLE(N.getClass().toString());
|
|
|
|
}
|
2017-03-15 05:04:21 +00:00
|
|
|
int inumber = P.getInstanceKeyMapping().getMappedIndex(N);
|
2012-09-04 22:56:05 +00:00
|
|
|
return (inumber == -1) ? -1 : inumber + pointerKeys.getMaximumIndex() + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Object getNode(int number) {
|
|
|
|
if (number > pointerKeys.getMaximumIndex()) {
|
|
|
|
return P.getInstanceKeyMapping().getMappedObject(number - pointerKeys.getSize());
|
|
|
|
} else {
|
|
|
|
return pointerKeys.getMappedObject(number);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getMaxNumber() {
|
|
|
|
return getNumberOfNodes() - 1;
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public boolean containsNode(Object n) {
|
|
|
|
return getNumber(n) != -1;
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Iterator<Object> iterateNodes(IntSet s) {
|
|
|
|
return new NumberedNodeIterator<Object>(s, this);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
final IBinaryNaturalRelation pred = computePredecessors(nodeMgr);
|
|
|
|
final IntFunction<Object> toNode = new IntFunction<Object>() {
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Object apply(int i) {
|
|
|
|
return nodeMgr.getNode(i);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
this.G = new AbstractNumberedGraph<Object>() {
|
|
|
|
private final NumberedEdgeManager<Object> edgeMgr = new NumberedEdgeManager<Object>() {
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Iterator<Object> getPredNodes(Object N) {
|
|
|
|
int n = nodeMgr.getNumber(N);
|
|
|
|
IntSet p = pred.getRelated(n);
|
|
|
|
if (p == null) {
|
|
|
|
return EmptyIterator.instance();
|
|
|
|
} else {
|
|
|
|
return new IntMapIterator<Object>(p.intIterator(), toNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public IntSet getPredNodeNumbers(Object N) {
|
|
|
|
int n = nodeMgr.getNumber(N);
|
|
|
|
IntSet p = pred.getRelated(n);
|
|
|
|
if (p != null) {
|
|
|
|
return p;
|
|
|
|
} else {
|
|
|
|
return IntSetUtil.make();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getPredNodeCount(Object N) {
|
|
|
|
int n = nodeMgr.getNumber(N);
|
|
|
|
return pred.getRelatedCount(n);
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Iterator<Object> getSuccNodes(Object N) {
|
|
|
|
int[] succ = computeSuccNodeNumbers(N, nodeMgr);
|
|
|
|
if (succ == null) {
|
|
|
|
return EmptyIterator.instance();
|
|
|
|
}
|
|
|
|
SparseIntSet s = factory.make(succ);
|
|
|
|
return new IntMapIterator<Object>(s.intIterator(), toNode);
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public IntSet getSuccNodeNumbers(Object N) {
|
|
|
|
int[] succ = computeSuccNodeNumbers(N, nodeMgr);
|
|
|
|
if (succ == null) {
|
|
|
|
return IntSetUtil.make();
|
|
|
|
} else {
|
|
|
|
return IntSetUtil.make(succ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getSuccNodeCount(Object N) {
|
|
|
|
int[] succ = computeSuccNodeNumbers(N, nodeMgr);
|
|
|
|
return succ == null ? 0 : succ.length;
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void addEdge(Object src, Object dst) {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeEdge(Object src, Object dst) {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeAllIncidentEdges(Object node) {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeIncomingEdges(Object node) {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeOutgoingEdges(Object node) {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public boolean hasEdge(Object src, Object dst) {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected NumberedNodeManager<Object> getNodeManager() {
|
|
|
|
return nodeMgr;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected NumberedEdgeManager<Object> getEdgeManager() {
|
|
|
|
return edgeMgr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSetMapping<PointerKey> getPointerKeys() {
|
|
|
|
MutableMapping<PointerKey> result = MutableMapping.make();
|
|
|
|
|
2017-11-28 20:26:09 +00:00
|
|
|
for (PointerKey p : getPointerAnalysis().getPointerKeys()) {
|
2012-09-04 22:56:05 +00:00
|
|
|
result.add(p);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private int[] computeSuccNodeNumbers(Object N, NumberedNodeManager<Object> nodeManager) {
|
|
|
|
if (N instanceof PointerKey) {
|
|
|
|
PointerKey P = (PointerKey) N;
|
2016-08-19 02:43:12 +00:00
|
|
|
OrdinalSet<T> S = getPointerAnalysis().getPointsToSet(P);
|
2012-09-04 22:56:05 +00:00
|
|
|
int[] result = new int[S.size()];
|
|
|
|
int i = 0;
|
2017-11-28 20:26:09 +00:00
|
|
|
for (T t : S) {
|
|
|
|
result[i] = nodeManager.getNumber(t);
|
2012-09-04 22:56:05 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
} else if (N instanceof InstanceKey) {
|
|
|
|
InstanceKey I = (InstanceKey) N;
|
|
|
|
TypeReference T = I.getConcreteType().getReference();
|
|
|
|
|
2017-08-06 01:54:42 +00:00
|
|
|
assert T != null : "null concrete type from " + I.getClass();
|
2012-09-04 22:56:05 +00:00
|
|
|
if (T.isArrayType()) {
|
|
|
|
PointerKey p = getHeapModel().getPointerKeyForArrayContents(I);
|
|
|
|
if (p == null || !nodeManager.containsNode(p)) {
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
return new int[] { nodeManager.getNumber(p) };
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
IClass klass = getHeapModel().getClassHierarchy().lookupClass(T);
|
2017-08-06 01:54:42 +00:00
|
|
|
assert klass != null : "null klass for type " + T;
|
2012-09-04 22:56:05 +00:00
|
|
|
MutableSparseIntSet result = MutableSparseIntSet.makeEmpty();
|
2017-11-28 20:26:09 +00:00
|
|
|
for (IField f : klass.getAllInstanceFields()) {
|
2012-09-04 22:56:05 +00:00
|
|
|
if (!f.getReference().getFieldType().isPrimitiveType()) {
|
|
|
|
PointerKey p = getHeapModel().getPointerKeyForInstanceField(I, f);
|
|
|
|
if (p != null && nodeManager.containsNode(p)) {
|
|
|
|
result.add(nodeManager.getNumber(p));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result.toIntArray();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Assertions.UNREACHABLE("Unexpected type: " + N.getClass());
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return R, y \in R(x,y) if the node y is a predecessor of node x
|
|
|
|
*/
|
|
|
|
private IBinaryNaturalRelation computePredecessors(NumberedNodeManager<Object> nodeManager) {
|
|
|
|
BasicNaturalRelation R = new BasicNaturalRelation(new byte[] { BasicNaturalRelation.SIMPLE }, BasicNaturalRelation.SIMPLE);
|
|
|
|
|
|
|
|
// we split the following loops to improve temporal locality,
|
|
|
|
// particularly for locals
|
|
|
|
computePredecessorsForNonLocals(nodeManager, R);
|
|
|
|
computePredecessorsForLocals(nodeManager, R);
|
|
|
|
|
|
|
|
return R;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void computePredecessorsForNonLocals(NumberedNodeManager<Object> nodeManager, BasicNaturalRelation R) {
|
|
|
|
// Note: we run this loop backwards on purpose, to avoid lots of resizing of
|
|
|
|
// bitvectors
|
|
|
|
// in the backing relation. i.e., we will add the biggest bits first.
|
|
|
|
// pretty damn tricky.
|
|
|
|
for (int i = nodeManager.getMaxNumber(); i >= 0; i--) {
|
|
|
|
if (VERBOSE) {
|
|
|
|
if (i % VERBOSE_INTERVAL == 0) {
|
|
|
|
System.err.println("Building HeapGraph: " + i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Object n = nodeManager.getNode(i);
|
|
|
|
if (!(n instanceof LocalPointerKey)) {
|
|
|
|
int[] succ = computeSuccNodeNumbers(n, nodeManager);
|
|
|
|
if (succ != null) {
|
2017-11-28 20:26:09 +00:00
|
|
|
for (int j : succ) {
|
2012-09-04 22:56:05 +00:00
|
|
|
R.add(j, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* traverse locals in order, first by node, then by value number: attempt to improve locality
|
|
|
|
*/
|
|
|
|
private void computePredecessorsForLocals(NumberedNodeManager<Object> nodeManager, BasicNaturalRelation R) {
|
|
|
|
|
|
|
|
ArrayList<LocalPointerKey> list = new ArrayList<LocalPointerKey>();
|
2017-11-28 20:26:09 +00:00
|
|
|
for (Object n : nodeManager) {
|
2012-09-04 22:56:05 +00:00
|
|
|
if (n instanceof LocalPointerKey) {
|
|
|
|
list.add((LocalPointerKey) n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Object[] arr = list.toArray();
|
|
|
|
Arrays.sort(arr, new LocalPointerComparator());
|
|
|
|
|
|
|
|
for (int i = 0; i < arr.length; i++) {
|
|
|
|
if (VERBOSE) {
|
|
|
|
if (i % VERBOSE_INTERVAL == 0) {
|
|
|
|
System.err.println("Building HeapGraph: " + i + " of " + arr.length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
LocalPointerKey n = (LocalPointerKey) arr[i];
|
|
|
|
int num = nodeManager.getNumber(n);
|
|
|
|
int[] succ = computeSuccNodeNumbers(n, nodeManager);
|
|
|
|
if (succ != null) {
|
2017-11-28 20:26:09 +00:00
|
|
|
for (int j : succ) {
|
2012-09-04 22:56:05 +00:00
|
|
|
R.add(j, num);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* sorts local pointers by node, then value number
|
|
|
|
*/
|
|
|
|
private final class LocalPointerComparator implements Comparator<Object> {
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int compare(Object arg1, Object arg2) {
|
|
|
|
LocalPointerKey o1 = (LocalPointerKey) arg1;
|
|
|
|
LocalPointerKey o2 = (LocalPointerKey) arg2;
|
|
|
|
if (o1.getNode().equals(o2.getNode())) {
|
|
|
|
return o1.getValueNumber() - o2.getValueNumber();
|
|
|
|
} else {
|
|
|
|
return callGraph.getNumber(o1.getNode()) - callGraph.getNumber(o2.getNode());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.NumberedNodeManager#getNumber(com.ibm.wala.util.graph.Node)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getNumber(Object N) {
|
|
|
|
return G.getNumber(N);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.NumberedNodeManager#getNode(int)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Object getNode(int number) {
|
|
|
|
return G.getNode(number);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.NumberedNodeManager#getMaxNumber()
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getMaxNumber() {
|
|
|
|
return G.getMaxNumber();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.NodeManager#iterateNodes()
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Iterator<Object> iterator() {
|
|
|
|
return G.iterator();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.NodeManager#getNumberOfNodes()
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getNumberOfNodes() {
|
|
|
|
return G.getNumberOfNodes();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodes(com.ibm.wala.util.graph.Node)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Iterator<Object> getPredNodes(Object N) {
|
|
|
|
return G.getPredNodes(N);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.EdgeManager#getPredNodeCount(com.ibm.wala.util.graph.Node)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getPredNodeCount(Object N) {
|
|
|
|
return G.getPredNodeCount(N);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodes(com.ibm.wala.util.graph.Node)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public Iterator<Object> getSuccNodes(Object N) {
|
|
|
|
return G.getSuccNodes(N);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.EdgeManager#getSuccNodeCount(com.ibm.wala.util.graph.Node)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public int getSuccNodeCount(Object N) {
|
|
|
|
return G.getSuccNodeCount(N);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.NodeManager#addNode(com.ibm.wala.util.graph.Node)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void addNode(Object n) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.NodeManager#remove(com.ibm.wala.util.graph.Node)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeNode(Object n) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void addEdge(Object from, Object to) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeEdge(Object from, Object to) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public boolean hasEdge(Object from, Object to) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeAllIncidentEdges(Object node) throws UnsupportedOperationException {
|
|
|
|
throw new UnsupportedOperationException();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.util.graph.NodeManager#containsNode(com.ibm.wala.util.graph.Node)
|
|
|
|
*/
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public boolean containsNode(Object N) {
|
|
|
|
return G.containsNode(N);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
StringBuffer result = new StringBuffer();
|
|
|
|
result.append("Nodes:\n");
|
|
|
|
for (int i = 0; i <= getMaxNumber(); i++) {
|
|
|
|
Object node = getNode(i);
|
|
|
|
if (node != null) {
|
|
|
|
result.append(i).append(" ").append(node).append("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result.append("Edges:\n");
|
|
|
|
for (int i = 0; i <= getMaxNumber(); i++) {
|
|
|
|
Object node = getNode(i);
|
|
|
|
if (node != null) {
|
|
|
|
result.append(i).append(" -> ");
|
2017-11-28 20:02:37 +00:00
|
|
|
for (Iterator<Object> it = getSuccNodes(node); it.hasNext();) {
|
2012-09-04 22:56:05 +00:00
|
|
|
Object s = it.next();
|
|
|
|
result.append(getNumber(s)).append(" ");
|
|
|
|
}
|
|
|
|
result.append("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result.toString();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeIncomingEdges(Object node) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public void removeOutgoingEdges(Object node) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public IntSet getSuccNodeNumbers(Object node) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-06-25 15:57:37 +00:00
|
|
|
@Override
|
2012-09-04 22:56:05 +00:00
|
|
|
public IntSet getPredNodeNumbers(Object node) throws UnimplementedError {
|
|
|
|
Assertions.UNREACHABLE();
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|