bug fixes and new tests for new Class.forName processing.
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2544 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
518d21140e
commit
fffb7ac8bc
|
@ -32,11 +32,7 @@ import com.ibm.wala.util.strings.StringStuff;
|
|||
*/
|
||||
class ForNameContextSelector implements ContextSelector {
|
||||
|
||||
private final IMethod forNameMethod;
|
||||
|
||||
public ForNameContextSelector(final IClassHierarchy cha) {
|
||||
this.forNameMethod = cha.resolveMethod(ForNameContextInterpreter.FOR_NAME_REF);
|
||||
assert forNameMethod != null;
|
||||
public ForNameContextSelector() {
|
||||
}
|
||||
|
||||
public boolean allSitesDispatchIdentically(CGNode node, CallSiteReference site) {
|
||||
|
@ -56,7 +52,7 @@ class ForNameContextSelector implements ContextSelector {
|
|||
* com.ibm.wala.ipa.callgraph.propagation.InstanceKey)
|
||||
*/
|
||||
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) {
|
||||
if (callee.equals(forNameMethod)) {
|
||||
if (callee.getReference().equals(ForNameContextInterpreter.FOR_NAME_REF)) {
|
||||
IR ir = caller.getIR();
|
||||
SymbolTable symbolTable = ir.getSymbolTable();
|
||||
SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site);
|
||||
|
@ -81,7 +77,7 @@ class ForNameContextSelector implements ContextSelector {
|
|||
* This object may understand a dispatch to Class.forName(s) when s is a string constant.
|
||||
*/
|
||||
public boolean mayUnderstand(CGNode caller, CallSiteReference site, IMethod targetMethod, InstanceKey instance) {
|
||||
if (targetMethod.equals(forNameMethod)) {
|
||||
if (targetMethod.getReference().equals(ForNameContextInterpreter.FOR_NAME_REF)) {
|
||||
IR ir = caller.getIR();
|
||||
SymbolTable symbolTable = ir.getSymbolTable();
|
||||
SSAAbstractInvokeInstruction[] invokeInstructions = caller.getIR().getCalls(site);
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ReflectionContextSelector extends DelegatingContextSelector {
|
|||
* First check "forName" logic, then factory logic.
|
||||
*/
|
||||
private ReflectionContextSelector(IClassHierarchy cha, MethodTargetSelector methodTargetSelector) {
|
||||
super(new ForNameContextSelector(cha), new FactoryContextSelector(cha, methodTargetSelector));
|
||||
super(new ForNameContextSelector(), new FactoryContextSelector(cha, methodTargetSelector));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import com.ibm.wala.classLoader.IMethod;
|
|||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
|
||||
/**
|
||||
*
|
||||
* An interface to an object which helps control context-sensitivity
|
||||
*
|
||||
* @author sfink
|
||||
|
|
|
@ -41,7 +41,6 @@ public class DelegatingContextSelector implements ContextSelector {
|
|||
}
|
||||
|
||||
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) {
|
||||
|
||||
if (DEBUG) {
|
||||
Trace.println("getCalleeTarget " + caller + " " + site + " " + callee);
|
||||
}
|
||||
|
|
|
@ -853,7 +853,6 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
|
|||
}
|
||||
|
||||
protected void visitGetInternal(int lval, int ref, boolean isStatic, FieldReference field) {
|
||||
|
||||
if (DEBUG) {
|
||||
System.err.println("visitGet " + field);
|
||||
}
|
||||
|
@ -1363,6 +1362,10 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
|
|||
public void visitLoadClass(SSALoadClassInstruction instruction) {
|
||||
PointerKey def = getPointerKeyForLocal(instruction.getDef());
|
||||
InstanceKey iKey = getInstanceKeyForClassObject(instruction.getLoadedClass());
|
||||
IClass klass = getClassHierarchy().lookupClass(instruction.getLoadedClass());
|
||||
if (klass != null) {
|
||||
processClassInitializer(klass);
|
||||
}
|
||||
|
||||
if (!contentsAreInvariant(symbolTable, du, instruction.getDef())) {
|
||||
system.newConstraint(def, iKey);
|
||||
|
|
|
@ -51,6 +51,7 @@ public class ContainerContextSelector implements ContextSelector {
|
|||
|
||||
public final static TypeReference SyntheticSystem = TypeReference.findOrCreate(ClassLoaderReference.Primordial,
|
||||
SyntheticSystemName);
|
||||
public final static TypeReference JavaUtilHashtable = TypeReference.findOrCreate(ClassLoaderReference.Primordial, "Ljava/util/Hashtable");
|
||||
|
||||
public final static Atom arraycopyAtom = Atom.findOrCreateUnicodeAtom("arraycopy");
|
||||
|
||||
|
@ -64,6 +65,7 @@ public class ContainerContextSelector implements ContextSelector {
|
|||
private final static MethodReference ArraysCopyOf = MethodReference.findOrCreate(Arrays, "copyOf", "([Ljava/lang/Object;I)[Ljava/lang/Object;");
|
||||
private final static MethodReference ArraysCopyOf2 = MethodReference.findOrCreate(Arrays, "copyOf", "([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;");
|
||||
private final static MethodReference StringValueOf = MethodReference.findOrCreate(TypeReference.JavaLangString, "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;");
|
||||
private final static MethodReference HashtableNewEntry = MethodReference.findOrCreate(JavaUtilHashtable, "newEntry", "(Ljava/lang/Object;Ljava/lang/Object;I)Ljava/util/Hashtable$Entry;");
|
||||
|
||||
/**
|
||||
* The governing class hierarchy.
|
||||
|
@ -141,6 +143,9 @@ public class ContainerContextSelector implements ContextSelector {
|
|||
if (m.equals(StringValueOf)) {
|
||||
return true;
|
||||
}
|
||||
if (m.equals(HashtableNewEntry)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ package com.ibm.wala.ipa.slicer;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -81,8 +82,6 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
|
||||
private final CGNode node;
|
||||
|
||||
private Map<SSAInstruction, Integer> instructionIndices;
|
||||
|
||||
private Statement[] paramCalleeStatements;
|
||||
|
||||
private Statement[] returnStatements;
|
||||
|
@ -159,18 +158,26 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
this.ignoreAllocHeapDefs = ignoreAllocHeapDefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: Since we're using a {@link HashMap} of {@link SSAInstruction}s, and equals() of {@link SSAInstruction}
|
||||
* assumes a canonical representative for each instruction, we <bf>must</bf> ensure that we use the same IR object
|
||||
* throughout initialization!!
|
||||
*/
|
||||
private void populate() {
|
||||
if (!isPopulated) {
|
||||
// ensure that we keep the single, canonical IR live throughout initialization, while the instructionIndices map is live.
|
||||
IR ir = node.getIR();
|
||||
isPopulated = true;
|
||||
instructionIndices = computeInstructionIndices(node.getIR());
|
||||
createNodes(ref, cOptions);
|
||||
createScalarEdges(cOptions);
|
||||
|
||||
Map<SSAInstruction, Integer> instructionIndices = computeInstructionIndices(ir);
|
||||
createNodes(ref, cOptions, ir);
|
||||
createScalarEdges(cOptions, ir, instructionIndices);
|
||||
}
|
||||
}
|
||||
|
||||
private void createScalarEdges(ControlDependenceOptions cOptions) {
|
||||
createScalarDataDependenceEdges();
|
||||
createControlDependenceEdges(cOptions);
|
||||
private void createScalarEdges(ControlDependenceOptions cOptions, IR ir, Map<SSAInstruction, Integer> instructionIndices) {
|
||||
createScalarDataDependenceEdges(ir, instructionIndices);
|
||||
createControlDependenceEdges(cOptions, ir, instructionIndices);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -198,12 +205,10 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
/**
|
||||
* Create all control dependence edges in this PDG.
|
||||
*/
|
||||
private void createControlDependenceEdges(ControlDependenceOptions cOptions) {
|
||||
private void createControlDependenceEdges(ControlDependenceOptions cOptions, IR ir,Map<SSAInstruction, Integer> instructionIndices) {
|
||||
if (cOptions.equals(ControlDependenceOptions.NONE)) {
|
||||
return;
|
||||
}
|
||||
IR ir;
|
||||
ir = node.getIR();
|
||||
if (ir == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -237,7 +242,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
// should have no control dependent successors.
|
||||
// leave src null.
|
||||
} else {
|
||||
src = ssaInstruction2Statement(s);
|
||||
src = ssaInstruction2Statement(s, ir, instructionIndices);
|
||||
// add edges from call statements to parameter passing and return
|
||||
// SJF: Alexey and I think that we should just define ParamStatements
|
||||
// as
|
||||
|
@ -266,7 +271,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
for (Iterator<? extends IInstruction> it2 = bb2.iterator(); it2.hasNext();) {
|
||||
SSAInstruction st = (SSAInstruction) it2.next();
|
||||
if (st != null) {
|
||||
Statement dest = ssaInstruction2Statement(st);
|
||||
Statement dest = ssaInstruction2Statement(st, ir, instructionIndices);
|
||||
assert src != null;
|
||||
delegate.addEdge(src, dest);
|
||||
}
|
||||
|
@ -284,7 +289,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
// this is control dependent on the method entry.
|
||||
for (IInstruction s : bb) {
|
||||
SSAInstruction st = (SSAInstruction) s;
|
||||
Statement dest = ssaInstruction2Statement(st);
|
||||
Statement dest = ssaInstruction2Statement(st, ir, instructionIndices);
|
||||
delegate.addEdge(methodEntry, dest);
|
||||
}
|
||||
}
|
||||
|
@ -308,17 +313,18 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
* @param pa
|
||||
* @param mod
|
||||
*/
|
||||
private void createScalarDataDependenceEdges() {
|
||||
private void createScalarDataDependenceEdges(IR ir, Map<SSAInstruction, Integer> instructionIndices) {
|
||||
if (dOptions.equals(DataDependenceOptions.NONE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IR ir = node.getIR();
|
||||
if (ir == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DefUse DU = node.getDU();
|
||||
// this is tricky .. I'm explicitly creating a new DefUse to make sure it refers to the instructions we need from
|
||||
// the "one true" ir of the moment.
|
||||
DefUse DU = new DefUse(ir);
|
||||
SSAInstruction[] instructions = ir.getInstructions();
|
||||
|
||||
//
|
||||
|
@ -331,7 +337,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
SSACFG.ExceptionHandlerBasicBlock ehbb = (SSACFG.ExceptionHandlerBasicBlock) bb;
|
||||
|
||||
if (ehbb.getCatchInstruction() != null) {
|
||||
Statement c = ssaInstruction2Statement(ehbb.getCatchInstruction());
|
||||
Statement c = ssaInstruction2Statement(ehbb.getCatchInstruction(), ir, instructionIndices);
|
||||
|
||||
for (ISSABasicBlock pb : ir.getControlFlowGraph().getExceptionalPredecessors(ehbb)) {
|
||||
SSAInstruction pi = instructions[pb.getLastInstructionIndex()];
|
||||
|
@ -340,7 +346,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
if (pi instanceof SSAAbstractInvokeInstruction) {
|
||||
delegate.addEdge(new ExceptionalReturnCaller(node, pb.getLastInstructionIndex()), c);
|
||||
} else if (pi instanceof SSAAbstractThrowInstruction) {
|
||||
delegate.addEdge(ssaInstruction2Statement(pi), c);
|
||||
delegate.addEdge(ssaInstruction2Statement(pi, ir, instructionIndices), c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +397,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Statement u = ssaInstruction2Statement(use);
|
||||
Statement u = ssaInstruction2Statement(use, ir, instructionIndices);
|
||||
delegate.addEdge(s, u);
|
||||
}
|
||||
}
|
||||
|
@ -427,7 +433,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
}
|
||||
}
|
||||
}
|
||||
Statement u = ssaInstruction2Statement(use);
|
||||
Statement u = ssaInstruction2Statement(use, ir, instructionIndices);
|
||||
delegate.addEdge(s, u);
|
||||
}
|
||||
break;
|
||||
|
@ -482,7 +488,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
delegate.addEdge(st, pac);
|
||||
}
|
||||
} else {
|
||||
Statement ds = ssaInstruction2Statement(d);
|
||||
Statement ds = ssaInstruction2Statement(d, ir, instructionIndices);
|
||||
delegate.addEdge(ds, pac);
|
||||
}
|
||||
}
|
||||
|
@ -578,6 +584,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
return;
|
||||
}
|
||||
|
||||
// It's OK to create a new IR here; we're not keeping any hashing live up to this point
|
||||
IR ir = node.getIR();
|
||||
if (ir == null) {
|
||||
return;
|
||||
|
@ -710,14 +717,16 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Wrap an SSAInstruction in a Statement
|
||||
* Wrap an {@link SSAInstruction} in a {@link Statement}. WARNING: Since we're using a {@link HashMap} of
|
||||
* {@link SSAInstruction}s, and equals() of {@link SSAInstruction} assumes a canonical representative for each
|
||||
* instruction, we <bf>must</bf> ensure that we use the same IR object throughout initialization!!
|
||||
*/
|
||||
private Statement ssaInstruction2Statement(SSAInstruction s) {
|
||||
return ssaInstruction2Statement(node, s, instructionIndices);
|
||||
private Statement ssaInstruction2Statement(SSAInstruction s, IR ir, Map<SSAInstruction, Integer> instructionIndices) {
|
||||
return ssaInstruction2Statement(node, s, instructionIndices, ir);
|
||||
}
|
||||
|
||||
public static synchronized Statement ssaInstruction2Statement(CGNode node, SSAInstruction s,
|
||||
Map<SSAInstruction, Integer> instructionIndices) {
|
||||
Map<SSAInstruction, Integer> instructionIndices, IR ir) {
|
||||
assert s != null;
|
||||
if (s instanceof SSAPhiInstruction) {
|
||||
SSAPhiInstruction phi = (SSAPhiInstruction) s;
|
||||
|
@ -730,7 +739,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
} else {
|
||||
Integer x = instructionIndices.get(s);
|
||||
if (x == null) {
|
||||
Assertions.UNREACHABLE(s.toString() + "\nnot found in map of\n" + node.getIR());
|
||||
Assertions.UNREACHABLE(s.toString() + "\nnot found in map of\n" + ir);
|
||||
}
|
||||
return new NormalStatement(node, x.intValue());
|
||||
}
|
||||
|
@ -783,11 +792,8 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
|
||||
/**
|
||||
* Create all nodes in this PDG. Each node is a Statement.
|
||||
*
|
||||
* @param dOptions
|
||||
*/
|
||||
private void createNodes(Map<CGNode, OrdinalSet<PointerKey>> ref, ControlDependenceOptions cOptions) {
|
||||
IR ir = node.getIR();
|
||||
private void createNodes(Map<CGNode, OrdinalSet<PointerKey>> ref, ControlDependenceOptions cOptions, IR ir) {
|
||||
|
||||
if (ir != null) {
|
||||
Collection<SSAInstruction> visited = createNormalStatements(ir, ref);
|
||||
|
@ -900,7 +906,7 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
visited.add(s);
|
||||
}
|
||||
if (s instanceof SSAAbstractInvokeInstruction) {
|
||||
addParamPassingStatements(i, ref);
|
||||
addParamPassingStatements(i, ref, ir);
|
||||
}
|
||||
}
|
||||
return visited;
|
||||
|
@ -909,9 +915,8 @@ public class PDG implements NumberedGraph<Statement> {
|
|||
/**
|
||||
* Create nodes in the graph corresponding to in/out parameter passing for a call instruction
|
||||
*/
|
||||
private void addParamPassingStatements(int callIndex, Map<CGNode, OrdinalSet<PointerKey>> ref) {
|
||||
|
||||
SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) node.getIR().getInstructions()[callIndex];
|
||||
private void addParamPassingStatements(int callIndex, Map<CGNode, OrdinalSet<PointerKey>> ref, IR ir) {
|
||||
SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) ir.getInstructions()[callIndex];
|
||||
Collection<Statement> params = MapUtil.findOrCreateSet(callerParamStatements, call.getCallSite());
|
||||
Collection<Statement> rets = MapUtil.findOrCreateSet(callerReturnStatements, call.getCallSite());
|
||||
for (int j = 0; j < call.getNumberOfUses(); j++) {
|
||||
|
|
Loading…
Reference in New Issue