1317 lines
46 KiB
Java
1317 lines
46 KiB
Java
/*******************************************************************************
|
|
* 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.demandpa.flowgraph;
|
|
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import com.ibm.wala.analysis.typeInference.TypeAbstraction;
|
|
import com.ibm.wala.analysis.typeInference.TypeInference;
|
|
import com.ibm.wala.cfg.ControlFlowGraph;
|
|
import com.ibm.wala.cfg.IBasicBlock;
|
|
import com.ibm.wala.classLoader.CallSiteReference;
|
|
import com.ibm.wala.classLoader.IClass;
|
|
import com.ibm.wala.classLoader.IField;
|
|
import com.ibm.wala.classLoader.ProgramCounter;
|
|
import com.ibm.wala.demandpa.util.MemoryAccess;
|
|
import com.ibm.wala.demandpa.util.MemoryAccessMap;
|
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
|
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
|
|
import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.HeapModel;
|
|
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
|
import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder;
|
|
import com.ibm.wala.ipa.callgraph.propagation.SSAPropagationCallGraphBuilder;
|
|
import com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey;
|
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|
import com.ibm.wala.ssa.DefUse;
|
|
import com.ibm.wala.ssa.IR;
|
|
import com.ibm.wala.ssa.ISSABasicBlock;
|
|
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
|
|
import com.ibm.wala.ssa.SSAAbstractThrowInstruction;
|
|
import com.ibm.wala.ssa.SSAArrayLoadInstruction;
|
|
import com.ibm.wala.ssa.SSAArrayStoreInstruction;
|
|
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.SSALoadMetadataInstruction;
|
|
import com.ibm.wala.ssa.SSANewInstruction;
|
|
import com.ibm.wala.ssa.SSAPhiInstruction;
|
|
import com.ibm.wala.ssa.SSAPiInstruction;
|
|
import com.ibm.wala.ssa.SSAPutInstruction;
|
|
import com.ibm.wala.ssa.SSAReturnInstruction;
|
|
import com.ibm.wala.ssa.SSAThrowInstruction;
|
|
import com.ibm.wala.ssa.SymbolTable;
|
|
import com.ibm.wala.types.FieldReference;
|
|
import com.ibm.wala.types.TypeReference;
|
|
import com.ibm.wala.util.collections.HashMapFactory;
|
|
import com.ibm.wala.util.collections.HashSetFactory;
|
|
import com.ibm.wala.util.collections.Iterator2Iterable;
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
import com.ibm.wala.util.debug.UnimplementedError;
|
|
import com.ibm.wala.util.graph.impl.SlowSparseNumberedGraph;
|
|
import com.ibm.wala.util.intset.BitVectorIntSet;
|
|
import com.ibm.wala.util.intset.IntSet;
|
|
import com.ibm.wala.util.ref.ReferenceCleanser;
|
|
|
|
/**
|
|
* The nodes in this graph are PointerKeys corresponding to local variables and static fields, InstanceKeys, and FieldRefs (see
|
|
* below).
|
|
*
|
|
* This graph is constructed on-demand during a traversal.
|
|
*
|
|
* The edges represent
|
|
* <ul>
|
|
* <li>flow from local -> local representing assignment (i.e. phi,pi)
|
|
* <li>flow from instancekey -> local for news
|
|
* <li>flow from formal -> actual parameter
|
|
* <li>flow from return value -> local
|
|
* <li>match edges
|
|
* <li>local -> local edges representing loads/stores (e.g. x = y.f will have a edge x->y, labelled with f) for a getstatic x = Y.f,
|
|
* we have an edge from x -> Y.f.
|
|
* </ul>
|
|
*
|
|
* N.B: Edges go OPPOSITE the flow of values.
|
|
*
|
|
* Edges carry labels if they arise from loads/stores, or calls
|
|
*/
|
|
public class SimpleDemandPointerFlowGraph extends SlowSparseNumberedGraph<Object> {
|
|
|
|
private static final long serialVersionUID = 5208052568163692029L;
|
|
|
|
private final static boolean DEBUG = false;
|
|
|
|
/**
|
|
* Counter for wiping soft caches
|
|
*/
|
|
private static int wipeCount = 0;
|
|
|
|
private final CallGraph cg;
|
|
|
|
private final HeapModel heapModel;
|
|
|
|
private final MemoryAccessMap fam;
|
|
|
|
private final IClassHierarchy cha;
|
|
|
|
/**
|
|
* node numbers of CGNodes we have already visited
|
|
*/
|
|
final BitVectorIntSet cgNodesVisited = new BitVectorIntSet();
|
|
|
|
/**
|
|
* Map: LocalPointerKey -> IField. if we have (x,f), that means x was def'fed by a getfield on f.
|
|
*/
|
|
final Map<PointerKey, IField> getFieldDefs = HashMapFactory.make();
|
|
|
|
final Collection<PointerKey> arrayDefs = HashSetFactory.make();
|
|
|
|
/**
|
|
* Map: LocalPointerKey -> SSAInvokeInstruction. If we have (x, foo()), that means that x was def'fed by the return value from a
|
|
* call to foo()
|
|
*/
|
|
final Map<PointerKey, SSAInvokeInstruction> callDefs = HashMapFactory.make();
|
|
|
|
/**
|
|
* Map: LocalPointerKey -> CGNode. If we have (x, foo), then x is a parameter of method foo. For now, we have to re-discover the
|
|
* parameter position.
|
|
*/
|
|
final Map<PointerKey, CGNode> params = HashMapFactory.make();
|
|
|
|
public SimpleDemandPointerFlowGraph(CallGraph cg, HeapModel heapModel, MemoryAccessMap fam, IClassHierarchy cha) {
|
|
super();
|
|
if (cg == null) {
|
|
throw new IllegalArgumentException("null cg");
|
|
}
|
|
this.cg = cg;
|
|
this.heapModel = heapModel;
|
|
this.fam = fam;
|
|
this.cha = cha;
|
|
}
|
|
|
|
public void addSubgraphForNode(CGNode node) {
|
|
int n = cg.getNumber(node);
|
|
if (!cgNodesVisited.contains(n)) {
|
|
cgNodesVisited.add(n);
|
|
unconditionallyAddConstraintsFromNode(node);
|
|
addNodesForParameters(node);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* add nodes for parameters and return values
|
|
*
|
|
* @param node
|
|
*/
|
|
private void addNodesForParameters(CGNode node) {
|
|
// TODO Auto-generated method stub
|
|
IR ir = node.getIR();
|
|
TypeInference ti = TypeInference.make(ir, false);
|
|
SymbolTable symbolTable = ir.getSymbolTable();
|
|
for (int i = 0; i < symbolTable.getNumberOfParameters(); i++) {
|
|
int parameter = symbolTable.getParameter(i);
|
|
TypeAbstraction t = ti.getType(parameter);
|
|
if (t != null) {
|
|
PointerKey paramPk = heapModel.getPointerKeyForLocal(node, parameter);
|
|
addNode(paramPk);
|
|
params.put(paramPk, node);
|
|
}
|
|
}
|
|
addNode(heapModel.getPointerKeyForReturnValue(node));
|
|
addNode(heapModel.getPointerKeyForExceptionalReturnValue(node));
|
|
}
|
|
|
|
/**
|
|
* @return Returns the heapModel.
|
|
*/
|
|
protected HeapModel getHeapModel() {
|
|
return heapModel;
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.capa.util.graph.AbstractNumberedGraph#getPredNodeNumbers(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public IntSet getPredNodeNumbers(Object node) throws UnimplementedError {
|
|
if (node instanceof StaticFieldKey) {
|
|
Assertions.UNREACHABLE();
|
|
return null;
|
|
} else {
|
|
return super.getPredNodeNumbers(node);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.capa.util.graph.AbstractNumberedGraph#getSuccNodeNumbers(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public IntSet getSuccNodeNumbers(Object node) throws IllegalArgumentException {
|
|
if (node instanceof com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey) {
|
|
throw new IllegalArgumentException("node instanceof com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey");
|
|
}
|
|
return super.getSuccNodeNumbers(node);
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.capa.util.graph.AbstractGraph#getPredNodeCount(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public int getPredNodeCount(Object N) throws UnimplementedError {
|
|
if (N instanceof StaticFieldKey) {
|
|
Assertions.UNREACHABLE();
|
|
return -1;
|
|
} else {
|
|
return super.getPredNodeCount(N);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.capa.util.graph.AbstractGraph#getPredNodes(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public Iterator<Object> getPredNodes(Object N) throws IllegalArgumentException {
|
|
if (N instanceof com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey) {
|
|
throw new IllegalArgumentException("N instanceof com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey");
|
|
}
|
|
return super.getPredNodes(N);
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.capa.util.graph.AbstractGraph#getSuccNodeCount(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public int getSuccNodeCount(Object N) throws UnimplementedError {
|
|
if (N instanceof StaticFieldKey) {
|
|
Assertions.UNREACHABLE();
|
|
return -1;
|
|
} else {
|
|
return super.getSuccNodeCount(N);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.capa.util.graph.AbstractGraph#getSuccNodes(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public Iterator<Object> getSuccNodes(Object N) {
|
|
if (N instanceof StaticFieldKey) {
|
|
addNodesThatWriteToStaticField(((StaticFieldKey) N).getField());
|
|
} else {
|
|
IField f = getFieldDefs.get(N);
|
|
if (f != null) {
|
|
addMatchEdges((LocalPointerKey) N, f);
|
|
} else {
|
|
SSAInvokeInstruction callInstr = callDefs.get(N);
|
|
if (callInstr != null) {
|
|
addReturnEdges((LocalPointerKey) N, callInstr);
|
|
} else {
|
|
CGNode node = params.get(N);
|
|
if (node != null) {
|
|
addParamEdges((LocalPointerKey) N, node);
|
|
} else {
|
|
if (arrayDefs.contains(N)) {
|
|
addArrayMatchEdges((LocalPointerKey) N);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return super.getSuccNodes(N);
|
|
}
|
|
|
|
private void addArrayMatchEdges(LocalPointerKey pk) {
|
|
Collection<MemoryAccess> arrayWrites = fam.getArrayWrites(null);
|
|
for (MemoryAccess a : arrayWrites) {
|
|
addSubgraphForNode(a.getNode());
|
|
}
|
|
for (MemoryAccess a : arrayWrites) {
|
|
IR ir = a.getNode().getIR();
|
|
SSAArrayStoreInstruction s = (SSAArrayStoreInstruction) ir.getInstructions()[a.getInstructionIndex()];
|
|
PointerKey r = heapModel.getPointerKeyForLocal(a.getNode(), s.getValue());
|
|
assert containsNode(r);
|
|
assert containsNode(pk);
|
|
addMatchEdge(pk, r);
|
|
}
|
|
}
|
|
|
|
private void addParamEdges(LocalPointerKey pk, CGNode node) {
|
|
// get parameter position: value number - 1?
|
|
int paramPos = pk.getValueNumber() - 1;
|
|
// iterate over callers
|
|
for (CGNode caller : cg) {
|
|
// TODO we don't need to add the graph if null is passed
|
|
// as the argument
|
|
addSubgraphForNode(caller);
|
|
IR ir = caller.getIR();
|
|
for (CallSiteReference call : Iterator2Iterable.make(ir.iterateCallSites())) {
|
|
if (cg.getPossibleTargets(caller, call).contains(node)) {
|
|
SSAAbstractInvokeInstruction[] callInstrs = ir.getCalls(call);
|
|
for (SSAAbstractInvokeInstruction callInstr : callInstrs) {
|
|
PointerKey actualPk = heapModel.getPointerKeyForLocal(caller, callInstr.getUse(paramPos));
|
|
assert containsNode(actualPk);
|
|
assert containsNode(pk);
|
|
addEdge(pk, actualPk);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param pk value being def'fed by a call instruction (either normal or exceptional)
|
|
*/
|
|
private void addReturnEdges(LocalPointerKey pk, SSAInvokeInstruction callInstr) {
|
|
boolean isExceptional = pk.getValueNumber() == callInstr.getException();
|
|
|
|
// get call targets
|
|
Collection<CGNode> possibleCallees = cg.getPossibleTargets(pk.getNode(), callInstr.getCallSite());
|
|
// construct graph for each target
|
|
for (CGNode callee : possibleCallees) {
|
|
addSubgraphForNode(callee);
|
|
PointerKey retVal = isExceptional ? heapModel.getPointerKeyForExceptionalReturnValue(callee) : heapModel
|
|
.getPointerKeyForReturnValue(callee);
|
|
assert containsNode(retVal);
|
|
addEdge(pk, retVal);
|
|
}
|
|
}
|
|
|
|
private void addMatchEdges(LocalPointerKey pk, IField f) {
|
|
Collection<MemoryAccess> fieldWrites = fam.getFieldWrites(null, f);
|
|
addMatchHelper(pk, fieldWrites);
|
|
}
|
|
|
|
private void addMatchHelper(LocalPointerKey pk, Collection<MemoryAccess> writes) {
|
|
for (MemoryAccess a : writes) {
|
|
addSubgraphForNode(a.getNode());
|
|
}
|
|
for (MemoryAccess a : writes) {
|
|
IR ir = a.getNode().getIR();
|
|
SSAPutInstruction s = (SSAPutInstruction) ir.getInstructions()[a.getInstructionIndex()];
|
|
PointerKey r = heapModel.getPointerKeyForLocal(a.getNode(), s.getVal());
|
|
assert containsNode(r);
|
|
assert containsNode(pk);
|
|
addMatchEdge(pk, r);
|
|
}
|
|
}
|
|
|
|
private void addMatchEdge(LocalPointerKey pk, PointerKey r) {
|
|
addEdge(pk, r);
|
|
}
|
|
|
|
private void addNodesThatWriteToStaticField(IField field) {
|
|
Collection<MemoryAccess> fieldWrites = fam.getStaticFieldWrites(field);
|
|
for (MemoryAccess a : fieldWrites) {
|
|
addSubgraphForNode(a.getNode());
|
|
}
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.capa.util.graph.AbstractGraph#hasEdge(java.lang.Object, java.lang.Object)
|
|
*/
|
|
public boolean hasEdge(PointerKey src, PointerKey dst) {
|
|
// TODO Auto-generated method stub
|
|
return super.hasEdge(src, dst);
|
|
}
|
|
|
|
protected void unconditionallyAddConstraintsFromNode(CGNode node) {
|
|
|
|
if (DEBUG) {
|
|
System.err.println(("Visiting CGNode " + node));
|
|
}
|
|
|
|
if (SSAPropagationCallGraphBuilder.PERIODIC_WIPE_SOFT_CACHES) {
|
|
wipeCount++;
|
|
if (wipeCount >= SSAPropagationCallGraphBuilder.WIPE_SOFT_CACHE_INTERVAL) {
|
|
wipeCount = 0;
|
|
ReferenceCleanser.clearSoftCaches();
|
|
}
|
|
}
|
|
|
|
IR ir = node.getIR();
|
|
debugPrintIR(ir);
|
|
|
|
if (ir == null) {
|
|
return;
|
|
}
|
|
|
|
DefUse du = node.getDU();
|
|
addNodeInstructionConstraints(node, ir, du);
|
|
addNodePassthruExceptionConstraints(node, ir);
|
|
}
|
|
|
|
/**
|
|
* Add constraints to represent the flow of exceptions to the exceptional return value for this node
|
|
*/
|
|
protected void addNodePassthruExceptionConstraints(CGNode node, IR ir) {
|
|
// add constraints relating to thrown exceptions that reach the exit block.
|
|
List<ProgramCounter> peis = SSAPropagationCallGraphBuilder.getIncomingPEIs(ir, ir.getExitBlock());
|
|
PointerKey exception = heapModel.getPointerKeyForExceptionalReturnValue(node);
|
|
IClass c = node.getClassHierarchy().lookupClass(TypeReference.JavaLangThrowable);
|
|
|
|
addExceptionDefConstraints(ir, node, peis, exception, Collections.singleton(c));
|
|
}
|
|
|
|
/**
|
|
* Generate constraints which assign exception values into an exception pointer
|
|
*
|
|
* @param node governing node
|
|
* @param peis list of PEI instructions
|
|
* @param exceptionVar PointerKey representing a pointer to an exception value
|
|
* @param catchClasses the types "caught" by the exceptionVar
|
|
*/
|
|
private void addExceptionDefConstraints(IR ir, CGNode node, List<ProgramCounter> peis, PointerKey exceptionVar,
|
|
Set<IClass> catchClasses) {
|
|
for (ProgramCounter peiLoc : peis) {
|
|
SSAInstruction pei = ir.getPEI(peiLoc);
|
|
|
|
if (pei instanceof SSAAbstractInvokeInstruction) {
|
|
SSAAbstractInvokeInstruction s = (SSAAbstractInvokeInstruction) pei;
|
|
PointerKey e = heapModel.getPointerKeyForLocal(node, s.getException());
|
|
addNode(exceptionVar);
|
|
addNode(e);
|
|
addEdge(exceptionVar, e);
|
|
|
|
} else if (pei instanceof SSAAbstractThrowInstruction) {
|
|
SSAAbstractThrowInstruction s = (SSAAbstractThrowInstruction) pei;
|
|
PointerKey e = heapModel.getPointerKeyForLocal(node, s.getException());
|
|
addNode(exceptionVar);
|
|
addNode(e);
|
|
addEdge(exceptionVar, e);
|
|
}
|
|
|
|
// Account for those exceptions for which we do not actually have a
|
|
// points-to set for
|
|
// the pei, but just instance keys
|
|
Collection<TypeReference> types = pei.getExceptionTypes();
|
|
if (types != null) {
|
|
for (TypeReference type : types) {
|
|
if (type != null) {
|
|
InstanceKey ik = heapModel.getInstanceKeyForPEI(node, peiLoc, type);
|
|
assert ik instanceof ConcreteTypeKey : "uh oh: need to implement getCaughtException constraints for instance " + ik;
|
|
ConcreteTypeKey ck = (ConcreteTypeKey) ik;
|
|
IClass klass = ck.getType();
|
|
if (PropagationCallGraphBuilder.catches(catchClasses, klass, cha)) {
|
|
addNode(exceptionVar);
|
|
addNode(ik);
|
|
addEdge(exceptionVar, ik);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add pointer flow constraints based on instructions in a given node
|
|
*/
|
|
protected void addNodeInstructionConstraints(CGNode node, IR ir, DefUse du) {
|
|
StatementVisitor v = makeVisitor((ExplicitCallGraph.ExplicitNode) node, ir, du);
|
|
ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg = ir.getControlFlowGraph();
|
|
for (ISSABasicBlock b : cfg) {
|
|
addBlockInstructionConstraints(node, cfg, b, v);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add constraints for a particular basic block.
|
|
*/
|
|
protected void addBlockInstructionConstraints(CGNode node, ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg,
|
|
ISSABasicBlock b, StatementVisitor v) {
|
|
v.setBasicBlock(b);
|
|
|
|
// visit each instruction in the basic block.
|
|
for (SSAInstruction s : b) {
|
|
if (s != null) {
|
|
s.visit(v);
|
|
}
|
|
}
|
|
|
|
addPhiConstraints(node, cfg, b);
|
|
}
|
|
|
|
private void addPhiConstraints(CGNode node, ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg, ISSABasicBlock b) {
|
|
|
|
// visit each phi instruction in each successor block
|
|
for (ISSABasicBlock sb : Iterator2Iterable.make(cfg.getSuccNodes(b))) {
|
|
if (sb.isExitBlock()) {
|
|
// an optimization based on invariant that exit blocks should have no
|
|
// phis.
|
|
continue;
|
|
}
|
|
int n = 0;
|
|
// set n to be whichPred(this, sb);
|
|
for (IBasicBlock back : Iterator2Iterable.make(cfg.getPredNodes(sb))) {
|
|
if (back == b) {
|
|
break;
|
|
}
|
|
++n;
|
|
}
|
|
assert n < cfg.getPredNodeCount(sb);
|
|
for (SSAPhiInstruction phi : Iterator2Iterable.make(sb.iteratePhis())) {
|
|
if (phi == null) {
|
|
continue;
|
|
}
|
|
PointerKey def = heapModel.getPointerKeyForLocal(node, phi.getDef());
|
|
if (phi.getUse(n) > 0) {
|
|
PointerKey use = heapModel.getPointerKeyForLocal(node, phi.getUse(n));
|
|
addNode(def);
|
|
addNode(use);
|
|
addEdge(def, use);
|
|
}
|
|
// }
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
|
|
protected StatementVisitor makeVisitor(ExplicitCallGraph.ExplicitNode node, IR ir, DefUse du) {
|
|
return new StatementVisitor(node, ir, du);
|
|
}
|
|
|
|
private static void debugPrintIR(IR ir) {
|
|
if (DEBUG) {
|
|
if (ir == null) {
|
|
System.err.println("\n No statements\n");
|
|
} else {
|
|
try {
|
|
System.err.println(ir.toString());
|
|
} catch (Error e) {
|
|
// TODO Auto-generated catch block
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A visitor that generates graph nodes and edges for an IR.
|
|
*
|
|
* strategy: when visiting a statement, for each use of that statement, add a graph edge from def to use.
|
|
*
|
|
* TODO: special treatment for parameter passing, etc.
|
|
*/
|
|
protected class StatementVisitor extends SSAInstruction.Visitor {
|
|
|
|
/**
|
|
* The node whose statements we are currently traversing
|
|
*/
|
|
protected final CGNode node;
|
|
|
|
/**
|
|
* The governing IR
|
|
*/
|
|
protected final IR ir;
|
|
|
|
/**
|
|
* The basic block currently being processed
|
|
*/
|
|
private ISSABasicBlock basicBlock;
|
|
|
|
/**
|
|
* Governing symbol table
|
|
*/
|
|
protected final SymbolTable symbolTable;
|
|
|
|
/**
|
|
* Def-use information
|
|
*/
|
|
protected final DefUse du;
|
|
|
|
public StatementVisitor(CGNode node, IR ir, DefUse du) {
|
|
this.node = node;
|
|
this.ir = ir;
|
|
this.symbolTable = ir.getSymbolTable();
|
|
assert symbolTable != null;
|
|
this.du = du;
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.SSAInstruction.Visitor#visitArrayLoad(com.ibm.domo.ssa.SSAArrayLoadInstruction)
|
|
*/
|
|
@Override
|
|
public void visitArrayLoad(SSAArrayLoadInstruction instruction) {
|
|
// skip arrays of primitive type
|
|
if (instruction.typeIsPrimitive()) {
|
|
return;
|
|
}
|
|
PointerKey result = heapModel.getPointerKeyForLocal(node, instruction.getDef());
|
|
arrayDefs.add(result);
|
|
// PointerKey arrayRef = getPointerKeyForLocal(node,
|
|
// instruction.getArrayRef());
|
|
// if (hasNoInterestingUses(instruction.getDef(), du)) {
|
|
// system.recordImplicitPointsToSet(result);
|
|
// } else {
|
|
// if (contentsAreInvariant(symbolTable, du, instruction.getArrayRef())) {
|
|
// system.recordImplicitPointsToSet(arrayRef);
|
|
// InstanceKey[] ik = getInvariantContents(symbolTable, du, node,
|
|
// instruction.getArrayRef(),
|
|
// SSAPropagationCallGraphBuilder.this);
|
|
// for (int i = 0; i < ik.length; i++) {
|
|
// system.findOrCreateIndexForInstanceKey(ik[i]);
|
|
// PointerKey p = getPointerKeyForArrayContents(ik[i]);
|
|
// if (p == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node,
|
|
// ik[i].getConcreteType()));
|
|
// } else {
|
|
// system.newConstraint(result, assignOperator, p);
|
|
// }
|
|
// }
|
|
// } else {
|
|
// if (Assertions.verifyAssertions) {
|
|
// Assertions._assert(!system.isUnified(result));
|
|
// Assertions._assert(!system.isUnified(arrayRef));
|
|
// }
|
|
// system.newSideEffect(new
|
|
// ArrayLoadOperator(system.findOrCreatePointsToSet(result)), arrayRef);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.SSAInstruction.Visitor#visitArrayStore(com.ibm.domo.ssa.SSAArrayStoreInstruction)
|
|
*/
|
|
@Override
|
|
public void visitArrayStore(SSAArrayStoreInstruction instruction) {
|
|
// Assertions.UNREACHABLE();
|
|
// skip arrays of primitive type
|
|
if (instruction.typeIsPrimitive()) {
|
|
return;
|
|
}
|
|
// make node for used value
|
|
PointerKey value = heapModel.getPointerKeyForLocal(node, instruction.getValue());
|
|
addNode(value);
|
|
//
|
|
// // (requires the creation of assign constraints as
|
|
// // the set points-to(a[]) grows.)
|
|
// PointerKey arrayRef = getPointerKeyForLocal(node,
|
|
// instruction.getArrayRef());
|
|
// // if (!supportFullPointerFlowGraph &&
|
|
// // contentsAreInvariant(instruction.getArrayRef())) {
|
|
// if (contentsAreInvariant(symbolTable, du, instruction.getArrayRef())) {
|
|
// system.recordImplicitPointsToSet(arrayRef);
|
|
// InstanceKey[] ik = getInvariantContents(symbolTable, du, node,
|
|
// instruction.getArrayRef(),
|
|
// SSAPropagationCallGraphBuilder.this);
|
|
//
|
|
// for (int i = 0; i < ik.length; i++) {
|
|
// system.findOrCreateIndexForInstanceKey(ik[i]);
|
|
// PointerKey p = getPointerKeyForArrayContents(ik[i]);
|
|
// IClass contents = ((ArrayClass)
|
|
// ik[i].getConcreteType()).getElementClass();
|
|
// if (p == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node,
|
|
// ik[i].getConcreteType()));
|
|
// } else {
|
|
// if (DEBUG_TRACK_INSTANCE) {
|
|
// if (system.findOrCreateIndexForInstanceKey(ik[i]) ==
|
|
// DEBUG_INSTANCE_KEY) {
|
|
// Assertions.UNREACHABLE();
|
|
// }
|
|
// }
|
|
// if (contentsAreInvariant(symbolTable, du, instruction.getValue())) {
|
|
// system.recordImplicitPointsToSet(value);
|
|
// InstanceKey[] vk = getInvariantContents(symbolTable, du, node,
|
|
// instruction.getValue(),
|
|
// SSAPropagationCallGraphBuilder.this);
|
|
// for (int j = 0; j < vk.length; j++) {
|
|
// system.findOrCreateIndexForInstanceKey(vk[j]);
|
|
// if (vk[j].getConcreteType() != null) {
|
|
// if (contents.isInterface()) {
|
|
// if (getClassHierarchy().implementsInterface(vk[j].getConcreteType(),
|
|
// contents.getReference())) {
|
|
// system.newConstraint(p, vk[j]);
|
|
// }
|
|
// } else {
|
|
// if (getClassHierarchy().isSubclassOf(vk[j].getConcreteType(),
|
|
// contents)) {
|
|
// system.newConstraint(p, vk[j]);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// } else {
|
|
// if (isRootType(contents)) {
|
|
// system.newConstraint(p, assignOperator, value);
|
|
// } else {
|
|
// system.newConstraint(p, filterOperator, value);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// } else {
|
|
// if (contentsAreInvariant(symbolTable, du, instruction.getValue())) {
|
|
// system.recordImplicitPointsToSet(value);
|
|
// InstanceKey[] ik = getInvariantContents(symbolTable, du, node,
|
|
// instruction.getValue(),
|
|
// SSAPropagationCallGraphBuilder.this);
|
|
// for (int i = 0; i < ik.length; i++) {
|
|
// system.findOrCreateIndexForInstanceKey(ik[i]);
|
|
// if (Assertions.verifyAssertions) {
|
|
// Assertions._assert(!system.isUnified(arrayRef));
|
|
// }
|
|
// system.newSideEffect(new InstanceArrayStoreOperator(ik[i]), arrayRef);
|
|
// }
|
|
// } else {
|
|
// system.newSideEffect(new
|
|
// ArrayStoreOperator(system.findOrCreatePointsToSet(value)), arrayRef);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.SSAInstruction.Visitor#visitCheckCast(com.ibm.domo.ssa.SSACheckCastInstruction)
|
|
*/
|
|
@Override
|
|
public void visitCheckCast(SSACheckCastInstruction instruction) {
|
|
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);
|
|
//
|
|
// if (hasNoInterestingUses(instruction.getDef(), du)) {
|
|
// system.recordImplicitPointsToSet(result);
|
|
// } else {
|
|
// if (contentsAreInvariant(symbolTable, du, instruction.getVal())) {
|
|
// system.recordImplicitPointsToSet(value);
|
|
// InstanceKey[] ik = getInvariantContents(symbolTable, du, node,
|
|
// instruction.getVal(), SSAPropagationCallGraphBuilder.this);
|
|
// if (cls.isInterface()) {
|
|
// for (int i = 0; i < ik.length; i++) {
|
|
// system.findOrCreateIndexForInstanceKey(ik[i]);
|
|
// if (getClassHierarchy().implementsInterface(ik[i].getConcreteType(),
|
|
// cls.getReference())) {
|
|
// 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 (cls == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node,
|
|
// instruction.getDeclaredResultType()));
|
|
// cls = getJavaLangObject();
|
|
// }
|
|
// if (isRootType(cls)) {
|
|
// system.newConstraint(result, assignOperator, value);
|
|
// } else {
|
|
// system.newConstraint(result, filterOperator, value);
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.SSAInstruction.Visitor#visitReturn(com.ibm.domo.ssa.SSAReturnInstruction)
|
|
*/
|
|
@Override
|
|
public void visitReturn(SSAReturnInstruction instruction) {
|
|
// skip returns of primitive type
|
|
if (instruction.returnsPrimitiveType() || instruction.returnsVoid()) {
|
|
return;
|
|
} else {
|
|
// just make a node for the def'd value
|
|
PointerKey def = heapModel.getPointerKeyForLocal(node, instruction.getResult());
|
|
addNode(def);
|
|
PointerKey returnValue = heapModel.getPointerKeyForReturnValue(node);
|
|
addNode(returnValue);
|
|
addEdge(returnValue, def);
|
|
}
|
|
// PointerKey returnValue = getPointerKeyForReturnValue(node);
|
|
// PointerKey result = getPointerKeyForLocal(node,
|
|
// instruction.getResult());
|
|
// // if (!supportFullPointerFlowGraph &&
|
|
// // contentsAreInvariant(instruction.getResult())) {
|
|
// if (contentsAreInvariant(symbolTable, du, instruction.getResult())) {
|
|
// system.recordImplicitPointsToSet(result);
|
|
// InstanceKey[] ik = getInvariantContents(symbolTable, du, node,
|
|
// instruction.getResult(), SSAPropagationCallGraphBuilder.this);
|
|
// for (int i = 0; i < ik.length; i++) {
|
|
// system.newConstraint(returnValue, ik[i]);
|
|
// }
|
|
// } else {
|
|
// system.newConstraint(returnValue, assignOperator, result);
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.SSAInstruction.Visitor#visitGet(com.ibm.domo.ssa.SSAGetInstruction)
|
|
*/
|
|
@Override
|
|
public void visitGet(SSAGetInstruction instruction) {
|
|
visitGetInternal(instruction.getDef(), instruction.isStatic(), instruction.getDeclaredField());
|
|
}
|
|
|
|
protected void visitGetInternal(int lval, boolean isStatic, FieldReference field) {
|
|
|
|
// skip getfields of primitive type (optimisation)
|
|
if (field.getFieldType().isPrimitiveType()) {
|
|
return;
|
|
}
|
|
IField f = cg.getClassHierarchy().resolveField(field);
|
|
if (f == null) {
|
|
return;
|
|
}
|
|
PointerKey def = heapModel.getPointerKeyForLocal(node, lval);
|
|
assert def != null;
|
|
|
|
if (isStatic) {
|
|
PointerKey fKey = heapModel.getPointerKeyForStaticField(f);
|
|
addNode(def);
|
|
addNode(fKey);
|
|
addEdge(def, fKey);
|
|
} else {
|
|
addNode(def);
|
|
getFieldDefs.put(def, f);
|
|
}
|
|
// system.newConstraint(def, assignOperator, fKey);
|
|
// IClass klass = getClassHierarchy().lookupClass(field.getType());
|
|
// if (klass == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node, field.getType()));
|
|
// } else {
|
|
// // side effect of getstatic: may call class initializer
|
|
// if (DEBUG) {
|
|
// Trace.guardedPrintln("getstatic call class init " + klass,
|
|
// DEBUG_METHOD_SUBSTRING);
|
|
// }
|
|
|
|
//
|
|
// if (hasNoInterestingUses(lval, du)) {
|
|
// system.recordImplicitPointsToSet(def);
|
|
// } else {
|
|
// if (isStatic) {
|
|
// PointerKey fKey = getPointerKeyForStaticField(f);
|
|
// system.newConstraint(def, assignOperator, fKey);
|
|
// IClass klass = getClassHierarchy().lookupClass(field.getType());
|
|
// if (klass == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node, field.getType()));
|
|
// } else {
|
|
// // side effect of getstatic: may call class initializer
|
|
// if (DEBUG) {
|
|
// Trace.guardedPrintln("getstatic call class init " + klass,
|
|
// DEBUG_METHOD_SUBSTRING);
|
|
// }
|
|
// processClassInitializer(klass);
|
|
// }
|
|
// } else {
|
|
// PointerKey refKey = getPointerKeyForLocal(node, ref);
|
|
// // if (!supportFullPointerFlowGraph &&
|
|
// // contentsAreInvariant(ref)) {
|
|
// if (contentsAreInvariant(symbolTable, du, ref)) {
|
|
// system.recordImplicitPointsToSet(refKey);
|
|
// InstanceKey[] ik = getInvariantContents(symbolTable, du, node, ref,
|
|
// SSAPropagationCallGraphBuilder.this);
|
|
// for (int i = 0; i < ik.length; i++) {
|
|
// system.findOrCreateIndexForInstanceKey(ik[i]);
|
|
// PointerKey p = getPointerKeyForInstanceField(ik[i], f);
|
|
// system.newConstraint(def, assignOperator, p);
|
|
// }
|
|
// } else {
|
|
// system.newSideEffect(new GetFieldOperator(f,
|
|
// system.findOrCreatePointsToSet(def)), refKey);
|
|
// }
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.Instruction.Visitor#visitPut(com.ibm.domo.ssa.PutInstruction)
|
|
*/
|
|
@Override
|
|
public void visitPut(SSAPutInstruction instruction) {
|
|
visitPutInternal(instruction.getVal(), instruction.isStatic(), instruction.getDeclaredField());
|
|
}
|
|
|
|
public void visitPutInternal(int rval, boolean isStatic, FieldReference field) {
|
|
// skip putfields of primitive type (optimisation)
|
|
if (field.getFieldType().isPrimitiveType()) {
|
|
return;
|
|
}
|
|
IField f = cg.getClassHierarchy().resolveField(field);
|
|
if (f == null) {
|
|
return;
|
|
}
|
|
PointerKey use = heapModel.getPointerKeyForLocal(node, rval);
|
|
assert use != null;
|
|
|
|
if (isStatic) {
|
|
PointerKey fKey = heapModel.getPointerKeyForStaticField(f);
|
|
addNode(use);
|
|
addNode(fKey);
|
|
addEdge(fKey, use);
|
|
} else {
|
|
addNode(use);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.domo.ssa.Instruction.Visitor#visitInvoke(com.ibm.domo.ssa.InvokeInstruction)
|
|
*/
|
|
@Override
|
|
public void visitInvoke(SSAInvokeInstruction instruction) {
|
|
|
|
for (int i = 0; i < instruction.getNumberOfUses(); i++) {
|
|
// just make nodes for parameters; we'll get to them when traversing
|
|
// from the callee
|
|
PointerKey use = heapModel.getPointerKeyForLocal(node, instruction.getUse(i));
|
|
addNode(use);
|
|
}
|
|
|
|
// for any def'd values, keep track of the fact that they are def'd
|
|
// by a call
|
|
if (instruction.hasDef()) {
|
|
PointerKey def = heapModel.getPointerKeyForLocal(node, instruction.getDef());
|
|
addNode(def);
|
|
callDefs.put(def, instruction);
|
|
}
|
|
PointerKey exc = heapModel.getPointerKeyForLocal(node, instruction.getException());
|
|
addNode(exc);
|
|
callDefs.put(exc, instruction);
|
|
// TODO handle exceptions
|
|
// if (DEBUG && debug) {
|
|
// Trace.println("visitInvoke: " + instruction);
|
|
// }
|
|
//
|
|
// PointerKey uniqueCatch = null;
|
|
// if (hasUniqueCatchBlock(instruction, ir)) {
|
|
// uniqueCatch = getUniqueCatchKey(instruction, ir, node);
|
|
// }
|
|
//
|
|
// if (instruction.getCallSite().isStatic()) {
|
|
// CGNode n = getTargetForCall(node, instruction.getCallSite(),
|
|
// (InstanceKey) null);
|
|
// if (n == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node, instruction));
|
|
// } else {
|
|
// processResolvedCall(node, instruction, n,
|
|
// computeInvariantParameters(instruction), uniqueCatch);
|
|
// if (DEBUG) {
|
|
// Trace.guardedPrintln("visitInvoke class init " + n,
|
|
// DEBUG_METHOD_SUBSTRING);
|
|
// }
|
|
//
|
|
// // side effect of invoke: may call class initializer
|
|
// processClassInitializer(n.getMethod().getDeclaringClass());
|
|
// }
|
|
// } else {
|
|
// // Add a side effect that will fire when we determine a value
|
|
// // for the receiver. This side effect will create a new node
|
|
// // and new constraints based on the new callee context.
|
|
// // NOTE: This will not be adequate for CPA-style context selectors,
|
|
// // where the callee context may depend on state other than the
|
|
// // receiver. TODO: rectify this when needed.
|
|
// PointerKey receiver = getPointerKeyForLocal(node,
|
|
// instruction.getReceiver());
|
|
// // if (!supportFullPointerFlowGraph &&
|
|
// // contentsAreInvariant(instruction.getReceiver())) {
|
|
// if (contentsAreInvariant(symbolTable, du, instruction.getReceiver())) {
|
|
// system.recordImplicitPointsToSet(receiver);
|
|
// InstanceKey[] ik = getInvariantContents(symbolTable, du, node,
|
|
// instruction.getReceiver(),
|
|
// SSAPropagationCallGraphBuilder.this);
|
|
// for (int i = 0; i < ik.length; i++) {
|
|
// system.findOrCreateIndexForInstanceKey(ik[i]);
|
|
// CGNode n = getTargetForCall(node, instruction.getCallSite(), ik[i]);
|
|
// if (n == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node, instruction));
|
|
// } else {
|
|
// processResolvedCall(node, instruction, n,
|
|
// computeInvariantParameters(instruction), uniqueCatch);
|
|
// // side effect of invoke: may call class initializer
|
|
// processClassInitializer(n.getMethod().getDeclaringClass());
|
|
// }
|
|
// }
|
|
// } else {
|
|
// if (DEBUG && debug) {
|
|
// Trace.println("Add side effect, dispatch to " + instruction + ",
|
|
// receiver " + receiver);
|
|
// }
|
|
// DispatchOperator dispatchOperator = new DispatchOperator(instruction,
|
|
// node, computeInvariantParameters(instruction),
|
|
// uniqueCatch);
|
|
// system.newSideEffect(dispatchOperator, receiver);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.Instruction.Visitor#visitNew(com.ibm.domo.ssa.NewInstruction)
|
|
*/
|
|
@Override
|
|
public void visitNew(SSANewInstruction instruction) {
|
|
|
|
InstanceKey iKey = heapModel.getInstanceKeyForAllocation(node, instruction.getNewSite());
|
|
if (iKey == null) {
|
|
// something went wrong. I hope someone raised a warning.
|
|
return;
|
|
}
|
|
PointerKey def = heapModel.getPointerKeyForLocal(node, instruction.getDef());
|
|
addNode(iKey);
|
|
addNode(def);
|
|
addEdge(def, iKey);
|
|
// IClass klass = iKey.getConcreteType();
|
|
//
|
|
// if (DEBUG && debug) {
|
|
// Trace.println("visitNew: " + instruction + " " + iKey + " " +
|
|
// system.findOrCreateIndexForInstanceKey(iKey));
|
|
// }
|
|
//
|
|
// if (klass == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node,
|
|
// instruction.getConcreteType()));
|
|
// return;
|
|
// }
|
|
//
|
|
// if (!contentsAreInvariant(symbolTable, du, instruction.getDef())) {
|
|
// system.newConstraint(def, iKey);
|
|
// } else {
|
|
// system.findOrCreateIndexForInstanceKey(iKey);
|
|
// system.recordImplicitPointsToSet(def);
|
|
// }
|
|
//
|
|
// // side effect of new: may call class initializer
|
|
// if (DEBUG) {
|
|
// Trace.guardedPrintln("visitNew call clinit: " + klass,
|
|
// DEBUG_METHOD_SUBSTRING);
|
|
// }
|
|
// processClassInitializer(klass);
|
|
//
|
|
// // add instance keys and pointer keys for array contents
|
|
// int dim = 0;
|
|
// InstanceKey lastInstance = iKey;
|
|
// while (klass != null && klass.isArrayClass()) {
|
|
// klass = ((ArrayClass) klass).getElementClass();
|
|
// // klass == null means it's a primitive
|
|
// if (klass != null && klass.isArrayClass()) {
|
|
// InstanceKey ik = getInstanceKeyForMultiNewArray(node,
|
|
// instruction.getNewSite(), dim);
|
|
// PointerKey pk = getPointerKeyForArrayContents(lastInstance);
|
|
// if (DEBUG_MULTINEWARRAY) {
|
|
// Trace.println("multinewarray constraint: ");
|
|
// Trace.println(" pk: " + pk);
|
|
// Trace.println(" ik: " + system.findOrCreateIndexForInstanceKey(ik) + "
|
|
// concrete type " + ik.getConcreteType()
|
|
// + " is " + ik);
|
|
// Trace.println(" klass:" + klass);
|
|
// }
|
|
// system.newConstraint(pk, ik);
|
|
// lastInstance = ik;
|
|
// dim++;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.Instruction.Visitor#visitThrow(com.ibm.domo.ssa.ThrowInstruction)
|
|
*/
|
|
@Override
|
|
public void visitThrow(SSAThrowInstruction instruction) {
|
|
// Assertions.UNREACHABLE();
|
|
// don't do anything: we handle exceptional edges
|
|
// in a separate pass
|
|
}
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.Instruction.Visitor#visitGetCaughtException(com.ibm.domo.ssa.GetCaughtExceptionInstruction)
|
|
*/
|
|
@Override
|
|
public void visitGetCaughtException(SSAGetCaughtExceptionInstruction instruction) {
|
|
List<ProgramCounter> peis = SSAPropagationCallGraphBuilder.getIncomingPEIs(ir, getBasicBlock());
|
|
PointerKey def = heapModel.getPointerKeyForLocal(node, instruction.getDef());
|
|
|
|
Set<IClass> types = SSAPropagationCallGraphBuilder.getCaughtExceptionTypes(instruction, ir);
|
|
addExceptionDefConstraints(ir, node, peis, def, types);
|
|
}
|
|
|
|
// private int booleanConstantTest(SSAConditionalBranchInstruction c, int v)
|
|
// {
|
|
// int result = 0;
|
|
//
|
|
// // right for OPR_eq
|
|
// if ((symbolTable.isZero(c.getUse(0)) && c.getUse(1) == v) ||
|
|
// (symbolTable.isZero(c.getUse(1)) && c.getUse(0) == v)) {
|
|
// result = -1;
|
|
// } else if ((symbolTable.isOne(c.getUse(0)) && c.getUse(1) == v) ||
|
|
// (symbolTable.isOne(c.getUse(1)) && c.getUse(0) == v)) {
|
|
// result = 1;
|
|
// }
|
|
//
|
|
// if (c.getOperator() == Constants.OPR_ne) {
|
|
// result = -result;
|
|
// }
|
|
//
|
|
// return result;
|
|
// }
|
|
//
|
|
// private int nullConstantTest(SSAConditionalBranchInstruction c, int v) {
|
|
// if ((symbolTable.isNullConstant(c.getUse(0)) && c.getUse(1) == v)
|
|
// || (symbolTable.isNullConstant(c.getUse(1)) && c.getUse(0) == v)) {
|
|
// if (c.getOperator() == Constants.OPR_eq) {
|
|
// return 1;
|
|
// } else {
|
|
// return -1;
|
|
// }
|
|
// } else {
|
|
// return 0;
|
|
// }
|
|
// }
|
|
|
|
/*
|
|
* (non-Javadoc)
|
|
*
|
|
* @see com.ibm.domo.ssa.SSAInstruction.Visitor#visitPi(com.ibm.domo.ssa.SSAPiInstruction)
|
|
*/
|
|
@Override
|
|
public void visitPi(SSAPiInstruction instruction) {
|
|
Assertions.UNREACHABLE();
|
|
// int dir;
|
|
// ControlFlowGraph CFG = ir.getControlFlowGraph();
|
|
// PointerKey src = getPointerKeyForLocal(node, instruction.getVal());
|
|
// if (hasNoInterestingUses(instruction.getDef(), du)) {
|
|
// PointerKey dst = getPointerKeyForLocal(node, instruction.getDef());
|
|
// system.recordImplicitPointsToSet(dst);
|
|
// } else {
|
|
// if (com.ibm.domo.cfg.Util.endsWithConditionalBranch(CFG,
|
|
// getBasicBlock()) && CFG.getSuccNodeCount(getBasicBlock()) == 2) {
|
|
// SSAConditionalBranchInstruction cond =
|
|
// com.ibm.domo.cfg.Util.getConditionalBranch(CFG, getBasicBlock());
|
|
// SSAInstruction cause = instruction.getCause();
|
|
// BasicBlock target = (BasicBlock)
|
|
// CFG.getNode(instruction.getSuccessor());
|
|
// if ((cause instanceof SSAInstanceofInstruction) && ((dir =
|
|
// booleanConstantTest(cond, cause.getDef())) != 0)) {
|
|
// TypeReference type = ((SSAInstanceofInstruction)
|
|
// cause).getCheckedType();
|
|
// IClass cls = cha.lookupClass(type);
|
|
// if (cls == null) {
|
|
// getWarnings().add(ResolutionFailure.create(node, type));
|
|
// PointerKey dst = getPointerKeyForLocal(node, instruction.getDef());
|
|
// system.newConstraint(dst, assignOperator, src);
|
|
// } else {
|
|
// PointerKey dst = getFilteredPointerKeyForLocal(node,
|
|
// instruction.getDef(), cls);
|
|
// if ((target == com.ibm.domo.cfg.Util.getTrueSuccessor(CFG,
|
|
// getBasicBlock()) && dir == 1)
|
|
// || (target == com.ibm.domo.cfg.Util.getFalseSuccessor(CFG,
|
|
// getBasicBlock()) && dir == -1)) {
|
|
// system.newConstraint(dst, filterOperator, src);
|
|
// // System.err.println("PI " + dst + " " + src);
|
|
// } else {
|
|
// system.newConstraint(dst, inverseFilterOperator, src);
|
|
// }
|
|
// }
|
|
// } else if ((dir = nullConstantTest(cond, instruction.getVal())) != 0) {
|
|
// if ((target == com.ibm.domo.cfg.Util.getTrueSuccessor(CFG,
|
|
// getBasicBlock()) && dir == -1)
|
|
// || (target == com.ibm.domo.cfg.Util.getFalseSuccessor(CFG,
|
|
// getBasicBlock()) && dir == 1)) {
|
|
// PointerKey dst = getPointerKeyForLocal(node, instruction.getDef());
|
|
// system.newConstraint(dst, assignOperator, src);
|
|
// }
|
|
// } else {
|
|
// PointerKey dst = getPointerKeyForLocal(node, instruction.getDef());
|
|
// system.newConstraint(dst, assignOperator, src);
|
|
// }
|
|
// } else {
|
|
// PointerKey dst = getPointerKeyForLocal(node, instruction.getDef());
|
|
// system.newConstraint(dst, assignOperator, src);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
public ISSABasicBlock getBasicBlock() {
|
|
return basicBlock;
|
|
}
|
|
|
|
/**
|
|
* The calling loop must call this in each iteration!
|
|
*/
|
|
public void setBasicBlock(ISSABasicBlock block) {
|
|
basicBlock = block;
|
|
}
|
|
|
|
// /**
|
|
// * Side effect: records invariant parameters as implicit points-to-sets.
|
|
// *
|
|
// * @return if non-null, then result[i] holds the set of instance keys
|
|
// which
|
|
// * may be passed as the ith parameter. (which must be invariant)
|
|
// */
|
|
// protected InstanceKey[][]
|
|
// computeInvariantParameters(SSAAbstractInvokeInstruction call) {
|
|
// InstanceKey[][] constParams = null;
|
|
// for (int i = 0; i < call.getNumberOfUses(); i++) {
|
|
// // not sure how getUse(i) <= 0 .. dead code?
|
|
// // TODO: investigate
|
|
// if (call.getUse(i) > 0) {
|
|
// if (contentsAreInvariant(symbolTable, du, call.getUse(i))) {
|
|
// system.recordImplicitPointsToSet(getPointerKeyForLocal(node,
|
|
// call.getUse(i)));
|
|
// if (constParams == null) {
|
|
// constParams = new InstanceKey[call.getNumberOfUses()][];
|
|
// }
|
|
// constParams[i] = getInvariantContents(symbolTable, du, node,
|
|
// call.getUse(i), SSAPropagationCallGraphBuilder.this);
|
|
// for (int j = 0; j < constParams[i].length; j++) {
|
|
// system.findOrCreateIndexForInstanceKey(constParams[i][j]);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// return constParams;
|
|
// }
|
|
|
|
@Override
|
|
public void visitLoadMetadata(SSALoadMetadataInstruction instruction) {
|
|
Assertions.UNREACHABLE();
|
|
// PointerKey def = getPointerKeyForLocal(node, instruction.getDef());
|
|
// InstanceKey iKey =
|
|
// getInstanceKeyForClassObject(instruction.getLoadedClass());
|
|
//
|
|
// if (!contentsAreInvariant(symbolTable, du, instruction.getDef())) {
|
|
// system.newConstraint(def, iKey);
|
|
// } else {
|
|
// system.findOrCreateIndexForInstanceKey(iKey);
|
|
// system.recordImplicitPointsToSet(def);
|
|
// }
|
|
}
|
|
}
|
|
|
|
// private final class FieldExpression {
|
|
// LocalPointerKey x;
|
|
//
|
|
// IField f;
|
|
//
|
|
// public FieldExpression(IField f, LocalPointerKey x) {
|
|
// this.f = f;
|
|
// this.x = x;
|
|
// }
|
|
//
|
|
// /*
|
|
// * (non-Javadoc)
|
|
// *
|
|
// * @see java.lang.Object#equals(java.lang.Object)
|
|
// */
|
|
// public boolean equals(Object obj) {
|
|
// if (obj instanceof FieldExpression) {
|
|
// FieldExpression other = (FieldExpression) obj;
|
|
// return x.equals(other.x) && f.equals(other.f);
|
|
// } else {
|
|
// return false;
|
|
// }
|
|
// }
|
|
//
|
|
// /*
|
|
// * (non-Javadoc)
|
|
// *
|
|
// * @see java.lang.Object#hashCode()
|
|
// */
|
|
// public int hashCode() {
|
|
// return x.hashCode() + 4729 * f.hashCode();
|
|
// }
|
|
// }
|
|
|
|
}
|