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 @Override
public ClassLoaderReference getSyntheticLoader() { public ClassLoaderReference getSyntheticLoader() {
Assertions.UNREACHABLE();
return null; return null;
} }

View File

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

View File

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

View File

@ -86,7 +86,7 @@ public class DefaultMethodsTest extends WalaTestCase {
TypeReference test1Type = TypeReference.findOrCreate(ClassLoaderReference.Application, "LdefaultMethods/DefaultMethods$Test1"); TypeReference test1Type = TypeReference.findOrCreate(ClassLoaderReference.Application, "LdefaultMethods/DefaultMethods$Test1");
IClass test1Class = cha.lookupClass(test1Type); IClass test1Class = cha.lookupClass(test1Type);
Collection<IMethod> allMethods = test1Class.getAllMethods(); Collection<? extends IMethod> allMethods = test1Class.getAllMethods();
IMethod defaultMethod = test1Class.getMethod(t1m.getSelector()); IMethod defaultMethod = test1Class.getMethod(t1m.getSelector());
Assert.assertTrue("Expecting default methods to show up in IClass.allMethods()", allMethods.contains(defaultMethod)); 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) { private static Collection<IMethod> getAllNormalPublicMethods(IClass cls,Atom name) {
Collection<IMethod> result = HashSetFactory.make(); Collection<IMethod> result = HashSetFactory.make();
Collection<IMethod> allMethods = null; Collection<? extends IMethod> allMethods = null;
allMethods = cls.getAllMethods(); allMethods = cls.getAllMethods();
for (IMethod m : allMethods) { for (IMethod m : allMethods) {
if (!m.isInit() && !m.isClinit() && m.isPublic() && m.getSelector().getName().equals(name)) { 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) { private static Collection<IMethod> getAllNormalPublicMethods(IClass cls) {
Collection<IMethod> result = HashSetFactory.make(); Collection<IMethod> result = HashSetFactory.make();
Collection<IMethod> allMethods = null; Collection<? extends IMethod> allMethods = null;
allMethods = cls.getAllMethods(); allMethods = cls.getAllMethods();
for (IMethod m : allMethods) { for (IMethod m : allMethods) {
if (!m.isInit() && !m.isClinit() && m.isPublic()) { 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() * @see com.ibm.wala.classLoader.IClass#getAllMethods()
*/ */
@Override @Override
public Collection<IMethod> getAllMethods() { public Collection<? extends IMethod> getAllMethods() {
return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName()).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(); IClass s = getSuperclass();
while (s != null) { while (s != null) {
Iterator<IMethod> superDeclaredMethods = s.getDeclaredMethods().iterator(); Iterator<? extends IMethod> superDeclaredMethods = s.getDeclaredMethods().iterator();
while (superDeclaredMethods.hasNext()) { while (superDeclaredMethods.hasNext()) {
result.add(superDeclaredMethods.next()); 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. * @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. * 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. * 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. * Compute the instance fields declared by this class.

View File

@ -16,7 +16,6 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
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.TypeName; import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference; import com.ibm.wala.types.TypeReference;
import com.ibm.wala.types.annotations.Annotation; import com.ibm.wala.types.annotations.Annotation;
@ -77,7 +76,7 @@ public abstract class SyntheticClass implements IClass {
*/ */
@Override @Override
public IClassLoader getClassLoader() { 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, IMethod target = (chaTarget == null) ? findOrCreateSyntheticMethod(ref, site.isStatic()) : findOrCreateSyntheticMethod(chaTarget,
site.isStatic()); 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) { if (DEBUG) {
System.err.println("target is initially " + target); 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() * @see com.ibm.wala.classLoader.IClass#getDeclaredMethods()
*/ */
@Override @Override
public Collection<IMethod> getDeclaredMethods() { public Collection<? extends IMethod> getDeclaredMethods() {
return realType.getDeclaredMethods(); return realType.getDeclaredMethods();
} }
@ -236,7 +236,7 @@ public class BypassSyntheticClass extends SyntheticClass {
* @see com.ibm.wala.classLoader.IClass#getAllMethods() * @see com.ibm.wala.classLoader.IClass#getAllMethods()
*/ */
@Override @Override
public Collection<IMethod> getAllMethods() { public Collection<? extends IMethod> getAllMethods() {
return realType.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, * 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 * 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. * be very bad to use an existing name for a new synthetic class.
* *
* Class lookup works just as for any other classloader. * Class lookup works just as for any other classloader.
@ -148,7 +148,7 @@ public class BypassSyntheticClassLoader implements IClassLoader {
*/ */
@Override @Override
public Language getLanguage() { public Language getLanguage() {
return Language.JAVA; return parent.getLanguage();
} }
/* /*

View File

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

View File

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

View File

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