Documentation and Refactoring.
This commit is contained in:
parent
467707701f
commit
c3b7f9ffb3
|
@ -10,42 +10,30 @@
|
|||
*******************************************************************************/
|
||||
package com.ibm.wala.analysis.exceptionanalysis;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.fixpoint.BitVectorVariable;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.collections.ObjectArrayMapping;
|
||||
import com.ibm.wala.util.intset.BitVector;
|
||||
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||
|
||||
public class ExceptionToBitvectorTransformer {
|
||||
|
||||
private Map<TypeReference, BitVector> includingExceptions;
|
||||
public class Exception2BitvectorTransformer {
|
||||
private OrdinalSetMapping<TypeReference> values;
|
||||
|
||||
public OrdinalSetMapping<TypeReference> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public ExceptionToBitvectorTransformer(Set<TypeReference> exceptions) {
|
||||
includingExceptions = new HashMap<TypeReference, BitVector>();
|
||||
public Exception2BitvectorTransformer(Set<TypeReference> exceptions) {
|
||||
createValues(exceptions);
|
||||
for (TypeReference exception : exceptions) {
|
||||
BitVector bv = new BitVector(values.getSize());
|
||||
bv.set(values.getMappedIndex(exception));
|
||||
includingExceptions.put(exception, bv);
|
||||
}
|
||||
}
|
||||
|
||||
public ExceptionToBitvectorTransformer(Set<TypeReference> exceptions, ClassHierarchy cha) {
|
||||
// TODO
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private void createValues(Set<TypeReference> exceptions) {
|
||||
TypeReference[] exceptionsArray = new TypeReference[exceptions.size()];
|
||||
exceptions.toArray(exceptionsArray);
|
||||
|
@ -55,12 +43,12 @@ public class ExceptionToBitvectorTransformer {
|
|||
public BitVector computeBitVector(Set<TypeReference> exceptions) {
|
||||
BitVector result = new BitVector(values.getSize());
|
||||
for (TypeReference exception : exceptions) {
|
||||
// if (!includingExceptions.containsKey(exception)) {
|
||||
// throw new IllegalArgumentException("Got exception I don't know about,"
|
||||
// + "make sure only to use exceptions given to the constructor ");
|
||||
// }
|
||||
if (includingExceptions.containsKey(exception)) {
|
||||
result.or(includingExceptions.get(exception));
|
||||
int pos = values.getMappedIndex(exception);
|
||||
if (pos != -1) {
|
||||
result.set(pos);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Got exception I don't know about,"
|
||||
+ "make sure only to use exceptions given to the constructor ");
|
||||
}
|
||||
}
|
||||
return result;
|
|
@ -24,13 +24,13 @@ import com.ibm.wala.ipa.cha.ClassHierarchy;
|
|||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
|
||||
import com.ibm.wala.util.graph.Graph;
|
||||
import com.ibm.wala.util.graph.impl.InvertedGraph;
|
||||
import com.ibm.wala.util.graph.impl.SelfLoopAddedGraph;
|
||||
|
||||
public class ExceptionAnalysis {
|
||||
private BitVectorSolver<CGNode> solver;
|
||||
private ExceptionToBitvectorTransformer transformer;
|
||||
private Exception2BitvectorTransformer transformer;
|
||||
|
||||
public ExceptionAnalysis(CallGraph callgraph, PointerAnalysis<InstanceKey> pointerAnalysis, ClassHierarchy cha) {
|
||||
this(callgraph, pointerAnalysis, cha, null);
|
||||
|
@ -38,16 +38,16 @@ public class ExceptionAnalysis {
|
|||
|
||||
public ExceptionAnalysis(CallGraph callgraph, PointerAnalysis<InstanceKey> pointerAnalysis, ClassHierarchy cha,
|
||||
InterproceduralExceptionFilter<SSAInstruction> filter) {
|
||||
IntraproceduralResult intraResult = new IntraproceduralResult(callgraph, pointerAnalysis, cha, filter);
|
||||
transformer = new ExceptionToBitvectorTransformer(intraResult.getExceptions());
|
||||
CGIntraproceduralExceptionAnalysis intraResult = new CGIntraproceduralExceptionAnalysis(callgraph, pointerAnalysis, cha, filter);
|
||||
transformer = new Exception2BitvectorTransformer(intraResult.getExceptions());
|
||||
ExceptionTransferFunctionProvider transferFunctionProvider = new ExceptionTransferFunctionProvider(intraResult, callgraph,
|
||||
transformer);
|
||||
|
||||
Graph<CGNode> graph = new SelfLoopAddedGraph<>(new InvertedGraph<CGNode>(callgraph));
|
||||
Graph<CGNode> graph = new InvertedGraph<CGNode>(callgraph);
|
||||
BitVectorFramework<CGNode, TypeReference> problem = new BitVectorFramework<>(graph, transferFunctionProvider,
|
||||
transformer.getValues());
|
||||
|
||||
solver = new ExceptionFlowSolver(problem, intraResult, transformer);
|
||||
solver = new InitializedBitVectorSolver(problem);
|
||||
solver.initForFirstSolve();
|
||||
}
|
||||
|
||||
|
@ -55,13 +55,17 @@ public class ExceptionAnalysis {
|
|||
try {
|
||||
solver.solve(null);
|
||||
} catch (CancelException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Internal Error: Got Cancel Exception, "
|
||||
+ "but didn't use Progressmonitor!", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void solve(IProgressMonitor monitor) throws CancelException {
|
||||
solver.solve(monitor);
|
||||
}
|
||||
|
||||
public Set<TypeReference> getCGNodeExceptions(CGNode node) {
|
||||
BitVectorVariable nodeResult = solver.getIn(node);
|
||||
BitVectorVariable nodeResult = solver.getOut(node);
|
||||
if (nodeResult != null) {
|
||||
return transformer.computeExceptions(nodeResult);
|
||||
} else {
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.exceptionanalysis;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
||||
import com.ibm.wala.dataflow.graph.IKilldallFramework;
|
||||
import com.ibm.wala.fixpoint.BitVectorVariable;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.intset.BitVector;
|
||||
|
||||
public class ExceptionFlowSolver extends BitVectorSolver<CGNode> {
|
||||
|
||||
private IntraproceduralResult intraResult;
|
||||
private ExceptionToBitvectorTransformer transformer;
|
||||
|
||||
public ExceptionFlowSolver(IKilldallFramework<CGNode, BitVectorVariable> problem, IntraproceduralResult intraResult,
|
||||
ExceptionToBitvectorTransformer transformer) {
|
||||
super(problem);
|
||||
this.intraResult = intraResult;
|
||||
this.transformer = transformer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BitVectorVariable makeNodeVariable(CGNode n, boolean IN) {
|
||||
BitVectorVariable result = new BitVectorVariable();
|
||||
Set<TypeReference> exceptions = intraResult.getIntraproceduralExceptions(n);
|
||||
BitVector bitVector = transformer.computeBitVector(exceptions);
|
||||
result.addAll(bitVector);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BitVectorVariable makeEdgeVariable(CGNode src, CGNode dst) {
|
||||
|
||||
if (src.equals(dst)) {
|
||||
/*
|
||||
* Set edge variables of self loops to the value of the node, otherwise
|
||||
* leafs will lose their information.
|
||||
*/
|
||||
return makeNodeVariable(src, true);
|
||||
} else {
|
||||
/*
|
||||
* If we do not initialize BitVectorVariable, with a BitVector, it
|
||||
* contains null, which may crash in combination with {@link
|
||||
* BitVectorMinusVector} used in {@link ExceptionTransferFunction}
|
||||
*/
|
||||
BitVectorVariable result = new BitVectorVariable();
|
||||
result.addAll(new BitVector());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,26 +11,29 @@
|
|||
package com.ibm.wala.analysis.exceptionanalysis;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.dataflow.graph.AbstractMeetOperator;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorIdentity;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorMinusVector;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorUnion;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorUnionVector;
|
||||
import com.ibm.wala.dataflow.graph.ITransferFunctionProvider;
|
||||
import com.ibm.wala.fixpoint.BitVectorVariable;
|
||||
import com.ibm.wala.fixpoint.UnaryOperator;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.intset.BitVector;
|
||||
|
||||
public class ExceptionTransferFunctionProvider implements ITransferFunctionProvider<CGNode, BitVectorVariable> {
|
||||
private ExceptionToBitvectorTransformer transformer;
|
||||
private Exception2BitvectorTransformer transformer;
|
||||
private CallGraph cg;
|
||||
private IntraproceduralResult intraResult;
|
||||
private CGIntraproceduralExceptionAnalysis intraResult;
|
||||
|
||||
public ExceptionTransferFunctionProvider(IntraproceduralResult intraResult, CallGraph cg,
|
||||
ExceptionToBitvectorTransformer transformer) {
|
||||
public ExceptionTransferFunctionProvider(CGIntraproceduralExceptionAnalysis intraResult, CallGraph cg,
|
||||
Exception2BitvectorTransformer transformer) {
|
||||
this.cg = cg;
|
||||
this.transformer = transformer;
|
||||
this.intraResult = intraResult;
|
||||
|
@ -38,7 +41,7 @@ public class ExceptionTransferFunctionProvider implements ITransferFunctionProvi
|
|||
|
||||
@Override
|
||||
public boolean hasNodeTransferFunctions() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,52 +56,40 @@ public class ExceptionTransferFunctionProvider implements ITransferFunctionProvi
|
|||
|
||||
@Override
|
||||
public UnaryOperator<BitVectorVariable> getNodeTransferFunction(CGNode node) {
|
||||
throw new UnsupportedOperationException();
|
||||
Set<TypeReference> exceptions = intraResult.getAnalysis(node).getExceptions();
|
||||
BitVector bitVector = transformer.computeBitVector(exceptions);
|
||||
return new BitVectorUnionVector(bitVector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnaryOperator<BitVectorVariable> getEdgeTransferFunction(CGNode src, CGNode dst) {
|
||||
// if (src.equals(dst)) {
|
||||
// /*
|
||||
// * To make use of start values for all nodes, self-loops were introduced
|
||||
// * into the graph (Otherwise these values would get eliminated during
|
||||
// * short circuit optimization.)
|
||||
// *
|
||||
// * If the method does not call itself, we would have no analysis result
|
||||
// * for the self-loop edge. We can just return the identity function for
|
||||
// * this cases.
|
||||
// *
|
||||
// * If the method does call itself, we could produce a more precise
|
||||
// * transfer function as the method is catching its own exceptions, maybe.
|
||||
// * However, the less precise transfer function we actually use, does not
|
||||
// * result in a less precise result: There is an execution, that produces
|
||||
// * the exceptions so they need to be included.
|
||||
// */
|
||||
// return BitVectorIdentity.instance();
|
||||
// } else
|
||||
{
|
||||
CGNode tmp = src;
|
||||
src = dst;
|
||||
dst = tmp;
|
||||
public UnaryOperator<BitVectorVariable> getEdgeTransferFunction(CGNode dst, CGNode src) {
|
||||
/*
|
||||
* Note, that dst and src are swapped. For the data-flow-analysis we use
|
||||
* called -> caller, but for the call graph we need caller -> called.
|
||||
*/
|
||||
|
||||
Iterator<CallSiteReference> callsites = cg.getPossibleSites(src, dst);
|
||||
BitVector filtered = new BitVector(transformer.getValues().getSize());
|
||||
|
||||
|
||||
if (callsites.hasNext()) {
|
||||
|
||||
CallSiteReference callsite = callsites.next();
|
||||
|
||||
Iterator<CallSiteReference> callsites = cg.getPossibleSites(src, dst);
|
||||
BitVector filtered = new BitVector(transformer.getValues().getSize());
|
||||
|
||||
if (callsites.hasNext()) {
|
||||
CallSiteReference callsite = callsites.next();
|
||||
filtered = transformer.computeBitVector(intraResult.getCaughtExceptions(src, callsite));
|
||||
while (callsites.hasNext()) {
|
||||
callsite = callsites.next();
|
||||
BitVector bv = transformer.computeBitVector(intraResult.getCaughtExceptions(src, callsite));
|
||||
filtered.and(bv);
|
||||
}
|
||||
|
||||
return new BitVectorMinusVector(filtered);
|
||||
} else {
|
||||
return BitVectorIdentity.instance();
|
||||
Set<TypeReference> caught = new LinkedHashSet<>();
|
||||
caught.addAll(intraResult.getAnalysis(src).getCaughtExceptions(callsite));
|
||||
while (callsites.hasNext()) {
|
||||
callsite = callsites.next();
|
||||
caught.retainAll(intraResult.getAnalysis(src).getCaughtExceptions(callsite));
|
||||
}
|
||||
|
||||
filtered = transformer.computeBitVector(caught);
|
||||
return new BitVectorMinusVector(filtered);
|
||||
} else {
|
||||
// This case should not happen, as we should only get src, dst pairs,
|
||||
// which represent an edge in the call graph. For each edge in the call
|
||||
// graph should be at least one call site.
|
||||
throw new RuntimeException("Internal Error: Got call graph edge without call site.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.exceptionanalysis;
|
||||
|
||||
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
||||
import com.ibm.wala.dataflow.graph.IKilldallFramework;
|
||||
import com.ibm.wala.fixpoint.BitVectorVariable;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.util.intset.BitVector;
|
||||
|
||||
public class InitializedBitVectorSolver extends BitVectorSolver<CGNode> {
|
||||
public InitializedBitVectorSolver(IKilldallFramework<CGNode, BitVectorVariable> problem) {
|
||||
super(problem);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BitVectorVariable makeNodeVariable(CGNode n, boolean IN) {
|
||||
return newBV();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BitVectorVariable makeEdgeVariable(CGNode src, CGNode dst) {
|
||||
return newBV();
|
||||
}
|
||||
|
||||
private BitVectorVariable newBV(){
|
||||
/*
|
||||
* If we do not initialize BitVectorVariable, with a BitVector, it contains
|
||||
* null, which may crash in combination with {@link BitVectorMinusVector}
|
||||
* used in {@link ExceptionTransferFunction}
|
||||
*/
|
||||
BitVectorVariable result = new BitVectorVariable();
|
||||
result.addAll(new BitVector());
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,248 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.exceptionanalysis;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.FilteredException;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.interprocedural.InterproceduralExceptionFilter;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.ISSABasicBlock;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction.Visitor;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAThrowInstruction;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.intset.IntIterator;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
|
||||
public class IntraproceduralResult {
|
||||
private Set<TypeReference> exceptions;
|
||||
private Map<CGNode, Set<TypeReference>> intraproceduralExceptions;
|
||||
private CallGraph callGraph;
|
||||
private PointerAnalysis<InstanceKey> pointerAnalysis;
|
||||
private ClassHierarchy classHierachy;
|
||||
private InterproceduralExceptionFilter<SSAInstruction> filter;
|
||||
|
||||
public IntraproceduralResult(CallGraph cg, PointerAnalysis<InstanceKey> pointerAnalysis, ClassHierarchy cha,
|
||||
InterproceduralExceptionFilter<SSAInstruction> filter) {
|
||||
this.callGraph = cg;
|
||||
this.pointerAnalysis = pointerAnalysis;
|
||||
this.classHierachy = cha;
|
||||
this.filter = filter;
|
||||
intraproceduralExceptions = new HashMap<>();
|
||||
exceptions = new HashSet<>();
|
||||
compute();
|
||||
}
|
||||
|
||||
private void compute() {
|
||||
for (final CGNode node : callGraph) {
|
||||
intraproceduralExceptions.put(node, new HashSet<TypeReference>());
|
||||
|
||||
IR ir = node.getIR();
|
||||
|
||||
if (ir != null) {
|
||||
for (ISSABasicBlock block : ir.getControlFlowGraph()) {
|
||||
SSAInstruction throwingInstruction = getThrowingInstruction(block);
|
||||
if (throwingInstruction != null) {
|
||||
Set<TypeReference> thrownExceptions = collectThrownExceptions(node, throwingInstruction);
|
||||
Set<TypeReference> caughtExceptions = collectCaughtExceptions(node, block);
|
||||
Set<TypeReference> filteredExceptions = collectFilteredExceptions(node, throwingInstruction);
|
||||
|
||||
thrownExceptions.removeAll(filteredExceptions);
|
||||
thrownExceptions.removeAll(caughtExceptions);
|
||||
intraproceduralExceptions.get(node).addAll(thrownExceptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Set<TypeReference> exceptions : intraproceduralExceptions.values()) {
|
||||
this.exceptions.addAll(exceptions);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<TypeReference> collectFilteredExceptions(CGNode node, SSAInstruction throwingInstruction) {
|
||||
if (filter != null) {
|
||||
Set<TypeReference> filtered = new LinkedHashSet<>();
|
||||
Collection<FilteredException> filters = filter.getFilter(node).filteredExceptions(throwingInstruction);
|
||||
for (FilteredException filter : filters) {
|
||||
if (filter.isSubclassFiltered()) {
|
||||
for (IClass iclass : this.classHierachy.computeSubClasses(filter.getException())) {
|
||||
filtered.add(iclass.getReference());
|
||||
}
|
||||
} else {
|
||||
filtered.add(filter.getException());
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of exceptions, which might be thrown from this instruction
|
||||
* within this method.
|
||||
*
|
||||
* This does include exceptions dispatched by throw instructions, but not
|
||||
* exceptions from method calls.
|
||||
*
|
||||
* @param node
|
||||
* @param throwingInstruction
|
||||
* @return a set of exceptions, which might be thrown from this instruction
|
||||
* within this method
|
||||
*/
|
||||
private Set<TypeReference> collectThrownExceptions(final CGNode node, SSAInstruction throwingInstruction) {
|
||||
final LinkedHashSet<TypeReference> result = new LinkedHashSet<>();
|
||||
result.addAll(throwingInstruction.getExceptionTypes());
|
||||
|
||||
throwingInstruction.visit(new Visitor() {
|
||||
@Override
|
||||
public void visitThrow(SSAThrowInstruction instruction) {
|
||||
addThrown(result, node, instruction);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all exceptions, which could be dispatched by the throw
|
||||
* instruction, by using the pointer analysis. Adds the collected exceptions
|
||||
* to addTo.
|
||||
*
|
||||
* @param addTo
|
||||
* set to add the result
|
||||
* @param node
|
||||
* node of the instruction
|
||||
* @param instruction
|
||||
* the throw instruction
|
||||
*/
|
||||
private void addThrown(LinkedHashSet<TypeReference> addTo, CGNode node, SSAThrowInstruction instruction) {
|
||||
int exceptionVariable = instruction.getException();
|
||||
PointerKey pointerKey = pointerAnalysis.getHeapModel().getPointerKeyForLocal(node, exceptionVariable);
|
||||
Iterator it = pointerAnalysis.getHeapGraph().getSuccNodes(pointerKey);
|
||||
while (it.hasNext()) {
|
||||
Object next = it.next();
|
||||
if (next instanceof InstanceKey) {
|
||||
InstanceKey instanceKey = (InstanceKey) next;
|
||||
IClass iclass = instanceKey.getConcreteType();
|
||||
addTo.add(iclass.getReference());
|
||||
} else {
|
||||
throw new IllegalStateException("Internal error: Expected InstanceKey, got " + next.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param block
|
||||
* @return an instruction which may throw exceptions, or null if this block
|
||||
* can't throw exceptions
|
||||
*/
|
||||
private SSAInstruction getThrowingInstruction(ISSABasicBlock block) {
|
||||
SSAInstruction result = null;
|
||||
if (block.getLastInstructionIndex() >= 0) {
|
||||
SSAInstruction lastInstruction = block.getLastInstruction();
|
||||
if (lastInstruction != null) {
|
||||
result = lastInstruction;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node
|
||||
* @param block
|
||||
* @return a set of all exceptions which will be caught, if thrown by the
|
||||
* given block.
|
||||
*/
|
||||
private Set<TypeReference> collectCaughtExceptions(CGNode node, ISSABasicBlock block) {
|
||||
LinkedHashSet<TypeReference> result = new LinkedHashSet<TypeReference>();
|
||||
List<ISSABasicBlock> exceptionalSuccessors = node.getIR().getControlFlowGraph().getExceptionalSuccessors(block);
|
||||
for (ISSABasicBlock succ : exceptionalSuccessors) {
|
||||
if (succ.isCatchBlock()) {
|
||||
Iterator<TypeReference> it = succ.getCaughtExceptionTypes();
|
||||
while (it.hasNext()) {
|
||||
result.add(it.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<TypeReference> subClasses = new LinkedHashSet<>();
|
||||
for (TypeReference caught : result) {
|
||||
for (IClass iclass : this.classHierachy.computeSubClasses(caught)) {
|
||||
subClasses.add(iclass.getReference());
|
||||
}
|
||||
}
|
||||
|
||||
result.addAll(subClasses);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<TypeReference> getCaughtExceptions(CGNode node, CallSiteReference callsite) {
|
||||
Set<TypeReference> result = new LinkedHashSet<>();
|
||||
|
||||
IntSet iindices = node.getIR().getCallInstructionIndices(callsite);
|
||||
IntIterator it = iindices.intIterator();
|
||||
while (it.hasNext()) {
|
||||
int iindex = it.next();
|
||||
|
||||
SSAInstruction instruction = node.getIR().getInstructions()[iindex];
|
||||
if (!((instruction instanceof SSAInvokeInstruction))) {
|
||||
throw new IllegalArgumentException("The given callsite dose not correspond to an invoke instruction." + instruction);
|
||||
}
|
||||
|
||||
ISSABasicBlock block = node.getIR().getBasicBlockForInstruction(instruction);
|
||||
if (result.isEmpty()) {
|
||||
result.addAll(collectCaughtExceptions(node, block));
|
||||
} else {
|
||||
result.retainAll(collectCaughtExceptions(node, block));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<TypeReference> getIntraproceduralExceptions(CGNode node) {
|
||||
if (!callGraph.containsNode(node)) {
|
||||
throw new IllegalArgumentException("The given CG node has to be part " + "of the call graph given during construction.");
|
||||
}
|
||||
|
||||
Set<TypeReference> result = intraproceduralExceptions.get(node);
|
||||
if (result == null) {
|
||||
throw new RuntimeException("Internal Error: No result for the given node.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<TypeReference> getExceptions() {
|
||||
return exceptions;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue