tweak call-string policy for well-known factory methods
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2283 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
aeadf8a6b7
commit
b18f82cd24
|
@ -23,24 +23,24 @@ import com.ibm.wala.ipa.callgraph.propagation.ReceiverInstanceContext;
|
||||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||||
import com.ibm.wala.types.ClassLoaderReference;
|
import com.ibm.wala.types.ClassLoaderReference;
|
||||||
import com.ibm.wala.types.Descriptor;
|
import com.ibm.wala.types.Descriptor;
|
||||||
import com.ibm.wala.types.MemberReference;
|
|
||||||
import com.ibm.wala.types.MethodReference;
|
import com.ibm.wala.types.MethodReference;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.util.Atom;
|
import com.ibm.wala.util.Atom;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
import com.ibm.wala.util.debug.Trace;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* This context selector returns a context customized for the instancekey of the
|
* This context selector returns a context customized for the {@link InstanceKey} of the receiver if
|
||||||
* receiver if
|
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>receiver is a container, or</li>
|
* <li>receiver is a container, or </li>
|
||||||
* was allocated in a node whose context was a ReceiverInstanceContext, and the
|
* was allocated in a node whose context was a {@link ReceiverInstanceContext}, and the type is interesting according
|
||||||
* type is interesting according to a delegate instance key selector
|
* to a delegate {@link ZeroXInstanceKeys}
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* Additionally, we add one level of call string context to a few well-known static factory methods from the standard
|
||||||
|
* libraries.
|
||||||
|
*
|
||||||
* @author sfink
|
* @author sfink
|
||||||
*/
|
*/
|
||||||
public class ContainerContextSelector implements ContextSelector {
|
public class ContainerContextSelector implements ContextSelector {
|
||||||
|
@ -48,18 +48,18 @@ public class ContainerContextSelector implements ContextSelector {
|
||||||
private final static boolean DEBUG = false;
|
private final static boolean DEBUG = false;
|
||||||
|
|
||||||
private final static TypeName SyntheticSystemName = TypeName.string2TypeName("Lcom/ibm/wala/model/java/lang/System");
|
private final static TypeName SyntheticSystemName = TypeName.string2TypeName("Lcom/ibm/wala/model/java/lang/System");
|
||||||
private final static TypeName JavaLangSystemName = TypeName.string2TypeName("Ljava/lang/System");
|
|
||||||
|
|
||||||
public final static TypeReference SyntheticSystem = TypeReference.findOrCreate(ClassLoaderReference.Primordial,
|
public final static TypeReference SyntheticSystem = TypeReference.findOrCreate(ClassLoaderReference.Primordial,
|
||||||
SyntheticSystemName);
|
SyntheticSystemName);
|
||||||
public final static TypeReference JavaLangSystem = TypeReference.findOrCreate(ClassLoaderReference.Primordial,
|
|
||||||
JavaLangSystemName);
|
|
||||||
|
|
||||||
public final static Atom arraycopyAtom = Atom.findOrCreateUnicodeAtom("arraycopy");
|
public final static Atom arraycopyAtom = Atom.findOrCreateUnicodeAtom("arraycopy");
|
||||||
|
|
||||||
private final static Descriptor arraycopyDesc = Descriptor.findOrCreateUTF8("(Ljava/lang/Object;Ljava/lang/Object;)V");
|
private final static Descriptor arraycopyDesc = Descriptor.findOrCreateUTF8("(Ljava/lang/Object;Ljava/lang/Object;)V");
|
||||||
|
|
||||||
public final static MemberReference synthArraycopy = MethodReference.findOrCreate(SyntheticSystem, arraycopyAtom, arraycopyDesc);
|
public final static MethodReference synthArraycopy = MethodReference.findOrCreate(SyntheticSystem, arraycopyAtom, arraycopyDesc);
|
||||||
|
|
||||||
|
private final static TypeReference Arrays = TypeReference.findOrCreate(ClassLoaderReference.Primordial, "Ljava/util/Arrays");
|
||||||
|
private final static MethodReference ArraysAsList = MethodReference.findOrCreate(Arrays, "asList", "([Ljava/lang/Object;)Ljava/util/List;");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The governing class hierarchy.
|
* The governing class hierarchy.
|
||||||
|
@ -72,8 +72,8 @@ public class ContainerContextSelector implements ContextSelector {
|
||||||
private final ZeroXInstanceKeys delegate;
|
private final ZeroXInstanceKeys delegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param cha
|
* @param cha governing class hierarchy
|
||||||
* @param delegate
|
* @param delegate object which determines which classes are "interesting"
|
||||||
*/
|
*/
|
||||||
public ContainerContextSelector(IClassHierarchy cha, ZeroXInstanceKeys delegate) {
|
public ContainerContextSelector(IClassHierarchy cha, ZeroXInstanceKeys delegate) {
|
||||||
this.cha = cha;
|
this.cha = cha;
|
||||||
|
@ -83,16 +83,18 @@ public class ContainerContextSelector implements ContextSelector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see com.ibm.wala.ipa.callgraph.ContextSelector#getCalleeTarget(com.ibm.wala.ipa.callgraph.CGNode, com.ibm.wala.classLoader.CallSiteReference, com.ibm.wala.classLoader.IMethod, com.ibm.wala.ipa.callgraph.propagation.InstanceKey)
|
||||||
|
*/
|
||||||
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) {
|
public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey receiver) {
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Trace.println("ContainerContextSelector: getCalleeTarget " + callee);
|
System.err.println("ContainerContextSelector: getCalleeTarget " + callee);
|
||||||
}
|
}
|
||||||
if (mayUnderstand(caller, site, callee, receiver)) {
|
if (mayUnderstand(caller, site, callee, receiver)) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Trace.println("May Understand: " + callee + " recv " + receiver);
|
System.err.println("May Understand: " + callee + " recv " + receiver);
|
||||||
}
|
}
|
||||||
if (isArrayCopy(callee.getReference())) {
|
if (isWellKnownStaticFactory(callee.getReference())) {
|
||||||
return new CallerSiteContext(caller, site);
|
return new CallerSiteContext(caller, site);
|
||||||
} else {
|
} else {
|
||||||
if (Assertions.verifyAssertions) {
|
if (Assertions.verifyAssertions) {
|
||||||
|
@ -107,28 +109,25 @@ public class ContainerContextSelector implements ContextSelector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isArrayCopy(MemberReference m) {
|
private static boolean isWellKnownStaticFactory(MethodReference m) {
|
||||||
if (m == null) {
|
if (m.equals(synthArraycopy)) {
|
||||||
throw new IllegalArgumentException("m is null");
|
return true;
|
||||||
}
|
}
|
||||||
if (m.getDeclaringClass().equals(JavaLangSystem)) {
|
if (m.equals(ArraysAsList)) {
|
||||||
if (m.getName().equals(arraycopyAtom)) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return m.equals(synthArraycopy);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method walks recursively up the definition of a context C, to see if
|
* This method walks recursively up the definition of a context C, to see if the chain of contexts that give rise to C
|
||||||
* the chain of contexts that give rise to C a) includes the method M. or b)
|
* a) includes the method M. or b) includes the method in which the receiver was allocated
|
||||||
* includes the method in which the receiver was allocated
|
|
||||||
*
|
*
|
||||||
* @return the matching context if found, null otherwise
|
* @return the matching context if found, null otherwise
|
||||||
*/
|
*/
|
||||||
public static Context findRecursiveMatchingContext(IMethod M, Context C, InstanceKey receiver) {
|
public static Context findRecursiveMatchingContext(IMethod M, Context C, InstanceKey receiver) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Trace.println("findRecursiveMatchingContext for " + M + " in context " + C + " receiver " + receiver);
|
System.err.println("findRecursiveMatchingContext for " + M + " in context " + C + " receiver " + receiver);
|
||||||
}
|
}
|
||||||
Context result = findRecursiveMatchingContext(M, C);
|
Context result = findRecursiveMatchingContext(M, C);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
|
@ -145,16 +144,15 @@ public class ContainerContextSelector implements ContextSelector {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method walks recursively up the definition of a context C, to see if
|
* This method walks recursively up the definition of a context C, to see if the chain of contexts that give rise to C
|
||||||
* the chain of contexts that give rise to C includes the method M.
|
* includes the method M.
|
||||||
*
|
*
|
||||||
* If C is a ReceiverInstanceContext, Let N be the node that allocated
|
* If C is a ReceiverInstanceContext, Let N be the node that allocated C.instance. If N.method == M, return N. Else
|
||||||
* C.instance. If N.method == M, return N. Else return
|
* return findRecursiveMatchingContext(M, N.context) Else return null
|
||||||
* findRecursiveMatchingContext(M, N.context) Else return null
|
|
||||||
*/
|
*/
|
||||||
public static CGNode findNodeRecursiveMatchingContext(IMethod M, Context C) {
|
public static CGNode findNodeRecursiveMatchingContext(IMethod M, Context C) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Trace.println("findNodeRecursiveMatchingContext " + M + " in context " + C);
|
System.err.println("findNodeRecursiveMatchingContext " + M + " in context " + C);
|
||||||
}
|
}
|
||||||
if (C instanceof ReceiverInstanceContext) {
|
if (C instanceof ReceiverInstanceContext) {
|
||||||
ReceiverInstanceContext ric = (ReceiverInstanceContext) C;
|
ReceiverInstanceContext ric = (ReceiverInstanceContext) C;
|
||||||
|
@ -174,12 +172,11 @@ public class ContainerContextSelector implements ContextSelector {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method walks recursively up the definition of a context C, to see if
|
* This method walks recursively up the definition of a context C, to see if the chain of contexts that give rise to C
|
||||||
* the chain of contexts that give rise to C includes the method M.
|
* includes the method M.
|
||||||
*
|
*
|
||||||
* If C is a ReceiverInstanceContext, Let N be the node that allocated
|
* If C is a ReceiverInstanceContext, Let N be the node that allocated C.instance. If N.method == M, return N.context.
|
||||||
* C.instance. If N.method == M, return N.context. Else return
|
* Else return findRecursiveMatchingContext(M, N.context) Else return null
|
||||||
* findRecursiveMatchingContext(M, N.context) Else return null
|
|
||||||
*/
|
*/
|
||||||
public static Context findRecursiveMatchingContext(IMethod M, Context C) {
|
public static Context findRecursiveMatchingContext(IMethod M, Context C) {
|
||||||
CGNode n = findNodeRecursiveMatchingContext(M, C);
|
CGNode n = findNodeRecursiveMatchingContext(M, C);
|
||||||
|
@ -196,7 +193,7 @@ public class ContainerContextSelector implements ContextSelector {
|
||||||
if (targetMethod == null) {
|
if (targetMethod == null) {
|
||||||
throw new IllegalArgumentException("targetMethod is null");
|
throw new IllegalArgumentException("targetMethod is null");
|
||||||
}
|
}
|
||||||
if (isArrayCopy(targetMethod.getReference())) {
|
if (isWellKnownStaticFactory(targetMethod.getReference())) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (site.isStatic()) {
|
if (site.isStatic()) {
|
||||||
|
@ -249,12 +246,11 @@ public class ContainerContextSelector implements ContextSelector {
|
||||||
*/
|
*/
|
||||||
protected boolean isContainer(IClass C) {
|
protected boolean isContainer(IClass C) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Trace.println("isContainer? " + C + " " + ContainerUtil.isContainer(C, cha));
|
System.err.println("isContainer? " + C + " " + ContainerUtil.isContainer(C, cha));
|
||||||
}
|
}
|
||||||
return ContainerUtil.isContainer(C, cha);
|
return ContainerUtil.isContainer(C, cha);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean contextIsIrrelevant(CGNode node, CallSiteReference site) {
|
public boolean contextIsIrrelevant(CGNode node, CallSiteReference site) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue