adapt to checkcast change
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3817 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
c3ea5a8a86
commit
00871016cb
|
@ -35,6 +35,7 @@ import com.ibm.wala.shrikeBT.IComparisonInstruction;
|
|||
import com.ibm.wala.shrikeBT.IConditionalBranchInstruction;
|
||||
import com.ibm.wala.shrikeBT.IConversionInstruction;
|
||||
import com.ibm.wala.shrikeBT.IGetInstruction;
|
||||
import com.ibm.wala.shrikeBT.IInstanceofInstruction;
|
||||
import com.ibm.wala.shrikeBT.IInstruction;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.shrikeBT.ILoadInstruction;
|
||||
|
@ -42,7 +43,6 @@ import com.ibm.wala.shrikeBT.IPutInstruction;
|
|||
import com.ibm.wala.shrikeBT.IShiftInstruction;
|
||||
import com.ibm.wala.shrikeBT.IStoreInstruction;
|
||||
import com.ibm.wala.shrikeBT.IUnaryOpInstruction;
|
||||
import com.ibm.wala.shrikeBT.InstanceofInstruction;
|
||||
import com.ibm.wala.shrikeBT.MonitorInstruction;
|
||||
import com.ibm.wala.shrikeBT.NewInstruction;
|
||||
import com.ibm.wala.shrikeBT.PopInstruction;
|
||||
|
@ -1023,10 +1023,10 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants {
|
|||
}
|
||||
|
||||
/**
|
||||
* @see com.ibm.wala.shrikeBT.Instruction.Visitor#visitInstanceof(InstanceofInstruction)
|
||||
* @see com.ibm.wala.shrikeBT.Instruction.Visitor#visitInstanceof(IInstanceofInstruction)
|
||||
*/
|
||||
@Override
|
||||
public void visitInstanceof(InstanceofInstruction instruction) {
|
||||
public void visitInstanceof(IInstanceofInstruction instruction) {
|
||||
workingState.pop();
|
||||
workingState.push(UNANALYZED);
|
||||
}
|
||||
|
|
|
@ -586,14 +586,20 @@ public class TypeInference extends SSAInference<TypeVariable> implements FixedPo
|
|||
|
||||
@Override
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
TypeReference type = instruction.getDeclaredResultType();
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass == null) {
|
||||
// a type that cannot be loaded.
|
||||
// be pessimistic
|
||||
result = new DeclaredTypeOperator(BOTTOM);
|
||||
} else {
|
||||
result = new DeclaredTypeOperator(new ConeType(klass));
|
||||
TypeAbstraction typeAbs = null;
|
||||
for (TypeReference type : instruction.getDeclaredResultTypes()) {
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass == null) {
|
||||
// a type that cannot be loaded.
|
||||
// be pessimistic
|
||||
typeAbs = BOTTOM;
|
||||
} else {
|
||||
if (typeAbs == null) {
|
||||
typeAbs = new ConeType(klass);
|
||||
} else {
|
||||
typeAbs = typeAbs.meet(new ConeType(klass));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -278,7 +278,9 @@ public class CodeScanner {
|
|||
if (statements[i] != null) {
|
||||
if (statements[i] instanceof SSACheckCastInstruction) {
|
||||
SSACheckCastInstruction c = (SSACheckCastInstruction) statements[i];
|
||||
result.add(c.getDeclaredResultType());
|
||||
for(TypeReference t : c.getDeclaredResultTypes()) {
|
||||
result.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.naming.OperationNotSupportedException;
|
||||
|
||||
import com.ibm.wala.analysis.typeInference.JavaPrimitiveType;
|
||||
import com.ibm.wala.analysis.typeInference.PrimitiveType;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
|
@ -62,6 +64,7 @@ import com.ibm.wala.types.FieldReference;
|
|||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.shrike.ShrikeUtil;
|
||||
import com.ibm.wala.util.shrike.Exceptions.MethodResolutionFailure;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
@ -128,14 +131,27 @@ public class JavaLanguage extends LanguageImpl implements BytecodeLanguage, Cons
|
|||
};
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type) {
|
||||
return new SSACheckCastInstruction(result, val, type) {
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types) {
|
||||
assert types.length == 1;
|
||||
return new SSACheckCastInstruction(result, val, types) {
|
||||
@Override
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return getClassCastException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue) {
|
||||
return CheckCastInstruction(result, val, new int[]{ typeValue });
|
||||
}
|
||||
|
||||
public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type) {
|
||||
return CheckCastInstruction(result, val, new TypeReference[]{ type });
|
||||
}
|
||||
|
||||
public SSAComparisonInstruction ComparisonInstruction(IComparisonInstruction.Operator operator, int result, int val1, int val2) {
|
||||
return new SSAComparisonInstruction(operator, result, val1, val2);
|
||||
|
|
|
@ -20,7 +20,6 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.shrikeBT.BytecodeConstants;
|
||||
import com.ibm.wala.shrikeBT.CheckCastInstruction;
|
||||
import com.ibm.wala.shrikeBT.Constants;
|
||||
import com.ibm.wala.shrikeBT.Decoder;
|
||||
import com.ibm.wala.shrikeBT.ExceptionHandler;
|
||||
|
@ -30,6 +29,7 @@ import com.ibm.wala.shrikeBT.IGetInstruction;
|
|||
import com.ibm.wala.shrikeBT.IInstruction;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
import com.ibm.wala.shrikeBT.IPutInstruction;
|
||||
import com.ibm.wala.shrikeBT.ITypeTestInstruction;
|
||||
import com.ibm.wala.shrikeBT.MonitorInstruction;
|
||||
import com.ibm.wala.shrikeBT.NewInstruction;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
|
@ -647,10 +647,11 @@ public abstract class ShrikeBTMethod implements IMethod, BytecodeConstants {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void visitCheckCast(CheckCastInstruction instruction) {
|
||||
castTypes.add(ShrikeUtil.makeTypeReference(getDeclaringClass().getClassLoader().getReference(), instruction.getType()));
|
||||
public void visitCheckCast(ITypeTestInstruction instruction) {
|
||||
for(String t : instruction.getTypes()) {
|
||||
castTypes.add(ShrikeUtil.makeTypeReference(getDeclaringClass().getClassLoader().getReference(), t));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -103,6 +103,7 @@ import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
|||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.ReturnValueKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey.MultipleClassesFilter;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey.SingleClassFilter;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey.SingleInstanceFilter;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey.TypeFilter;
|
||||
|
@ -903,6 +904,21 @@ public class DemandRefinementPointsTo extends AbstractDemandPointsTo {
|
|||
|
||||
});
|
||||
vals = tmp;
|
||||
} else if (typeFilter instanceof MultipleClassesFilter) {
|
||||
final MutableIntSet tmp = intSetFactory.make();
|
||||
vals.foreach(new IntSetAction() {
|
||||
|
||||
public void act(int x) {
|
||||
InstanceKeyAndState ikAndState = ikAndStates.getMappedObject(x);
|
||||
for (IClass t : ((MultipleClassesFilter)typeFilter).getConcreteTypes()) {
|
||||
if (cha.isAssignableFrom(t, ikAndState.getInstanceKey().getConcreteType())) {
|
||||
tmp.add(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
vals = tmp;
|
||||
} else if (typeFilter instanceof SingleInstanceFilter) {
|
||||
final InstanceKey theOnlyInstanceKey = ((SingleInstanceFilter) typeFilter).getInstance();
|
||||
final MutableIntSet tmp = intSetFactory.make();
|
||||
|
|
|
@ -213,34 +213,23 @@ public class DemandPointerFlowGraph extends AbstractDemandFlowGraph implements I
|
|||
*/
|
||||
@Override
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
// Assertions.UNREACHABLE();
|
||||
|
||||
IClass cls = cha.lookupClass(instruction.getDeclaredResultType());
|
||||
PointerKey result = null;
|
||||
if (cls == null) {
|
||||
// warnings.add(
|
||||
// CheckcastFailure.create(instruction.getDeclaredResultType()));
|
||||
// we failed to find the type.
|
||||
// conservatively it would make sense to ignore the filter and
|
||||
// be
|
||||
// conservative, assuming
|
||||
// java.lang.Object.
|
||||
// however, this breaks the invariants downstream that assume
|
||||
// every
|
||||
// variable is
|
||||
// strongly typed ... we can't have bad types flowing around.
|
||||
// since things are broken anyway, just give up.
|
||||
// result = getPointerKeyForLocal(node,
|
||||
// instruction.getResult());
|
||||
return;
|
||||
} else {
|
||||
FilteredPointerKey.SingleClassFilter singleClassFilter = new FilteredPointerKey.SingleClassFilter(cls);
|
||||
result = heapModel.getPointerKeyForLocal(node, instruction.getResult());
|
||||
PointerKey value = heapModel.getPointerKeyForLocal(node, instruction.getVal());
|
||||
g.addNode(result);
|
||||
g.addNode(value);
|
||||
g.addEdge(result, value, AssignLabel.make(singleClassFilter));
|
||||
Set<IClass> types = HashSetFactory.make();
|
||||
|
||||
for(TypeReference t : instruction.getDeclaredResultTypes()) {
|
||||
IClass cls = cha.lookupClass(t);
|
||||
if (cls == null) {
|
||||
return;
|
||||
} else {
|
||||
types.add(cls);
|
||||
}
|
||||
}
|
||||
|
||||
FilteredPointerKey.MultipleClassesFilter filter = new FilteredPointerKey.MultipleClassesFilter(types.toArray(new IClass[ types.size() ]));
|
||||
PointerKey result = heapModel.getPointerKeyForLocal(node, instruction.getResult());
|
||||
PointerKey value = heapModel.getPointerKeyForLocal(node, instruction.getVal());
|
||||
g.addNode(result);
|
||||
g.addNode(value);
|
||||
g.addEdge(result, value, AssignLabel.make(filter));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -79,6 +79,8 @@ import com.ibm.wala.ssa.SSAUnaryOpInstruction;
|
|||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.SSAInstruction.Visitor;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.collections.MapUtil;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
|
@ -186,32 +188,24 @@ public class DemandValueFlowGraph extends AbstractDemandFlowGraph {
|
|||
*/
|
||||
@Override
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
// Assertions.UNREACHABLE();
|
||||
|
||||
IClass cls = cha.lookupClass(instruction.getDeclaredResultType());
|
||||
PointerKey result = null;
|
||||
if (cls == null) {
|
||||
// warnings.add(
|
||||
// CheckcastFailure.create(instruction.getDeclaredResultType()));
|
||||
// we failed to find the type.
|
||||
// conservatively it would make sense to ignore the filter and
|
||||
// be
|
||||
// conservative, assuming
|
||||
// java.lang.Object.
|
||||
// however, this breaks the invariants downstream that assume
|
||||
// every
|
||||
// variable is
|
||||
// strongly typed ... we can't have bad types flowing around.
|
||||
// since things are broken anyway, just give up.
|
||||
// result = getPointerKeyForLocal(node,
|
||||
// instruction.getResult());
|
||||
return;
|
||||
} else {
|
||||
result = heapModel.getFilteredPointerKeyForLocal(node, instruction.getResult(), new FilteredPointerKey.SingleClassFilter(
|
||||
cls));
|
||||
Set<IClass> types = HashSetFactory.make();
|
||||
|
||||
for(TypeReference t : instruction.getDeclaredResultTypes()) {
|
||||
IClass cls = cha.lookupClass(t);
|
||||
if (cls == null) {
|
||||
return;
|
||||
} else {
|
||||
types.add(cls);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PointerKey result = heapModel.getFilteredPointerKeyForLocal(node,
|
||||
instruction.getResult(),
|
||||
new FilteredPointerKey.MultipleClassesFilter(types.toArray(new IClass[ types.size() ])) );
|
||||
|
||||
PointerKey value = heapModel.getPointerKeyForLocal(node, instruction.getVal());
|
||||
// TODO actually use the cast type
|
||||
|
||||
addNode(result);
|
||||
addNode(value);
|
||||
addEdge(result, value, AssignLabel.noFilter());
|
||||
|
|
|
@ -732,27 +732,22 @@ public class SimpleDemandPointerFlowGraph extends SlowSparseNumberedGraph<Object
|
|||
*/
|
||||
@Override
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
// Assertions.UNREACHABLE();
|
||||
|
||||
IClass cls = cha.lookupClass(instruction.getDeclaredResultType());
|
||||
PointerKey result = null;
|
||||
if (cls == null) {
|
||||
// warnings.add(
|
||||
// CheckcastFailure.create(instruction.getDeclaredResultType()));
|
||||
// we failed to find the type.
|
||||
// conservatively it would make sense to ignore the filter and be
|
||||
// conservative, assuming
|
||||
// java.lang.Object.
|
||||
// however, this breaks the invariants downstream that assume every
|
||||
// variable is
|
||||
// strongly typed ... we can't have bad types flowing around.
|
||||
// since things are broken anyway, just give up.
|
||||
// result = getPointerKeyForLocal(node, instruction.getResult());
|
||||
return;
|
||||
} else {
|
||||
result = heapModel.getFilteredPointerKeyForLocal(node, instruction.getResult(), new FilteredPointerKey.SingleClassFilter(
|
||||
cls));
|
||||
Set<IClass> types = HashSetFactory.make();
|
||||
|
||||
for(TypeReference t : instruction.getDeclaredResultTypes()) {
|
||||
IClass cls = cha.lookupClass(t);
|
||||
if (cls == null) {
|
||||
return;
|
||||
} else {
|
||||
types.add(cls);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PointerKey result = heapModel.getFilteredPointerKeyForLocal(node,
|
||||
instruction.getResult(),
|
||||
new FilteredPointerKey.MultipleClassesFilter(types.toArray(new IClass[ types.size() ])) );
|
||||
|
||||
PointerKey value = heapModel.getPointerKeyForLocal(node, instruction.getVal());
|
||||
// TODO actually use the cast type
|
||||
addNode(result);
|
||||
|
|
|
@ -330,10 +330,10 @@ public abstract class AbstractRootMethod extends SyntheticMethod {
|
|||
return result;
|
||||
}
|
||||
|
||||
public int addCheckcast(TypeReference type, int rv) {
|
||||
public int addCheckcast(TypeReference[] types, int rv) {
|
||||
int lv = nextLocal++;
|
||||
|
||||
statements.add(insts.CheckCastInstruction(lv, rv, type));
|
||||
statements.add(insts.CheckCastInstruction(lv, rv, types));
|
||||
return lv;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,13 @@ import java.util.Iterator;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.analysis.reflection.JavaTypeContext;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.ReceiverInstanceContext;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeBT.IInvokeInstruction;
|
||||
|
@ -350,5 +352,37 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
|
|||
protected NodeManager<CGNode> getNodeManager() {
|
||||
return nodeManager;
|
||||
}
|
||||
|
||||
public void summarizeByPackage() {
|
||||
Map<String, Integer> packages = HashMapFactory.make();
|
||||
for(CGNode n : this) {
|
||||
String nm = n.getMethod().getDeclaringClass().getName().toString() + "/" + n.getMethod().getName() + "/" + n.getContext().getClass().toString();
|
||||
|
||||
if (n.getContext() instanceof ReceiverInstanceContext) {
|
||||
nm = nm + "/" + ((ReceiverInstanceContext)n.getContext()).getReceiver().getConcreteType().getName();
|
||||
} else if (n.getContext() instanceof JavaTypeContext) {
|
||||
nm = nm + "/" + ((JavaTypeContext)n.getContext()).getType().getTypeReference().getName();
|
||||
}
|
||||
|
||||
do {
|
||||
if (packages.containsKey(nm)) {
|
||||
packages.put(nm, 1 + packages.get(nm));
|
||||
} else {
|
||||
packages.put(nm, 1);
|
||||
}
|
||||
|
||||
if (nm.indexOf('/') < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
nm = nm.substring(0, nm.lastIndexOf('/'));
|
||||
} while (true);
|
||||
}
|
||||
|
||||
System.err.println("dump of CG");
|
||||
for(Map.Entry<String, Integer> e : packages.entrySet()) {
|
||||
System.err.println(e.getValue().intValue() + " " + e.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -72,6 +72,75 @@ public interface FilteredPointerKey extends PointerKey {
|
|||
}
|
||||
}
|
||||
|
||||
public class MultipleClassesFilter implements TypeFilter {
|
||||
private final IClass[] concreteType;
|
||||
|
||||
public MultipleClassesFilter(IClass[] concreteType) {
|
||||
this.concreteType = concreteType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SingleClassFilter: " + concreteType;
|
||||
}
|
||||
|
||||
public IClass[] getConcreteTypes() {
|
||||
return concreteType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return concreteType[0].hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (! (o instanceof MultipleClassesFilter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MultipleClassesFilter f = (MultipleClassesFilter)o;
|
||||
|
||||
if (concreteType.length != f.concreteType.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(int i = 0; i < concreteType.length; i++) {
|
||||
if (! (concreteType[i].equals(f.concreteType[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private IntSet bits(PropagationSystem system) {
|
||||
IntSet f = null;
|
||||
for(IClass cls : concreteType) {
|
||||
if (f == null) {
|
||||
f = system.getInstanceKeysForClass(cls);
|
||||
} else {
|
||||
f = f.union(system.getInstanceKeysForClass(cls));
|
||||
}
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
public boolean addFiltered(PropagationSystem system, PointsToSetVariable L, PointsToSetVariable R) {
|
||||
IntSet f = bits(system);
|
||||
return (f == null) ? false : L.addAllInIntersection(R, f);
|
||||
}
|
||||
|
||||
public boolean addInverseFiltered(PropagationSystem system, PointsToSetVariable L, PointsToSetVariable R) {
|
||||
IntSet f = bits(system);
|
||||
|
||||
// SJF: this is horribly inefficient. we really don't want to do
|
||||
// diffs in here. TODO: fix it. probably keep not(f) cached and
|
||||
// use addAllInIntersection
|
||||
return (f == null) ? L.addAll(R) : L.addAll(IntSetUtil.diff(R.getValue(), f));
|
||||
}
|
||||
}
|
||||
|
||||
public class SingleInstanceFilter implements TypeFilter {
|
||||
private final InstanceKey concreteType;
|
||||
|
||||
|
|
|
@ -378,23 +378,25 @@ public class PointerAnalysisImpl extends AbstractPointerAnalysis {
|
|||
PointerKey rhs = pointerKeys.getPointerKeyForLocal(node, instruction.getVal());
|
||||
OrdinalSet<InstanceKey> rhsSet = getPointsToSet(rhs);
|
||||
MutableSparseIntSet S = MutableSparseIntSet.makeEmpty();
|
||||
IClass klass = getCallGraph().getClassHierarchy().lookupClass(instruction.getDeclaredResultType());
|
||||
if (klass == null) {
|
||||
// could not find the type. conservatively assume Object
|
||||
return rhsSet;
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
}
|
||||
for (TypeReference t : instruction.getDeclaredResultTypes()) {
|
||||
IClass klass = getCallGraph().getClassHierarchy().lookupClass(t);
|
||||
if (klass == null) {
|
||||
// could not find the type. conservatively assume Object
|
||||
return rhsSet;
|
||||
} 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));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,11 +113,13 @@ public class ReflectionHandler {
|
|||
|
||||
for (Statement st : casts) {
|
||||
SSACheckCastInstruction c = (SSACheckCastInstruction) ((NormalStatement) st).getInstruction();
|
||||
TypeReference type = c.getDeclaredResultType();
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass != null) {
|
||||
if (contextInterpreter.recordFactoryType(returnStatement.getNode(), klass)) {
|
||||
result.add(returnStatement.getNode());
|
||||
|
||||
for (TypeReference type : c.getDeclaredResultTypes()) {
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass != null) {
|
||||
if (contextInterpreter.recordFactoryType(returnStatement.getNode(), klass)) {
|
||||
result.add(returnStatement.getNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -739,23 +739,24 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
|
|||
*/
|
||||
@Override
|
||||
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
||||
IClass cls = getClassHierarchy().lookupClass(instruction.getDeclaredResultType());
|
||||
PointerKey result = null;
|
||||
if (cls == null) {
|
||||
Warnings.add(CheckcastFailure.create(instruction.getDeclaredResultType()));
|
||||
// we failed to find the type.
|
||||
// conservatively it would make sense to ignore the filter and be
|
||||
// conservative, assuming
|
||||
// java.lang.Object.
|
||||
// however, this breaks the invariants downstream that assume every
|
||||
// variable is
|
||||
// strongly typed ... we can't have bad types flowing around.
|
||||
// since things are broken anyway, just give up.
|
||||
// result = getPointerKeyForLocal(node, instruction.getResult());
|
||||
return;
|
||||
} else {
|
||||
result = getFilteredPointerKeyForLocal(instruction.getResult(), new FilteredPointerKey.SingleClassFilter(cls));
|
||||
|
||||
boolean isRoot = false;
|
||||
Set<IClass> types = HashSetFactory.make();
|
||||
|
||||
for(TypeReference t : instruction.getDeclaredResultTypes()) {
|
||||
IClass cls = getClassHierarchy().lookupClass(t);
|
||||
if (cls == null) {
|
||||
Warnings.add(CheckcastFailure.create(t));
|
||||
return;
|
||||
} else {
|
||||
if (isRootType(cls)) {
|
||||
isRoot = true;
|
||||
}
|
||||
types.add(cls);
|
||||
}
|
||||
}
|
||||
|
||||
PointerKey result = getFilteredPointerKeyForLocal(instruction.getResult(), new FilteredPointerKey.MultipleClassesFilter(types.toArray(new IClass[ types.size() ])));
|
||||
PointerKey value = getPointerKeyForLocal(instruction.getVal());
|
||||
|
||||
if (hasNoInterestingUses(instruction.getDef())) {
|
||||
|
@ -764,23 +765,27 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
|
|||
if (contentsAreInvariant(symbolTable, du, instruction.getVal())) {
|
||||
system.recordImplicitPointsToSet(value);
|
||||
InstanceKey[] ik = getInvariantContents(instruction.getVal());
|
||||
if (cls.isInterface()) {
|
||||
for (int i = 0; i < ik.length; i++) {
|
||||
system.findOrCreateIndexForInstanceKey(ik[i]);
|
||||
if (getClassHierarchy().implementsInterface(ik[i].getConcreteType(), cls)) {
|
||||
system.newConstraint(result, ik[i]);
|
||||
for(TypeReference t : instruction.getDeclaredResultTypes()) {
|
||||
IClass cls = getClassHierarchy().lookupClass(t);
|
||||
|
||||
if (cls.isInterface()) {
|
||||
for (int i = 0; i < ik.length; i++) {
|
||||
system.findOrCreateIndexForInstanceKey(ik[i]);
|
||||
if (getClassHierarchy().implementsInterface(ik[i].getConcreteType(), cls)) {
|
||||
system.newConstraint(result, ik[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < ik.length; i++) {
|
||||
system.findOrCreateIndexForInstanceKey(ik[i]);
|
||||
if (getClassHierarchy().isSubclassOf(ik[i].getConcreteType(), cls)) {
|
||||
system.newConstraint(result, ik[i]);
|
||||
} else {
|
||||
for (int i = 0; i < ik.length; i++) {
|
||||
system.findOrCreateIndexForInstanceKey(ik[i]);
|
||||
if (getClassHierarchy().isSubclassOf(ik[i].getConcreteType(), cls)) {
|
||||
system.newConstraint(result, ik[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (isRootType(cls)) {
|
||||
if (isRoot) {
|
||||
system.newConstraint(result, assignOperator, value);
|
||||
} else {
|
||||
system.newConstraint(result, getBuilder().filterOperator, value);
|
||||
|
|
|
@ -55,6 +55,8 @@ public class StandardSolver extends AbstractPointsToSolver {
|
|||
}
|
||||
getBuilder().addConstraintsFromNewNodes();
|
||||
|
||||
// getBuilder().callGraph.summarizeByPackage();
|
||||
|
||||
if (DEBUG) {
|
||||
System.err.println("handling reflection");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue