2006-11-22 17:38:46 +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.ipa.callgraph.propagation;
|
|
|
|
|
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Set;
|
|
|
|
|
|
|
|
import com.ibm.wala.classLoader.IClass;
|
|
|
|
import com.ibm.wala.classLoader.IField;
|
|
|
|
import com.ibm.wala.classLoader.NewSiteReference;
|
|
|
|
import com.ibm.wala.classLoader.ProgramCounter;
|
|
|
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
|
|
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
2007-06-01 03:26:18 +00:00
|
|
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
2006-11-22 17:38:46 +00:00
|
|
|
import com.ibm.wala.ssa.DefUse;
|
|
|
|
import com.ibm.wala.ssa.IR;
|
|
|
|
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
|
|
|
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
|
|
|
|
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.SSANewInstruction;
|
|
|
|
import com.ibm.wala.ssa.SSAPhiInstruction;
|
|
|
|
import com.ibm.wala.ssa.SSAPiInstruction;
|
|
|
|
import com.ibm.wala.ssa.SSAThrowInstruction;
|
|
|
|
import com.ibm.wala.types.FieldReference;
|
|
|
|
import com.ibm.wala.types.TypeReference;
|
2007-11-29 18:54:44 +00:00
|
|
|
import com.ibm.wala.util.collections.HashSetFactory;
|
2011-07-22 15:53:33 +00:00
|
|
|
import com.ibm.wala.util.collections.Iterator2Iterable;
|
2006-11-22 17:38:46 +00:00
|
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
|
|
import com.ibm.wala.util.intset.IntSet;
|
|
|
|
import com.ibm.wala.util.intset.MutableMapping;
|
|
|
|
import com.ibm.wala.util.intset.MutableSparseIntSet;
|
|
|
|
import com.ibm.wala.util.intset.OrdinalSet;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* General representation of the results of pointer analysis
|
|
|
|
*/
|
|
|
|
public class PointerAnalysisImpl extends AbstractPointerAnalysis {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* mapping from PointerKey to PointsToSetVariable
|
|
|
|
*/
|
|
|
|
private final PointsToMap pointsToMap;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Meta-data regarding heap abstractions
|
|
|
|
*/
|
|
|
|
private final HeapModel H;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An object that abstracts how to model pointers in the heap.
|
|
|
|
*/
|
|
|
|
private final PointerKeyFactory pointerKeys;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An object that abstracts how to model instances in the heap.
|
|
|
|
*/
|
|
|
|
private final InstanceKeyFactory iKeyFactory;
|
|
|
|
|
2012-01-06 21:22:58 +00:00
|
|
|
protected final PropagationCallGraphBuilder builder;
|
2006-11-22 17:38:46 +00:00
|
|
|
|
2007-01-08 21:29:40 +00:00
|
|
|
public PointerAnalysisImpl(PropagationCallGraphBuilder builder, CallGraph cg, PointsToMap pointsToMap,
|
|
|
|
MutableMapping<InstanceKey> instanceKeys, PointerKeyFactory pointerKeys, InstanceKeyFactory iKeyFactory) {
|
2006-11-22 17:38:46 +00:00
|
|
|
super(cg, instanceKeys);
|
|
|
|
this.builder = builder;
|
|
|
|
this.pointerKeys = pointerKeys;
|
|
|
|
this.iKeyFactory = iKeyFactory;
|
|
|
|
this.pointsToMap = pointsToMap;
|
2009-03-11 17:44:29 +00:00
|
|
|
if (iKeyFactory == null) {
|
|
|
|
throw new IllegalArgumentException("null iKeyFactory");
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
H = makeHeapModel();
|
|
|
|
}
|
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public String toString() {
|
|
|
|
StringBuffer result = new StringBuffer("PointerAnalysis:\n");
|
|
|
|
for (Iterator it = pointsToMap.iterateKeys(); it.hasNext();) {
|
|
|
|
PointerKey p = (PointerKey) it.next();
|
|
|
|
OrdinalSet O = getPointsToSet(p);
|
|
|
|
result.append(" ").append(p).append(" ->\n");
|
|
|
|
for (Iterator it2 = O.iterator(); it2.hasNext();) {
|
|
|
|
result.append(" ").append(it2.next()).append("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
private HeapModel makeHeapModel() {
|
|
|
|
return new HModel();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis#getPointsToSet(com.ibm.wala.ipa.callgraph.propagation.PointerKey)
|
|
|
|
*/
|
2007-11-29 18:54:44 +00:00
|
|
|
@SuppressWarnings("unchecked")
|
2006-11-22 17:38:46 +00:00
|
|
|
public OrdinalSet<InstanceKey> getPointsToSet(PointerKey key) {
|
|
|
|
if (pointsToMap.isImplicit(key)) {
|
|
|
|
return computeImplicitPointsToSet(key);
|
|
|
|
}
|
2009-05-01 17:42:28 +00:00
|
|
|
|
2007-11-29 18:54:44 +00:00
|
|
|
// special logic to handle contents of char[] from string constants.
|
|
|
|
if (key instanceof InstanceFieldKey) {
|
2009-05-01 17:42:28 +00:00
|
|
|
InstanceFieldKey ifk = (InstanceFieldKey) key;
|
2007-11-29 18:54:44 +00:00
|
|
|
if (ifk.getInstanceKey() instanceof ConstantKey) {
|
2009-05-01 17:42:28 +00:00
|
|
|
ConstantKey<?> i = (ConstantKey<?>) ifk.getInstanceKey();
|
2007-11-29 18:54:44 +00:00
|
|
|
if (i.getValue() instanceof String) {
|
|
|
|
StringConstantCharArray contents = StringConstantCharArray.make((ConstantKey<String>) i);
|
|
|
|
instanceKeys.add(contents);
|
|
|
|
Collection<InstanceKey> singleton = HashSetFactory.make();
|
|
|
|
singleton.add(contents);
|
|
|
|
return OrdinalSet.toOrdinalSet(singleton, instanceKeys);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-05-01 17:42:28 +00:00
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
PointsToSetVariable v = pointsToMap.getPointsToSet(key);
|
|
|
|
|
|
|
|
if (v == null) {
|
|
|
|
return OrdinalSet.empty();
|
|
|
|
} else {
|
|
|
|
IntSet S = v.getValue();
|
|
|
|
return new OrdinalSet<InstanceKey>(S, instanceKeys);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-05-01 17:42:28 +00:00
|
|
|
* did the pointer analysis use a type filter for a given points-to set? (this is ugly).
|
2006-11-22 17:38:46 +00:00
|
|
|
*/
|
|
|
|
public boolean isFiltered(PointerKey key) {
|
|
|
|
if (pointsToMap.isImplicit(key)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
PointsToSetVariable v = pointsToMap.getPointsToSet(key);
|
|
|
|
if (v == null) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return v.getPointerKey() instanceof FilteredPointerKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-01 03:26:18 +00:00
|
|
|
protected static class ImplicitPointsToSetVisitor extends SSAInstruction.Visitor {
|
|
|
|
protected final PointerAnalysisImpl analysis;
|
2009-05-01 17:42:28 +00:00
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
protected final CGNode node;
|
2007-01-08 21:29:40 +00:00
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
protected final LocalPointerKey lpk;
|
2007-01-08 21:29:40 +00:00
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
protected OrdinalSet<InstanceKey> pointsToSet = null;
|
|
|
|
|
2009-05-01 17:42:28 +00:00
|
|
|
protected ImplicitPointsToSetVisitor(PointerAnalysisImpl analysis, LocalPointerKey lpk) {
|
2006-11-22 17:38:46 +00:00
|
|
|
this.lpk = lpk;
|
|
|
|
this.node = lpk.getNode();
|
2007-06-01 03:26:18 +00:00
|
|
|
this.analysis = analysis;
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public void visitNew(SSANewInstruction instruction) {
|
|
|
|
pointsToSet = OrdinalSet.empty();
|
|
|
|
}
|
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public void visitInvoke(SSAInvokeInstruction instruction) {
|
2009-05-01 17:42:28 +00:00
|
|
|
pointsToSet = analysis.computeImplicitPointsToSetAtCall(lpk, node, instruction);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
2009-05-01 17:42:28 +00:00
|
|
|
pointsToSet = analysis.computeImplicitPointsToSetAtCheckCast(node, instruction);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {
|
2009-05-01 17:42:28 +00:00
|
|
|
pointsToSet = analysis.computeImplicitPointsToSetAtCatch(node, instruction);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public void visitGet(SSAGetInstruction instruction) {
|
2009-05-01 17:42:28 +00:00
|
|
|
pointsToSet = analysis.computeImplicitPointsToSetAtGet(node, instruction);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public void visitPhi(SSAPhiInstruction instruction) {
|
2009-05-01 17:42:28 +00:00
|
|
|
pointsToSet = analysis.computeImplicitPointsToSetAtPhi(node, instruction);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
2007-01-08 21:29:40 +00:00
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public void visitPi(SSAPiInstruction instruction) {
|
2009-05-01 17:42:28 +00:00
|
|
|
pointsToSet = analysis.computeImplicitPointsToSetAtPi(node, instruction);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
2007-05-30 15:16:05 +00:00
|
|
|
@Override
|
2006-11-22 17:38:46 +00:00
|
|
|
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
2009-05-01 17:42:28 +00:00
|
|
|
pointsToSet = analysis.computeImplicitPointsToSetAtALoad(node, instruction);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
};
|
2007-01-08 21:29:40 +00:00
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
protected ImplicitPointsToSetVisitor makeImplicitPointsToVisitor(LocalPointerKey lpk) {
|
2007-06-01 03:26:18 +00:00
|
|
|
return new ImplicitPointsToSetVisitor(this, lpk);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSet<InstanceKey> computeImplicitPointsToSet(PointerKey key) {
|
|
|
|
if (key instanceof LocalPointerKey) {
|
|
|
|
LocalPointerKey lpk = (LocalPointerKey) key;
|
|
|
|
CGNode node = lpk.getNode();
|
2007-07-06 22:08:13 +00:00
|
|
|
IR ir = node.getIR();
|
|
|
|
DefUse du = node.getDU();
|
2007-01-08 21:29:40 +00:00
|
|
|
if (((SSAPropagationCallGraphBuilder) builder).contentsAreInvariant(ir.getSymbolTable(), du, lpk.getValueNumber())) {
|
2006-11-22 17:38:46 +00:00
|
|
|
// cons up the points-to set for invariant contents
|
2007-01-08 21:29:40 +00:00
|
|
|
InstanceKey[] ik = ((SSAPropagationCallGraphBuilder) builder).getInvariantContents(ir.getSymbolTable(), du, node, lpk
|
|
|
|
.getValueNumber(), H, true);
|
2006-11-22 17:38:46 +00:00
|
|
|
return toOrdinalSet(ik);
|
|
|
|
} else {
|
|
|
|
SSAInstruction def = du.getDef(lpk.getValueNumber());
|
|
|
|
if (def != null) {
|
2007-01-08 21:29:40 +00:00
|
|
|
ImplicitPointsToSetVisitor v = makeImplicitPointsToVisitor(lpk);
|
|
|
|
def.visit(v);
|
|
|
|
if (v.pointsToSet != null) {
|
|
|
|
return v.pointsToSet;
|
|
|
|
} else {
|
|
|
|
Assertions.UNREACHABLE("saw " + key + ": time to implement for " + def.getClass());
|
2006-11-22 17:38:46 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Assertions.UNREACHABLE("unexpected null def for " + key);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Assertions.UNREACHABLE("unexpected implicit key " + key + " that's not a local pointer key");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2007-01-08 21:29:40 +00:00
|
|
|
|
2006-11-22 17:38:46 +00:00
|
|
|
private OrdinalSet<InstanceKey> computeImplicitPointsToSetAtPi(CGNode node, SSAPiInstruction instruction) {
|
2007-10-29 13:18:26 +00:00
|
|
|
MutableSparseIntSet S = MutableSparseIntSet.makeEmpty();
|
2006-11-22 17:38:46 +00:00
|
|
|
for (int i = 0; i < instruction.getNumberOfUses(); i++) {
|
|
|
|
int vn = instruction.getUse(i);
|
|
|
|
if (vn != -1) {
|
|
|
|
PointerKey lpk = pointerKeys.getPointerKeyForLocal(node, vn);
|
|
|
|
OrdinalSet pointees = getPointsToSet(lpk);
|
|
|
|
IntSet set = pointees.getBackingSet();
|
|
|
|
if (set != null) {
|
|
|
|
S.addAll(set);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new OrdinalSet<InstanceKey>(S, instanceKeys);
|
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSet<InstanceKey> computeImplicitPointsToSetAtPhi(CGNode node, SSAPhiInstruction instruction) {
|
2007-10-29 13:18:26 +00:00
|
|
|
MutableSparseIntSet S = MutableSparseIntSet.makeEmpty();
|
2006-11-22 17:38:46 +00:00
|
|
|
for (int i = 0; i < instruction.getNumberOfUses(); i++) {
|
|
|
|
int vn = instruction.getUse(i);
|
|
|
|
if (vn != -1) {
|
|
|
|
PointerKey lpk = pointerKeys.getPointerKeyForLocal(node, vn);
|
|
|
|
OrdinalSet pointees = getPointsToSet(lpk);
|
|
|
|
IntSet set = pointees.getBackingSet();
|
|
|
|
if (set != null) {
|
|
|
|
S.addAll(set);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new OrdinalSet<InstanceKey>(S, instanceKeys);
|
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSet<InstanceKey> computeImplicitPointsToSetAtALoad(CGNode node, SSAArrayLoadInstruction instruction) {
|
|
|
|
PointerKey arrayRef = pointerKeys.getPointerKeyForLocal(node, instruction.getArrayRef());
|
2007-10-29 13:18:26 +00:00
|
|
|
MutableSparseIntSet S = MutableSparseIntSet.makeEmpty();
|
2006-11-22 17:38:46 +00:00
|
|
|
OrdinalSet refs = getPointsToSet(arrayRef);
|
|
|
|
for (Iterator it = refs.iterator(); it.hasNext();) {
|
|
|
|
InstanceKey ik = (InstanceKey) it.next();
|
|
|
|
PointerKey key = pointerKeys.getPointerKeyForArrayContents(ik);
|
|
|
|
OrdinalSet pointees = getPointsToSet(key);
|
|
|
|
IntSet set = pointees.getBackingSet();
|
|
|
|
if (set != null) {
|
|
|
|
S.addAll(set);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new OrdinalSet<InstanceKey>(S, instanceKeys);
|
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSet<InstanceKey> computeImplicitPointsToSetAtGet(CGNode node, SSAGetInstruction instruction) {
|
2007-01-08 21:29:40 +00:00
|
|
|
return computeImplicitPointsToSetAtGet(node, instruction.getDeclaredField(), instruction.getRef(), instruction.isStatic());
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
2007-06-01 03:26:18 +00:00
|
|
|
public OrdinalSet<InstanceKey> computeImplicitPointsToSetAtGet(CGNode node, FieldReference field, int refVn, boolean isStatic) {
|
2006-11-22 17:38:46 +00:00
|
|
|
IField f = getCallGraph().getClassHierarchy().resolveField(field);
|
|
|
|
if (f == null) {
|
|
|
|
return OrdinalSet.empty();
|
|
|
|
}
|
|
|
|
if (isStatic) {
|
|
|
|
PointerKey fKey = pointerKeys.getPointerKeyForStaticField(f);
|
|
|
|
return getPointsToSet(fKey);
|
|
|
|
} else {
|
|
|
|
PointerKey ref = pointerKeys.getPointerKeyForLocal(node, refVn);
|
2007-10-29 13:18:26 +00:00
|
|
|
MutableSparseIntSet S = MutableSparseIntSet.makeEmpty();
|
2006-11-22 17:38:46 +00:00
|
|
|
OrdinalSet refs = getPointsToSet(ref);
|
|
|
|
for (Iterator it = refs.iterator(); it.hasNext();) {
|
|
|
|
InstanceKey ik = (InstanceKey) it.next();
|
|
|
|
PointerKey fkey = pointerKeys.getPointerKeyForInstanceField(ik, f);
|
2010-11-02 19:11:58 +00:00
|
|
|
if (fkey != null) {
|
|
|
|
OrdinalSet pointees = getPointsToSet(fkey);
|
|
|
|
IntSet set = pointees.getBackingSet();
|
|
|
|
if (set != null) {
|
|
|
|
S.addAll(set);
|
|
|
|
}
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return new OrdinalSet<InstanceKey>(S, instanceKeys);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSet<InstanceKey> computeImplicitPointsToSetAtCatch(CGNode node, SSAGetCaughtExceptionInstruction instruction) {
|
2007-07-06 22:08:13 +00:00
|
|
|
IR ir = node.getIR();
|
2006-11-22 17:38:46 +00:00
|
|
|
List<ProgramCounter> peis = SSAPropagationCallGraphBuilder.getIncomingPEIs(ir, ir.getBasicBlockForCatch(instruction));
|
2008-06-13 15:27:55 +00:00
|
|
|
Set<IClass> caughtTypes = SSAPropagationCallGraphBuilder.getCaughtExceptionTypes(instruction, ir);
|
2007-10-29 13:18:26 +00:00
|
|
|
MutableSparseIntSet S = MutableSparseIntSet.makeEmpty();
|
2006-11-22 17:38:46 +00:00
|
|
|
// add the instances from each incoming pei ...
|
|
|
|
for (Iterator<ProgramCounter> it = peis.iterator(); it.hasNext();) {
|
|
|
|
ProgramCounter peiLoc = it.next();
|
|
|
|
SSAInstruction pei = ir.getPEI(peiLoc);
|
|
|
|
PointerKey e = null;
|
|
|
|
// first deal with exception variables from calls and throws.
|
|
|
|
if (pei instanceof SSAAbstractInvokeInstruction) {
|
|
|
|
SSAAbstractInvokeInstruction s = (SSAAbstractInvokeInstruction) pei;
|
|
|
|
e = pointerKeys.getPointerKeyForLocal(node, s.getException());
|
|
|
|
} else if (pei instanceof SSAThrowInstruction) {
|
|
|
|
SSAThrowInstruction s = (SSAThrowInstruction) pei;
|
|
|
|
e = pointerKeys.getPointerKeyForLocal(node, s.getException());
|
|
|
|
}
|
|
|
|
if (e != null) {
|
|
|
|
OrdinalSet ep = getPointsToSet(e);
|
|
|
|
for (Iterator it2 = ep.iterator(); it2.hasNext();) {
|
|
|
|
InstanceKey ik = (InstanceKey) it2.next();
|
2007-07-06 03:07:14 +00:00
|
|
|
if (PropagationCallGraphBuilder.catches(caughtTypes, ik.getConcreteType(), getCallGraph().getClassHierarchy())) {
|
2006-11-22 17:38:46 +00:00
|
|
|
S.add(instanceKeys.getMappedIndex(ik));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Account for those exceptions for which we do not actually have a
|
|
|
|
// points-to set for
|
|
|
|
// the pei, but just instance keys
|
|
|
|
Collection types = pei.getExceptionTypes();
|
|
|
|
if (types != null) {
|
|
|
|
for (Iterator it2 = types.iterator(); it2.hasNext();) {
|
|
|
|
TypeReference type = (TypeReference) it2.next();
|
|
|
|
if (type != null) {
|
|
|
|
InstanceKey ik = SSAPropagationCallGraphBuilder.getInstanceKeyForPEI(node, peiLoc, type, iKeyFactory);
|
|
|
|
ConcreteTypeKey ck = (ConcreteTypeKey) ik;
|
|
|
|
IClass klass = ck.getType();
|
2007-07-06 03:07:14 +00:00
|
|
|
if (PropagationCallGraphBuilder.catches(caughtTypes, klass, getCallGraph().getClassHierarchy())) {
|
2006-11-22 17:38:46 +00:00
|
|
|
S.add(instanceKeys.getMappedIndex(SSAPropagationCallGraphBuilder
|
|
|
|
.getInstanceKeyForPEI(node, peiLoc, type, iKeyFactory)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new OrdinalSet<InstanceKey>(S, instanceKeys);
|
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSet<InstanceKey> computeImplicitPointsToSetAtCheckCast(CGNode node, SSACheckCastInstruction instruction) {
|
|
|
|
PointerKey rhs = pointerKeys.getPointerKeyForLocal(node, instruction.getVal());
|
|
|
|
OrdinalSet<InstanceKey> rhsSet = getPointsToSet(rhs);
|
2007-10-29 13:18:26 +00:00
|
|
|
MutableSparseIntSet S = MutableSparseIntSet.makeEmpty();
|
2010-04-28 19:33:34 +00:00
|
|
|
for (TypeReference t : instruction.getDeclaredResultTypes()) {
|
|
|
|
IClass klass = getCallGraph().getClassHierarchy().lookupClass(t);
|
|
|
|
if (klass == null) {
|
|
|
|
// could not find the type. conservatively assume Object
|
|
|
|
return rhsSet;
|
2006-11-22 17:38:46 +00:00
|
|
|
} else {
|
2010-04-28 19:33:34 +00:00
|
|
|
if (klass.isInterface()) {
|
|
|
|
for (Iterator it = rhsSet.iterator(); it.hasNext();) {
|
|
|
|
InstanceKey ik = (InstanceKey) it.next();
|
|
|
|
if (getCallGraph().getClassHierarchy().implementsInterface(ik.getConcreteType(), klass)) {
|
|
|
|
S.add(getInstanceKeyMapping().getMappedIndex(ik));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (Iterator it = rhsSet.iterator(); it.hasNext();) {
|
|
|
|
InstanceKey ik = (InstanceKey) it.next();
|
|
|
|
if (getCallGraph().getClassHierarchy().isSubclassOf(ik.getConcreteType(), klass)) {
|
|
|
|
S.add(getInstanceKeyMapping().getMappedIndex(ik));
|
|
|
|
}
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new OrdinalSet<InstanceKey>(S, instanceKeys);
|
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSet<InstanceKey> computeImplicitPointsToSetAtCall(LocalPointerKey lpk, CGNode node, SSAInvokeInstruction call) {
|
|
|
|
int exc = call.getException();
|
|
|
|
if (lpk.getValueNumber() == exc) {
|
|
|
|
return computeImplicitExceptionsForCall(node, call);
|
|
|
|
} else {
|
|
|
|
Assertions.UNREACHABLE("time to implement me.");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private OrdinalSet<InstanceKey> toOrdinalSet(InstanceKey[] ik) {
|
2007-10-29 13:18:26 +00:00
|
|
|
MutableSparseIntSet s = MutableSparseIntSet.makeEmpty();
|
2006-11-22 17:38:46 +00:00
|
|
|
for (int i = 0; i < ik.length; i++) {
|
|
|
|
int index = instanceKeys.getMappedIndex(ik[i]);
|
|
|
|
if (index != -1) {
|
|
|
|
s.add(index);
|
|
|
|
} else {
|
2009-04-30 13:16:52 +00:00
|
|
|
assert index != -1 : "instance " + ik[i] + " not mapped!";
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return new OrdinalSet<InstanceKey>(s, instanceKeys);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2009-05-01 17:42:28 +00:00
|
|
|
* @return the points-to set for the exceptional return values from a particular call site
|
2006-11-22 17:38:46 +00:00
|
|
|
*/
|
|
|
|
private OrdinalSet<InstanceKey> computeImplicitExceptionsForCall(CGNode node, SSAInvokeInstruction call) {
|
2007-10-29 13:18:26 +00:00
|
|
|
MutableSparseIntSet S = MutableSparseIntSet.makeEmpty();
|
2007-07-11 16:24:58 +00:00
|
|
|
for (Iterator it = getCallGraph().getPossibleTargets(node, call.getCallSite()).iterator(); it.hasNext();) {
|
2006-11-22 17:38:46 +00:00
|
|
|
CGNode target = (CGNode) it.next();
|
|
|
|
PointerKey retVal = pointerKeys.getPointerKeyForExceptionalReturnValue(target);
|
|
|
|
IntSet set = getPointsToSet(retVal).getBackingSet();
|
|
|
|
if (set != null) {
|
|
|
|
S.addAll(set);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return new OrdinalSet<InstanceKey>(S, instanceKeys);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis#getHeapModel()
|
|
|
|
*/
|
|
|
|
public HeapModel getHeapModel() {
|
|
|
|
return H;
|
|
|
|
}
|
|
|
|
|
|
|
|
private class HModel implements HeapModel {
|
|
|
|
|
2007-07-07 01:57:47 +00:00
|
|
|
public Iterator<PointerKey> iteratePointerKeys() {
|
2006-11-22 17:38:46 +00:00
|
|
|
return pointsToMap.iterateKeys();
|
|
|
|
}
|
|
|
|
|
|
|
|
public InstanceKey getInstanceKeyForAllocation(CGNode node, NewSiteReference allocation) {
|
|
|
|
return iKeyFactory.getInstanceKeyForAllocation(node, allocation);
|
|
|
|
}
|
|
|
|
|
|
|
|
public InstanceKey getInstanceKeyForMultiNewArray(CGNode node, NewSiteReference allocation, int dim) {
|
|
|
|
return iKeyFactory.getInstanceKeyForMultiNewArray(node, allocation, dim);
|
|
|
|
}
|
|
|
|
|
2007-11-29 18:22:39 +00:00
|
|
|
public <T> InstanceKey getInstanceKeyForConstant(TypeReference type, T S) {
|
2007-06-01 18:50:24 +00:00
|
|
|
return iKeyFactory.getInstanceKeyForConstant(type, S);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public InstanceKey getInstanceKeyForPEI(CGNode node, ProgramCounter peiLoc, TypeReference type) {
|
2008-01-25 18:09:34 +00:00
|
|
|
return iKeyFactory.getInstanceKeyForPEI(node, peiLoc, type);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public InstanceKey getInstanceKeyForClassObject(TypeReference type) {
|
2008-01-25 18:09:34 +00:00
|
|
|
return iKeyFactory.getInstanceKeyForClassObject(type);
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-05-01 17:42:28 +00:00
|
|
|
* @see com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory#getPointerKeyForLocal(com.ibm.detox.ipa.callgraph.CGNode, int)
|
2006-11-22 17:38:46 +00:00
|
|
|
*/
|
|
|
|
public PointerKey getPointerKeyForLocal(CGNode node, int valueNumber) {
|
|
|
|
return pointerKeys.getPointerKeyForLocal(node, valueNumber);
|
|
|
|
}
|
|
|
|
|
2007-03-12 01:56:32 +00:00
|
|
|
public FilteredPointerKey getFilteredPointerKeyForLocal(CGNode node, int valueNumber, FilteredPointerKey.TypeFilter filter) {
|
2006-11-22 17:38:46 +00:00
|
|
|
return pointerKeys.getFilteredPointerKeyForLocal(node, valueNumber, filter);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory#getPointerKeyForReturnValue(com.ibm.detox.ipa.callgraph.CGNode)
|
|
|
|
*/
|
|
|
|
public PointerKey getPointerKeyForReturnValue(CGNode node) {
|
|
|
|
return pointerKeys.getPointerKeyForReturnValue(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-05-01 17:42:28 +00:00
|
|
|
* @see
|
|
|
|
* com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory#getPointerKeyForExceptionalReturnValue(com.ibm.detox.ipa.callgraph
|
|
|
|
* .CGNode)
|
2006-11-22 17:38:46 +00:00
|
|
|
*/
|
|
|
|
public PointerKey getPointerKeyForExceptionalReturnValue(CGNode node) {
|
|
|
|
return pointerKeys.getPointerKeyForExceptionalReturnValue(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-05-01 17:42:28 +00:00
|
|
|
* @see
|
|
|
|
* com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory#getPointerKeyForStaticField(com.ibm.wala.classLoader.FieldReference)
|
2006-11-22 17:38:46 +00:00
|
|
|
*/
|
|
|
|
public PointerKey getPointerKeyForStaticField(IField f) {
|
|
|
|
return pointerKeys.getPointerKeyForStaticField(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-05-01 17:42:28 +00:00
|
|
|
* @see
|
|
|
|
* com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory#getPointerKeyForInstance(com.ibm.wala.ipa.callgraph.propagation.
|
|
|
|
* InstanceKey, com.ibm.wala.classLoader.FieldReference)
|
2006-11-22 17:38:46 +00:00
|
|
|
*/
|
|
|
|
public PointerKey getPointerKeyForInstanceField(InstanceKey I, IField field) {
|
|
|
|
assert field != null;
|
|
|
|
return pointerKeys.getPointerKeyForInstanceField(I, field);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-05-01 17:42:28 +00:00
|
|
|
* @see
|
|
|
|
* com.ibm.wala.ipa.callgraph.propagation.PointerKeyFactory#getPointerKeyForArrayContents(com.ibm.wala.ipa.callgraph.propagation
|
|
|
|
* .InstanceKey)
|
2006-11-22 17:38:46 +00:00
|
|
|
*/
|
|
|
|
public PointerKey getPointerKeyForArrayContents(InstanceKey I) {
|
|
|
|
return pointerKeys.getPointerKeyForArrayContents(I);
|
|
|
|
}
|
|
|
|
|
2007-06-01 03:26:18 +00:00
|
|
|
public IClassHierarchy getClassHierarchy() {
|
2006-11-22 17:38:46 +00:00
|
|
|
return getCallGraph().getClassHierarchy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @see com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis#iteratePointerKeys()
|
|
|
|
*/
|
2011-07-22 15:53:33 +00:00
|
|
|
public Iterable<PointerKey> getPointerKeys() {
|
|
|
|
return Iterator2Iterable.make(pointsToMap.iterateKeys());
|
2006-11-22 17:38:46 +00:00
|
|
|
}
|
|
|
|
|
2007-06-01 03:26:18 +00:00
|
|
|
public IClassHierarchy getClassHierarchy() {
|
2006-11-22 17:38:46 +00:00
|
|
|
return builder.getClassHierarchy();
|
|
|
|
}
|
|
|
|
}
|