more work for reuse

make synthetic code better support non-Java languages
This commit is contained in:
Julian Dolby 2018-02-14 09:00:07 -05:00
parent 81a6e67b4b
commit 6c1d0d9cb6
17 changed files with 84 additions and 27 deletions

View File

@ -94,7 +94,6 @@ public class CAstAnalysisScope extends AnalysisScope {
*/
@Override
public ClassLoaderReference getSyntheticLoader() {
Assertions.UNREACHABLE();
return null;
}

View File

@ -176,7 +176,7 @@ abstract public class AstClass implements IClass, ClassConstants {
return getField(name);
}
@Override
public Collection<IMethod> getDeclaredMethods() {
public Collection<? extends IMethod> getDeclaredMethods() {
return declaredMethods.values();
}
@ -235,7 +235,7 @@ abstract public class AstClass implements IClass, ClassConstants {
}
@Override
public Collection<IMethod> getAllMethods() {
public Collection<? extends IMethod> getAllMethods() {
Collection<IMethod> result = HashSetFactory.make();
for (IMethod iMethod : getDeclaredMethods()) {
result.add(iMethod);

View File

@ -88,4 +88,45 @@ public class AstDynamicField implements IField {
public Collection<Annotation> getAnnotations() {
return Collections.emptySet();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((cls == null) ? 0 : cls.hashCode());
result = prime * result + ((descriptor == null) ? 0 : descriptor.hashCode());
result = prime * result + (isStatic ? 1231 : 1237);
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AstDynamicField other = (AstDynamicField) obj;
if (cls == null) {
if (other.cls != null)
return false;
} else if (!cls.equals(other.cls))
return false;
if (descriptor == null) {
if (other.descriptor != null)
return false;
} else if (!descriptor.equals(other.descriptor))
return false;
if (isStatic != other.isStatic)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}

View File

@ -14,6 +14,7 @@ import com.ibm.wala.classLoader.ClassLoaderFactory;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ipa.summaries.BypassSyntheticClassLoader;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.debug.Assertions;
@ -28,8 +29,13 @@ public abstract class SingleClassLoaderFactory implements ClassLoaderFactory {
*/
private IClassLoader THE_LOADER = null;
/**
* Support synthetic classes
*/
private IClassLoader syntheticLoader;
@Override
public IClassLoader getLoader(ClassLoaderReference classLoaderReference, IClassHierarchy cha, AnalysisScope scope) {
public IClassLoader getLoader(ClassLoaderReference classLoaderReference, IClassHierarchy cha, AnalysisScope scope) {
if (THE_LOADER == null) {
THE_LOADER = makeTheLoader(cha);
try {
@ -39,9 +45,14 @@ public abstract class SingleClassLoaderFactory implements ClassLoaderFactory {
}
}
assert classLoaderReference.equals(getTheReference());
return THE_LOADER;
if (classLoaderReference.equals(scope.getSyntheticLoader())) {
syntheticLoader = new BypassSyntheticClassLoader(scope.getSyntheticLoader(), THE_LOADER, scope.getExclusions(), cha);
return syntheticLoader;
} else {
assert classLoaderReference.equals(getTheReference());
return THE_LOADER;
}
}
public IClassLoader getTheLoader() {

View File

@ -86,7 +86,7 @@ public class DefaultMethodsTest extends WalaTestCase {
TypeReference test1Type = TypeReference.findOrCreate(ClassLoaderReference.Application, "LdefaultMethods/DefaultMethods$Test1");
IClass test1Class = cha.lookupClass(test1Type);
Collection<IMethod> allMethods = test1Class.getAllMethods();
Collection<? extends IMethod> allMethods = test1Class.getAllMethods();
IMethod defaultMethod = test1Class.getMethod(t1m.getSelector());
Assert.assertTrue("Expecting default methods to show up in IClass.allMethods()", allMethods.contains(defaultMethod));
}

View File

@ -168,7 +168,7 @@ public class GetMethodContextInterpreter implements SSAContextInterpreter {
*/
private static Collection<IMethod> getAllNormalPublicMethods(IClass cls,Atom name) {
Collection<IMethod> result = HashSetFactory.make();
Collection<IMethod> allMethods = null;
Collection<? extends IMethod> allMethods = null;
allMethods = cls.getAllMethods();
for (IMethod m : allMethods) {
if (!m.isInit() && !m.isClinit() && m.isPublic() && m.getSelector().getName().equals(name)) {

View File

@ -239,7 +239,7 @@ public class JavaLangClassContextInterpreter implements SSAContextInterpreter {
*/
private static Collection<IMethod> getAllNormalPublicMethods(IClass cls) {
Collection<IMethod> result = HashSetFactory.make();
Collection<IMethod> allMethods = null;
Collection<? extends IMethod> allMethods = null;
allMethods = cls.getAllMethods();
for (IMethod m : allMethods) {
if (!m.isInit() && !m.isClinit() && m.isPublic()) {

View File

@ -343,7 +343,7 @@ public class ArrayClass implements IClass, Constants {
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
*/
@Override
public Collection<IMethod> getAllMethods() {
public Collection<? extends IMethod> getAllMethods() {
return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName()).getAllMethods();
}

View File

@ -405,7 +405,7 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
}
IClass s = getSuperclass();
while (s != null) {
Iterator<IMethod> superDeclaredMethods = s.getDeclaredMethods().iterator();
Iterator<? extends IMethod> superDeclaredMethods = s.getDeclaredMethods().iterator();
while (superDeclaredMethods.hasNext()) {
result.add(superDeclaredMethods.next());
}

View File

@ -135,7 +135,7 @@ public interface IClass extends IClassHierarchyDweller {
/**
* @return an Iterator of the IMethods declared by this class.
*/
Collection<IMethod> getDeclaredMethods();
Collection<? extends IMethod> getDeclaredMethods();
/**
* Compute the instance fields declared by this class or any of its superclasses.
@ -155,7 +155,7 @@ public interface IClass extends IClassHierarchyDweller {
/**
* Compute the methods declared by this class or any of its superclasses.
*/
Collection<IMethod> getAllMethods();
Collection<? extends IMethod> getAllMethods();
/**
* Compute the instance fields declared by this class.

View File

@ -16,7 +16,6 @@ import java.util.Collection;
import java.util.Collections;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.types.annotations.Annotation;
@ -77,7 +76,7 @@ public abstract class SyntheticClass implements IClass {
*/
@Override
public IClassLoader getClassLoader() {
return cha.getLoader(ClassLoaderReference.Primordial);
return cha.getLoader(T.getClassLoader());
}
/*

View File

@ -112,7 +112,14 @@ public class BypassMethodTargetSelector implements MethodTargetSelector {
IMethod target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget,
site.isStatic());
// try synthetic method that matches receiver type
if (dispatchType != null) {
ref = MethodReference.findOrCreate(dispatchType.getReference(), ref.getSelector());
chaTarget = chaMethodTargetSelector.getCalleeTarget(caller, site, dispatchType);
target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget,
site.isStatic());
}
if (DEBUG) {
System.err.println("target is initially " + target);
}

View File

@ -137,7 +137,7 @@ public class BypassSyntheticClass extends SyntheticClass {
* @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
*/
@Override
public Collection<IMethod> getDeclaredMethods() {
public Collection<? extends IMethod> getDeclaredMethods() {
return realType.getDeclaredMethods();
}
@ -236,7 +236,7 @@ public class BypassSyntheticClass extends SyntheticClass {
* @see com.ibm.wala.classLoader.IClass#getAllMethods()
*/
@Override
public Collection<IMethod> getAllMethods() {
public Collection<? extends IMethod> getAllMethods() {
return realType.getAllMethods();
}

View File

@ -50,7 +50,7 @@ import com.ibm.wala.util.strings.Atom;
*
* Code that wants to introduce synthetic classes uses the registerClass method,
* giving it an Atom which is the class name, and an IClass which is the class
* to load. Since the synthetic loader musat be a child of the others, it would
* to load. Since the synthetic loader must be a child of the others, it would
* be very bad to use an existing name for a new synthetic class.
*
* Class lookup works just as for any other classloader.
@ -148,7 +148,7 @@ public class BypassSyntheticClassLoader implements IClassLoader {
*/
@Override
public Language getLanguage() {
return Language.JAVA;
return parent.getLanguage();
}
/*

View File

@ -54,8 +54,8 @@ public class JUnitEntryPoints {
System.out.println("application class: " + klass);
// return all the tests methods
Collection<IMethod> methods = klass.getAllMethods();
Iterator<IMethod> methodsIt = methods.iterator();
Collection<? extends IMethod> methods = klass.getAllMethods();
Iterator<? extends IMethod> methodsIt = methods.iterator();
while (methodsIt.hasNext()) {
IMethod m = methodsIt.next();

View File

@ -248,7 +248,7 @@ nextMethod:
// Don't consider internal overrides
continue;
}
final Collection<IMethod> methods = candid.getDeclaredMethods();
final Collection<? extends IMethod> methods = candid.getDeclaredMethods();
for (final IMethod method : methods) {
@ -329,7 +329,7 @@ nextMethod:
{ // Overridden methods
if (isAPIComponent(appClass)) continue;
if (isExcluded(appClass)) continue;
final Collection<IMethod> methods = appClass.getDeclaredMethods();
final Collection<? extends IMethod> methods = appClass.getDeclaredMethods();
for (final IMethod method : methods) {
if ((method.isInit() || method.isClinit()) && (! this.flags.contains(LocatorFlags.WITH_CTOR))) {
logger.debug("Skipping constructor of {}", method);
@ -359,7 +359,7 @@ nextMethod:
}
if (isExcluded(iFace)) continue;
logger.debug("Searching Interface {}", iFace);
final Collection<IMethod> ifMethods = iFace.getDeclaredMethods();
final Collection<? extends IMethod> ifMethods = iFace.getDeclaredMethods();
for (final IMethod ifMethod : ifMethods) {
final IMethod method = appClass.getMethod(ifMethod.getSelector());
if (method != null && method.getDeclaringClass().getClassLoader().getReference().equals(ClassLoaderReference.Application)) {

View File

@ -85,7 +85,7 @@ public class MethodNamePattern {
Collection<IMethod> matching = new LinkedList<>();
Atom atom = Atom.findOrCreateUnicodeAtom(memberName);
Descriptor desc = descriptor == null ? null : Descriptor.findOrCreateUTF8(descriptor);
Collection<IMethod> allMethods = c.getAllMethods();
Collection<? extends IMethod> allMethods = c.getAllMethods();
for(IMethod m: allMethods) {
if(m.getName().equals(atom) && (desc == null || m.getDescriptor().equals(desc))) {
matching.add(m);