Nuke ClassHierarchyException from IClass.getSuperclass()

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3539 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
sjfink 2009-04-28 19:52:34 +00:00
parent 50e093779a
commit 829145e97b
18 changed files with 252 additions and 369 deletions

View File

@ -519,7 +519,7 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
}
@Override
public IClass getSuperclass() throws ClassHierarchyException {
public IClass getSuperclass() {
return superClass;
}
}
@ -544,7 +544,7 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
return Collections.emptySet();
}
public IClass getSuperclass() throws ClassHierarchyException {
public IClass getSuperclass() {
return null;
}
}

View File

@ -22,7 +22,6 @@ import com.ibm.wala.core.tests.util.WalaTestCase;
import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.impl.Everywhere;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ssa.IRFactory;
import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.util.collections.HashMapFactory;
@ -120,8 +119,7 @@ public abstract class TestCAstTranslator extends WalaTestCase {
public ClassHierarchy runTranslator(SourceFileModule[] fileNames) throws Exception {
SingleClassLoaderFactory loaders = getClassLoaderFactory();
AnalysisScope scope =
Util.makeScope(fileNames, loaders, getLanguage());
AnalysisScope scope = Util.makeScope(fileNames, loaders, getLanguage());
ClassHierarchy cha = ClassHierarchy.make(scope, loaders, getLanguage());
@ -144,8 +142,7 @@ public abstract class TestCAstTranslator extends WalaTestCase {
IMethod mth = (IMethod) mths.next();
if (mth.isStatic())
System.err.print("static ");
System.err.println(("method " + mth + " with " +
mth.getNumberOfParameters() + " parameters"));
System.err.println(("method " + mth + " with " + mth.getNumberOfParameters() + " parameters"));
for (int i = 0; i < mth.getNumberOfParameters(); i++) {
System.err.println(("param " + i + ": " + mth.getParameterType(i)));
}
@ -168,15 +165,11 @@ public abstract class TestCAstTranslator extends WalaTestCase {
clsCount++;
Assert.assertTrue("found class " + cls.getName().toString(), classes.contains(cls.getName().toString()));
try {
if (cls.getSuperclass() == null) {
Assert.assertTrue(cls.getName() + " has no superclass", supers.get(cls.getName()) == null);
} else {
Assert.assertTrue("super of " + cls.getName() + " is " + cls.getSuperclass().getName(), supers.get(
cls.getName().toString()).equals(cls.getSuperclass().getName().toString()));
}
} catch (ClassHierarchyException e) {
Assert.assertTrue(false);
if (cls.getSuperclass() == null) {
Assert.assertTrue(cls.getName() + " has no superclass", supers.get(cls.getName()) == null);
} else {
Assert.assertTrue("super of " + cls.getName() + " is " + cls.getSuperclass().getName(), supers
.get(cls.getName().toString()).equals(cls.getSuperclass().getName().toString()));
}
for (Iterator<?> flds = cls.getDeclaredInstanceFields().iterator(); flds.hasNext();) {

View File

@ -29,7 +29,6 @@ import com.ibm.wala.types.Selector;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
abstract public class AstClass implements IClass, ClassConstants {
@ -66,7 +65,7 @@ abstract public class AstClass implements IClass, ClassConstants {
public boolean isPublic() {
return (modifiers & ACC_PUBLIC) != 0;
}
public boolean isReferenceType() {
return true;
}
@ -90,7 +89,7 @@ abstract public class AstClass implements IClass, ClassConstants {
public String getSourceFileName() {
return sourcePosition.getURL().getFile();
}
public InputStream getSource() {
return null;
}
@ -107,13 +106,14 @@ abstract public class AstClass implements IClass, ClassConstants {
return loader;
}
public abstract IClass getSuperclass() throws ClassHierarchyException;
public abstract IClass getSuperclass();
private Collection<IClass> gatherInterfaces() throws ClassHierarchyException {
Set<IClass> result = HashSetFactory.make();
result.addAll(getDirectInterfaces());
if (getSuperclass() != null)
if (getSuperclass() != null) {
result.addAll(getSuperclass().getAllImplementedInterfaces());
}
return result;
}
@ -128,31 +128,21 @@ abstract public class AstClass implements IClass, ClassConstants {
}
public IMethod getMethod(Selector selector) {
try {
if (declaredMethods.containsKey(selector)) {
return declaredMethods.get(selector);
} else if (getSuperclass() != null) {
return getSuperclass().getMethod(selector);
} else {
return null;
}
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
if (declaredMethods.containsKey(selector)) {
return declaredMethods.get(selector);
} else if (getSuperclass() != null) {
return getSuperclass().getMethod(selector);
} else {
return null;
}
}
public IField getField(Atom name) {
try {
if (declaredFields.containsKey(name)) {
return declaredFields.get(name);
} else if (getSuperclass() != null) {
return getSuperclass().getField(name);
} else {
return null;
}
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
if (declaredFields.containsKey(name)) {
return declaredFields.get(name);
} else if (getSuperclass() != null) {
return getSuperclass().getField(name);
} else {
return null;
}
}

View File

@ -18,13 +18,11 @@ import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.Selector;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
public abstract class AstDynamicPropertyClass extends AstClass {
@ -37,69 +35,65 @@ public abstract class AstDynamicPropertyClass extends AstClass {
}
public IField getField(final Atom name) {
try {
if (declaredFields.containsKey(name)) {
return declaredFields.get(name);
} else if (getSuperclass() != null) {
return getSuperclass().getField(name);
} else {
final boolean isStatic = isStaticField(name);
declaredFields.put(name, new IField() {
public String toString() {
return "<field " + name + ">";
}
if (declaredFields.containsKey(name)) {
return declaredFields.get(name);
} else if (getSuperclass() != null) {
return getSuperclass().getField(name);
} else {
final boolean isStatic = isStaticField(name);
declaredFields.put(name, new IField() {
public String toString() {
return "<field " + name + ">";
}
public IClass getDeclaringClass() {
return AstDynamicPropertyClass.this;
}
public IClass getDeclaringClass() {
return AstDynamicPropertyClass.this;
}
public Atom getName() {
return name;
}
public Atom getName() {
return name;
}
public TypeReference getFieldTypeReference() {
return defaultDescriptor;
}
public TypeReference getFieldTypeReference() {
return defaultDescriptor;
}
public FieldReference getReference() {
return FieldReference.findOrCreate(AstDynamicPropertyClass.this.getReference(), name, defaultDescriptor);
}
public FieldReference getReference() {
return FieldReference.findOrCreate(AstDynamicPropertyClass.this.getReference(), name, defaultDescriptor);
}
public boolean isFinal() {
return false;
}
public boolean isFinal() {
return false;
}
public boolean isPrivate() {
return false;
}
public boolean isPrivate() {
return false;
}
public boolean isProtected() {
return false;
}
public boolean isProtected() {
return false;
}
public boolean isPublic() {
return false;
}
public boolean isPublic() {
return false;
}
public boolean isVolatile() {
return false;
}
public boolean isVolatile() {
return false;
}
public boolean isStatic() {
return isStatic;
}
public boolean isStatic() {
return isStatic;
}
public IClassHierarchy getClassHierarchy() {
return AstDynamicPropertyClass.this.getClassHierarchy();
}
});
public IClassHierarchy getClassHierarchy() {
return AstDynamicPropertyClass.this.getClassHierarchy();
}
});
return declaredFields.get(name);
}
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
return null;
return declaredFields.get(name);
}
}
protected boolean isStaticField(Atom name) {

View File

@ -23,7 +23,6 @@ import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.shrikeCT.ClassConstants;
import com.ibm.wala.types.Selector;
import com.ibm.wala.types.TypeName;
@ -86,7 +85,7 @@ abstract public class AstFunctionClass implements IClass, ClassConstants {
return ACC_PUBLIC;
}
public IClass getSuperclass() throws ClassHierarchyException {
public IClass getSuperclass() {
return loader.lookupClass(superReference.getName());
}

View File

@ -29,7 +29,6 @@ import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextUtil;
import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.summaries.SyntheticIR;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.ssa.DefUse;
@ -87,8 +86,7 @@ public class CloneInterpreter implements SSAContextInterpreter {
arraycopyDesc);
/**
* If the type is an array, the program counter of the synthesized call to
* arraycopy. Doesn't really matter what it is.
* If the type is an array, the program counter of the synthesized call to arraycopy. Doesn't really matter what it is.
*/
private final static int ARRAYCOPY_PC = 3;
@ -103,7 +101,7 @@ public class CloneInterpreter implements SSAContextInterpreter {
final private Map<TypeReference, IR> IRCache = HashMapFactory.make();
private final SSAInstructionFactory insts = Language.JAVA.instructionFactory();
public IR getIR(CGNode node) {
if (node == null) {
throw new IllegalArgumentException("node is null");
@ -153,8 +151,7 @@ public class CloneInterpreter implements SSAContextInterpreter {
}
/**
* @return an array of statements that encode the behavior of the clone method
* for a given type.
* @return an array of statements that encode the behavior of the clone method for a given type.
*/
private SSAInstruction[] makeStatements(IClass klass) {
if (Assertions.verifyAssertions) {
@ -173,7 +170,7 @@ public class CloneInterpreter implements SSAContextInterpreter {
int length = nextLocal++;
statements.add(insts.ArrayLengthInstruction(length, 1));
int[] sizes = new int[klass.getReference().getDimensionality()];
Arrays.fill(sizes,length);
Arrays.fill(sizes, length);
N = insts.NewInstruction(retValue, ref, sizes);
} else {
N = insts.NewInstruction(retValue, ref);
@ -202,11 +199,7 @@ public class CloneInterpreter implements SSAContextInterpreter {
SSAPutInstruction P = insts.PutInstruction(retValue, tempValue, f.getReference());
statements.add(P);
}
try {
k = k.getSuperclass();
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
}
k = k.getSuperclass();
}
}
@ -223,8 +216,7 @@ public class CloneInterpreter implements SSAContextInterpreter {
}
/**
* @return an IR that encodes the behavior of the clone method for a given
* type.
* @return an IR that encodes the behavior of the clone method for a given type.
*/
private IR makeIR(IMethod method, Context context, IClass klass) {
if (Assertions.verifyAssertions) {
@ -236,13 +228,12 @@ public class CloneInterpreter implements SSAContextInterpreter {
/*
* @see com.ibm.wala.ipa.callgraph.propagation.cfa.CFAContextInterpreter#recordFactoryType(com.ibm.wala.ipa.callgraph.CGNode,
* com.ibm.wala.classLoader.IClass)
* com.ibm.wala.classLoader.IClass)
*/
public boolean recordFactoryType(CGNode node, IClass klass) {
return false;
}
public Iterator<FieldReference> iterateFieldsRead(CGNode node) {
SSAInstruction[] statements = getIR(node).getInstructions();
return CodeScanner.getFieldsRead(statements).iterator();

View File

@ -28,9 +28,8 @@ import com.ibm.wala.util.debug.UnimplementedError;
import com.ibm.wala.util.strings.Atom;
/**
* Implementation of {@link IClass} for array classes. Such classes would be
* best called 'broken covariant array types', since that is the semantics that
* they implement.
* Implementation of {@link IClass} for array classes. Such classes would be best called 'broken covariant array types', since that
* is the semantics that they implement.
*/
public class ArrayClass implements IClass, Constants {
@ -107,30 +106,24 @@ public class ArrayClass implements IClass, Constants {
* @see com.ibm.wala.classLoader.IClass#getSuperclass()
*/
public IClass getSuperclass() {
try {
IClass elt = getElementClass();
IClass elt = getElementClass();
if (Assertions.verifyAssertions) {
Assertions._assert(getReference().getArrayElementType().isPrimitiveType() || elt != null);
}
if (Assertions.verifyAssertions) {
Assertions._assert(getReference().getArrayElementType().isPrimitiveType() || elt != null);
}
// super is Ljava/lang/Object in two cases:
// 1) [Ljava/lang/Object
// 2) [? for primitive arrays (null from getElementClass)
if (elt == null || elt.getReference() == getClassLoader().getLanguage().getRootType()) {
return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName());
}
// super is Ljava/lang/Object in two cases:
// 1) [Ljava/lang/Object
// 2) [? for primitive arrays (null from getElementClass)
if (elt == null || elt.getReference() == getClassLoader().getLanguage().getRootType()) {
return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName());
}
// else it is array of super of element type (yuck)
else {
TypeReference eltSuperRef = elt.getSuperclass().getReference();
TypeReference superRef = TypeReference.findOrCreateArrayOf(eltSuperRef);
return elt.getSuperclass().getClassLoader().lookupClass(superRef.getName());
}
} catch (ClassHierarchyException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
return null;
// else it is array of super of element type (yuck)
else {
TypeReference eltSuperRef = elt.getSuperclass().getReference();
TypeReference superRef = TypeReference.findOrCreateArrayOf(eltSuperRef);
return elt.getSuperclass().getClassLoader().lookupClass(superRef.getName());
}
}
@ -225,7 +218,7 @@ public class ArrayClass implements IClass, Constants {
*/
public Collection<IClass> getAllImplementedInterfaces() {
HashSet<IClass> result = HashSetFactory.make(2);
for(TypeReference ref : getClassLoader().getLanguage().getArrayInterfaces()) {
for (TypeReference ref : getClassLoader().getLanguage().getArrayInterfaces()) {
IClass klass = loader.lookupClass(ref.getName());
if (klass != null) {
result.add(klass);

View File

@ -44,8 +44,8 @@ import com.ibm.wala.util.warnings.Warnings;
/**
* A class representing which originates in some form of bytecode.
*
* @param <T> type of classloader which loads this format of class.
*
* @param <T> type of classloader which loads this format of class.
*/
public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
@ -151,7 +151,6 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
protected abstract IMethod[] computeDeclaredMethods() throws InvalidClassFileException;
public TypeReference getReference() {
return typeReference;
}
@ -159,7 +158,7 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
public String getSourceFileName() {
return loader.getSourceFileName(this);
}
public InputStream getSource() {
return loader.getSource(this);
}
@ -235,12 +234,12 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
superClass = loader.lookupClass(TypeName.findOrCreate(superName));
}
public IClass getSuperclass() throws ClassHierarchyException {
public IClass getSuperclass() {
if (!superclassComputed) {
computeSuperclass();
}
if (superClass == null && !getReference().equals(TypeReference.JavaLangObject)) {
throw new ClassHierarchyException("No superclass found for " + this+" Superclass name "+superName);
throw new IllegalStateException("No superclass found for " + this + " Superclass name " + superName);
}
return superClass;
}
@ -381,22 +380,18 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
}
// check parent, caching if found
try {
if (!selector.equals(MethodReference.clinitSelector) && !selector.equals(MethodReference.initSelector)) {
IClass superclass = getSuperclass();
if (superclass != null) {
IMethod inherit = superclass.getMethod(selector);
if (inherit != null) {
if (inheritCache == null) {
inheritCache = new BimodalMap<Selector, IMethod>(5);
}
inheritCache.put(selector, inherit);
return inherit;
if (!selector.equals(MethodReference.clinitSelector) && !selector.equals(MethodReference.initSelector)) {
IClass superclass = getSuperclass();
if (superclass != null) {
IMethod inherit = superclass.getMethod(selector);
if (inherit != null) {
if (inheritCache == null) {
inheritCache = new BimodalMap<Selector, IMethod>(5);
}
inheritCache.put(selector, inherit);
return inherit;
}
}
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
}
// didn't find it yet. special logic for interfaces
@ -441,7 +436,7 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
Warnings.add(ClassHierarchyWarning.create("expected an interface " + klass));
}
}
// at this point result holds all interfaces the class directly extends.
// now expand to a fixed point.
Set<IClass> last = null;
@ -451,15 +446,10 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
result.addAll(i.getDirectInterfaces());
}
} while (last.size() < result.size());
// now add any interfaces implemented by the super class
IClass sup = null;
try {
sup = getSuperclass();
} catch (ClassHierarchyException e1) {
Assertions.UNREACHABLE();
}
sup = getSuperclass();
if (sup != null) {
result.addAll(sup.getAllImplementedInterfaces());
}

View File

@ -57,8 +57,9 @@ public interface IClass extends IClassHierarchyDweller {
/**
* @return the superclass, or null if java.lang.Object
* @throws IllegalStateException if there's some problem determining the superclass
*/
IClass getSuperclass() throws ClassHierarchyException;
IClass getSuperclass();
/**
* @return Collection of (IClass) interfaces this class directly implements. If this class is an interface, returns the interfaces

View File

@ -38,7 +38,6 @@ import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod;
import com.ibm.wala.ipa.callgraph.impl.FakeWorldClinitMethod;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
@ -82,8 +81,8 @@ import com.ibm.wala.util.warnings.Warning;
import com.ibm.wala.util.warnings.Warnings;
/**
* This abstract base class provides the general algorithm for a call graph builder that relies on propagation through
* an iterative dataflow solver, and constraints generated by statements in SSA form.
* This abstract base class provides the general algorithm for a call graph builder that relies on propagation through an iterative
* dataflow solver, and constraints generated by statements in SSA form.
*
* TODO: This implementation currently keeps all points to sets live ... even those for local variables that do not span
* interprocedural boundaries. This may be too space-inefficient .. we can consider recomputing local sets on demand.
@ -116,8 +115,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
*/
// private final static boolean OPTIMIZE_WITH_TYPE_INFERENCE = true;
/**
* An optimization: if we can locally determine the final solution for a points-to set, then don't actually create the
* points-to set, but instead short circuit by propagating the final solution to all such uses.
* An optimization: if we can locally determine the final solution for a points-to set, then don't actually create the points-to
* set, but instead short circuit by propagating the final solution to all such uses.
*
* String constants are ALWAYS considered invariant, regardless of the value of this flag.
*
@ -128,9 +127,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
private final static boolean SHORT_CIRCUIT_INVARIANT_SETS = true;
/**
* An optimization: if we can locally determine that a particular pointer p has exactly one use, then we don't
* actually create the points-to-set for p, but instead short-circuit by propagating the final solution to the unique
* use.
* An optimization: if we can locally determine that a particular pointer p has exactly one use, then we don't actually create the
* points-to-set for p, but instead short-circuit by propagating the final solution to the unique use.
*
* Doesn't play well with pre-transitive solver; turning off for now.
*/
@ -261,7 +259,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
/**
* Add constraints for a particular basic block.
*/
protected void addBlockInstructionConstraints(CGNode node, ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg, BasicBlock b, ConstraintVisitor v) {
protected void addBlockInstructionConstraints(CGNode node, ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg, BasicBlock b,
ConstraintVisitor v) {
v.setBasicBlock(b);
// visit each instruction in the basic block.
@ -278,7 +277,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
addPhiConstraints(node, cfg, b, v);
}
private void addPhiConstraints(CGNode node, ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg, BasicBlock b, ConstraintVisitor v) {
private void addPhiConstraints(CGNode node, ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg, BasicBlock b,
ConstraintVisitor v) {
// visit each phi instruction in each successor block
for (Iterator sbs = cfg.getSuccNodes(b); sbs.hasNext();) {
BasicBlock sb = (BasicBlock) sbs.next();
@ -333,8 +333,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
List<ProgramCounter> peis = getIncomingPEIs(ir, ir.getExitBlock());
PointerKey exception = getPointerKeyForExceptionalReturnValue(node);
TypeReference throwableType =
node.getMethod().getDeclaringClass().getClassLoader().getLanguage().getThrowableType();
TypeReference throwableType = node.getMethod().getDeclaringClass().getClassLoader().getLanguage().getThrowableType();
IClass c = node.getClassHierarchy().lookupClass(throwableType);
addExceptionDefConstraints(ir, du, node, peis, exception, Collections.singleton(c));
}
@ -391,7 +390,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
// 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();
Collection<TypeReference> types = pei.getExceptionTypes();
if (types != null) {
for (Iterator<TypeReference> it2 = types.iterator(); it2.hasNext();) {
TypeReference type = it2.next();
@ -502,8 +501,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
protected static class ConstraintVisitor extends SSAInstruction.Visitor {
/**
* The governing call graph builder. This field is used instead of an inner class in order to allow more flexible
* reuse of this visitor in subclasses
* The governing call graph builder. This field is used instead of an inner class in order to allow more flexible reuse of this
* visitor in subclasses
*/
protected final SSAPropagationCallGraphBuilder builder;
@ -826,7 +825,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
if (DEBUG) {
System.err.println("visitReturn: " + instruction);
}
PointerKey returnValue = getPointerKeyForReturnValue();
PointerKey result = getPointerKeyForLocal(instruction.getResult());
if (contentsAreInvariant(symbolTable, du, instruction.getResult())) {
@ -1298,8 +1297,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
}
/**
* Add a constraint to the system indicating that the contents of local src flows to dst, with no special type
* filter.
* Add a constraint to the system indicating that the contents of local src flows to dst, with no special type filter.
*/
private void addPiAssignment(PointerKey dst, int src) {
PointerKey srcKey = getPointerKeyForLocal(src);
@ -1329,8 +1327,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
/**
* 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)
* @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;
@ -1357,8 +1355,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
public void visitLoadMetadata(SSALoadMetadataInstruction instruction) {
PointerKey def = getPointerKeyForLocal(instruction.getDef());
assert instruction.getType() == TypeReference.JavaLangClass;
InstanceKey iKey = getInstanceKeyForClassObject((TypeReference)instruction.getToken());
IClass klass = getClassHierarchy().lookupClass((TypeReference)instruction.getToken());
InstanceKey iKey = getInstanceKeyForClassObject((TypeReference) instruction.getToken());
IClass klass = getClassHierarchy().lookupClass((TypeReference) instruction.getToken());
if (klass != null) {
processClassInitializer(klass);
}
@ -1385,7 +1383,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
if (!getBuilder().getOptions().getHandleStaticInit()) {
return;
}
if (getBuilder().clinitVisited.contains(klass)) {
return;
}
@ -1411,13 +1409,9 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
}
}
try {
IClass sc = klass.getSuperclass();
if (sc != null) {
processClassInitializer(sc);
}
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
IClass sc = klass.getSuperclass();
if (sc != null) {
processClassInitializer(sc);
}
}
}
@ -1428,10 +1422,9 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
* Side effect: add edge to the call graph.
*
* @param instruction
* @param constParams if non-null, then constParams[i] holds the set of instance keys that are passed as param i, or
* null if param i is not invariant
* @param uniqueCatchKey if non-null, then this is the unique PointerKey that catches all exceptions from this call
* site.
* @param constParams if non-null, then constParams[i] holds the set of instance keys that are passed as param i, or null if param
* i is not invariant
* @param uniqueCatchKey if non-null, then this is the unique PointerKey that catches all exceptions from this call site.
*/
@SuppressWarnings("deprecation")
private void processResolvedCall(CGNode caller, SSAAbstractInvokeInstruction instruction, CGNode target,
@ -1572,8 +1565,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
*
* This operator will create a new callee context and constraints if necessary.
*
* N.B: This implementation assumes that the calling context depends solely on the dataflow information computed for
* the receiver. TODO: generalize this to have other forms of context selection, such as CPA-style algorithms.
* N.B: This implementation assumes that the calling context depends solely on the dataflow information computed for the receiver.
* TODO: generalize this to have other forms of context selection, such as CPA-style algorithms.
*/
final class DispatchOperator extends UnaryOperator<PointsToSetVariable> implements IPointerOperator {
private final SSAAbstractInvokeInstruction call;
@ -1587,8 +1580,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
/**
* @param call
* @param node
* @param constParams if non-null, then constParams[i] holds the String constant that is passed as param i, or null
* if param i is not a String constant
* @param constParams if non-null, then constParams[i] holds the String constant that is passed as param i, or null if param i
* is not a String constant
*/
DispatchOperator(SSAAbstractInvokeInstruction call, ExplicitCallGraph.ExplicitNode node, InstanceKey[][] constParams,
PointerKey uniqueCatch) {
@ -1605,7 +1598,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
/*
* @see com.ibm.wala.dataflow.fixpoint.UnaryOperator#evaluate(com.ibm.wala.dataflow.fixpoint.IVariable,
* com.ibm.wala.dataflow.fixpoint.IVariable)
* com.ibm.wala.dataflow.fixpoint.IVariable)
*/
@Override
public byte evaluate(PointsToSetVariable lhs, PointsToSetVariable rhs) {
@ -1738,7 +1731,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
throw new IllegalArgumentException("du is null");
}
if (vn <= 0) {
throw new IllegalArgumentException("v is invalid: " + vn);
throw new IllegalArgumentException("v is invalid: " + vn);
}
// todo: enhance this by solving a dead-code elimination
// problem.
@ -1880,8 +1873,8 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
}
/**
* TODO: enhance this logic using type inference TODO!!!: enhance filtering to consider concrete types, not just
* cones. precondition: needs Filter
* TODO: enhance this logic using type inference TODO!!!: enhance filtering to consider concrete types, not just cones.
* precondition: needs Filter
*
* @param target
* @return an IClass which represents
@ -1918,8 +1911,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
}
/**
* A value is "invariant" if we can figure out the instances it can ever point to locally, without resorting to
* propagation.
* A value is "invariant" if we can figure out the instances it can ever point to locally, without resorting to propagation.
*
* @param valueNumber
* @return true iff the contents of the local with this value number can be deduced locally, without propagation
@ -2012,7 +2004,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
/**
* @author sfink
*
* A warning for when we fail to resolve the type for a checkcast
* A warning for when we fail to resolve the type for a checkcast
*/
private static class CheckcastFailure extends Warning {
@ -2036,7 +2028,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
/**
* @author sfink
*
* A warning for when we fail to resolve the type for a field
* A warning for when we fail to resolve the type for a field
*/
private static class FieldResolutionFailure extends Warning {

View File

@ -29,18 +29,16 @@ import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory;
import com.ibm.wala.ipa.callgraph.propagation.SmushedAllocationSiteInstanceKeys;
import com.ibm.wala.ipa.callgraph.propagation.rta.RTAContextInterpreter;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
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.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
/**
* Flexible class to create {@link InstanceKey}s depending on various policies ranging from
* class-based (i.e. 0-CFA) to allocation-site-based (0-1-CFA variants).
* Flexible class to create {@link InstanceKey}s depending on various policies ranging from class-based (i.e. 0-CFA) to
* allocation-site-based (0-1-CFA variants).
*
* @author sfink
*/
@ -55,7 +53,7 @@ public class ZeroXInstanceKeys implements InstanceKeyFactory {
public final static TypeReference JavaLangStringBuilder = TypeReference.findOrCreate(ClassLoaderReference.Primordial,
JavaLangStringBuilderName);
private final static TypeName JavaLangAbstractStringBuilderName = TypeName.string2TypeName("Ljava/lang/AbstractStringBuilder");
public final static TypeReference JavaLangAbstractStringBuilder = TypeReference.findOrCreate(ClassLoaderReference.Primordial,
@ -67,35 +65,31 @@ public class ZeroXInstanceKeys implements InstanceKeyFactory {
public static final int NONE = 0;
/**
* An ALLOCATIONS - based policy distinguishes instances by allocation site.
* Otherwise, the policy distinguishes instances by type.
* An ALLOCATIONS - based policy distinguishes instances by allocation site. Otherwise, the policy distinguishes instances by
* type.
*/
public static final int ALLOCATIONS = 1;
/**
* A policy variant where String and StringBuffers are NOT disambiguated
* according to allocation site.
* A policy variant where String and StringBuffers are NOT disambiguated according to allocation site.
*/
public static final int SMUSH_STRINGS = 2;
/**
* A policy variant where {@link Throwable} instances are NOT disambiguated according
* to allocation site.
* A policy variant where {@link Throwable} instances are NOT disambiguated according to allocation site.
*
*/
public static final int SMUSH_THROWABLES = 4;
/**
* A policy variant where if a type T has only primitive instance fields, then
* instances of type T are NOT disambiguated by allocation site.
* A policy variant where if a type T has only primitive instance fields, then instances of type T are NOT disambiguated by
* allocation site.
*/
public static final int SMUSH_PRIMITIVE_HOLDERS = 8;
/**
* This variant counts the N, number of allocation sites of a particular type
* T in each method. If N > SMUSH_LIMIT, then these N allocation sites are NOT
* distinguished ... instead there is a single abstract allocation site for
* <N,T>
* This variant counts the N, number of allocation sites of a particular type T in each method. If N > SMUSH_LIMIT, then these N
* allocation sites are NOT distinguished ... instead there is a single abstract allocation site for <N,T>
*
* Probably the best choice in many cases.
*/
@ -107,8 +101,7 @@ public class ZeroXInstanceKeys implements InstanceKeyFactory {
public static final int CONSTANT_SPECIFIC = 32;
/**
* When using smushing, how many sites in a node will be kept distinct before
* smushing?
* When using smushing, how many sites in a node will be kept distinct before smushing?
*/
private final int SMUSH_LIMIT = 25;
@ -128,8 +121,7 @@ public class ZeroXInstanceKeys implements InstanceKeyFactory {
private final AllocationSiteInNodeFactory siteBased;
/**
* A delegate object to create "abstract allocation site" - based abstract
* instances
* A delegate object to create "abstract allocation site" - based abstract instances
*/
private final SmushedAllocationSiteInstanceKeys smushed;
@ -230,15 +222,14 @@ public class ZeroXInstanceKeys implements InstanceKeyFactory {
smushees.add(e.getKey());
}
}
s = smushees.isEmpty() ? Collections.<IClass>emptySet() : smushees;
s = smushees.isEmpty() ? Collections.<IClass> emptySet() : smushees;
smushMap.put(node, s);
}
return s.contains(c);
}
/**
* @return Map: IClass -> Integer, the number of allocation sites for each
* type.
* @return Map: IClass -> Integer, the number of allocation sites for each type.
*/
private Map<IClass, Integer> countAllocsByType(CGNode node) {
Map<IClass, Integer> count = HashMapFactory.make();
@ -282,8 +273,7 @@ public class ZeroXInstanceKeys implements InstanceKeyFactory {
/*
* @see com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory#getInstanceKeyForPEI(com.ibm.wala.ipa.callgraph.CGNode,
* com.ibm.wala.classLoader.ProgramCounter,
* com.ibm.wala.types.TypeReference)
* com.ibm.wala.classLoader.ProgramCounter, com.ibm.wala.types.TypeReference)
*/
public InstanceKey getInstanceKeyForPEI(CGNode node, ProgramCounter pei, TypeReference type) {
return classBased.getInstanceKeyForPEI(node, pei, type);
@ -326,33 +316,28 @@ public class ZeroXInstanceKeys implements InstanceKeyFactory {
return c.getClassHierarchy().isSubclassOf(c, c.getClassHierarchy().lookupClass(TypeReference.JavaLangThrowable));
}
public boolean isStackTraceElement(IClass C) {
if (C == null) {
public boolean isStackTraceElement(IClass c) {
if (c == null) {
throw new IllegalArgumentException("C is null");
}
return C.getReference().equals(TypeReference.JavaLangStackTraceElement);
return c.getReference().equals(TypeReference.JavaLangStackTraceElement);
}
private boolean allFieldsArePrimitive(IClass C) {
if (C.isArrayClass()) {
TypeReference t = C.getReference().getArrayElementType();
private boolean allFieldsArePrimitive(IClass c) {
if (c.isArrayClass()) {
TypeReference t = c.getReference().getArrayElementType();
return t.isPrimitiveType();
} else {
if (C.getReference().equals(TypeReference.JavaLangObject)) {
if (c.getReference().equals(TypeReference.JavaLangObject)) {
return true;
} else {
for (Iterator<IField> it = C.getDeclaredInstanceFields().iterator(); it.hasNext();) {
for (Iterator<IField> it = c.getDeclaredInstanceFields().iterator(); it.hasNext();) {
IField f = it.next();
if (f.getReference().getFieldType().isReferenceType()) {
return false;
}
}
try {
return allFieldsArePrimitive(C.getSuperclass());
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
return false;
}
return allFieldsArePrimitive(c.getSuperclass());
}
}
}

View File

@ -45,7 +45,6 @@ import com.ibm.wala.ipa.callgraph.propagation.StandardSolver;
import com.ibm.wala.ipa.callgraph.propagation.cfa.DefaultPointerKeyFactory;
import com.ibm.wala.ipa.callgraph.propagation.cfa.DefaultSSAInterpreter;
import com.ibm.wala.ipa.callgraph.propagation.cfa.DelegatingSSAContextInterpreter;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
@ -55,7 +54,6 @@ import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashSetFactory;
import com.ibm.wala.util.debug.Assertions;
/**
* Abstract superclass of various RTA flavors
@ -87,10 +85,8 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
*/
protected final HashSet<IClass> allocatedClasses = HashSetFactory.make();
/**
* set of class names that are implicitly pre-allocated Note: for performance
* reasons make sure java.lang.Object comes first
* set of class names that are implicitly pre-allocated Note: for performance reasons make sure java.lang.Object comes first
*/
private final static TypeReference[] PRE_ALLOC = {
TypeReference.findOrCreate(ClassLoaderReference.Primordial, "Ljava/lang/Object"),
@ -103,8 +99,8 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
TypeReference.findOrCreate(ClassLoaderReference.Primordial, "Ljava/lang/ExceptionInInitializerError"),
TypeReference.findOrCreate(ClassLoaderReference.Primordial, "Ljava/lang/NullPointerException") };
protected AbstractRTABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, ContextSelector appContextSelector,
SSAContextInterpreter appContextInterpreter, ReflectionSpecification reflect) {
protected AbstractRTABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache,
ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, ReflectionSpecification reflect) {
super(cha, options, cache, new DefaultPointerKeyFactory());
setInstanceKeys(new ClassBasedInstanceKeys(options, cha));
setContextSelector(makeContextSelector(appContextSelector));
@ -116,13 +112,11 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
}
/**
* Visit all instructions in a node, and add dataflow constraints induced by
* each statement relevat to RTA
* Visit all instructions in a node, and add dataflow constraints induced by each statement relevat to RTA
*/
@Override
protected boolean addConstraintsFromNode(CGNode node) {
if (haveAlreadyVisited(node)) {
return false;
} else {
@ -175,8 +169,7 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
}
/**
* Is s is a getstatic or putstatic, then potentially add the relevant
* <clinit>to the newMethod set.
* Is s is a getstatic or putstatic, then potentially add the relevant <clinit>to the newMethod set.
*/
private void processFieldAccess(CGNode node, FieldReference f) {
if (DEBUG) {
@ -190,9 +183,8 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
}
}
protected void processClassInitializer(IClass klass) {
if (clinitProcessed.contains(klass)) {
return;
}
@ -217,8 +209,8 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
processResolvedCall(callGraph.getFakeWorldClinitNode(), s.getCallSite(), target);
} catch (CancelException e) {
if (DEBUG) {
System.err.println("Could not add node for class initializer: " + targetMethod.getSignature() +
" due to constraints on the maximum number of nodes in the call graph.");
System.err.println("Could not add node for class initializer: " + targetMethod.getSignature()
+ " due to constraints on the maximum number of nodes in the call graph.");
return;
}
}
@ -226,18 +218,15 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
}
}
try {
klass = klass.getSuperclass();
if (klass != null && !clinitProcessed.contains(klass))
processClassInitializer(klass);
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
}
klass = klass.getSuperclass();
if (klass != null && !clinitProcessed.contains(klass))
processClassInitializer(klass);
}
/**
* Add a constraint for a call instruction
* @throws IllegalArgumentException if site is null
*
* @throws IllegalArgumentException if site is null
*/
public void visitInvoke(CGNode node, CallSiteReference site) {
@ -247,7 +236,7 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
if (DEBUG) {
System.err.println(("visitInvoke: " + site));
}
// if non-virtual, add callgraph edges directly
IInvokeInstruction.IDispatch code = site.getInvocationCode();
@ -286,8 +275,7 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
protected abstract PointerKey getKeyForSite(CallSiteReference site);
/**
* Add constraints for a call site after we have computed a reachable target
* for the dispatch
* Add constraints for a call site after we have computed a reachable target for the dispatch
*
* Side effect: add edge to the call graph.
*/
@ -312,7 +300,8 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
/**
* Add a constraint for an allocate
* @throws IllegalArgumentException if newSite is null
*
* @throws IllegalArgumentException if newSite is null
*/
public void visitNew(CGNode node, NewSiteReference newSite) {
@ -395,9 +384,10 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
ReflectionSpecification reflect) {
SSAContextInterpreter defI = new DefaultSSAInterpreter(getOptions(), getAnalysisCache());
defI = new DelegatingSSAContextInterpreter(ReflectionContextInterpreter.createReflectionContextInterpreter(cha, getOptions(), getAnalysisCache(), reflect),
defI);
SSAContextInterpreter contextInterpreter = appContextInterpreter == null ? defI : new DelegatingSSAContextInterpreter(appContextInterpreter, defI);
defI = new DelegatingSSAContextInterpreter(ReflectionContextInterpreter.createReflectionContextInterpreter(cha, getOptions(),
getAnalysisCache(), reflect), defI);
SSAContextInterpreter contextInterpreter = appContextInterpreter == null ? defI : new DelegatingSSAContextInterpreter(
appContextInterpreter, defI);
return contextInterpreter;
}
@ -426,9 +416,8 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
result.setPeriodicMaintainInterval(PERIODIC_MAINTAIN_INTERVAL);
return result;
}
/*
/*
* @see com.ibm.wala.ipa.callgraph.CallGraphBuilder#getPointerAnalysis()
*/
@Override

View File

@ -125,17 +125,18 @@ public class ClassHierarchy implements IClassHierarchy {
private Collection<TypeReference> runtimeExceptionTypeRefs;
/**
* Return a set of IClasses that holds all superclasses of klass
* Return a set of {@link IClass} that holds all superclasses of klass
*
* @param klass class in question
* @return Set the result set
*/
private Set<IClass> computeSuperclasses(IClass klass) throws ClassHierarchyException {
private Set<IClass> computeSuperclasses(IClass klass) {
if (DEBUG) {
System.err.println("computeSuperclasses: " + klass);
}
Set<IClass> result = HashSetFactory.make(3);
klass = klass.getSuperclass();
while (klass != null) {
@ -146,7 +147,7 @@ public class ClassHierarchy implements IClassHierarchy {
klass = klass.getSuperclass();
if (klass != null && klass.getReference().getName().equals(rootTypeRef.getName())) {
if (!klass.getReference().getClassLoader().equals(rootTypeRef.getClassLoader())) {
throw new ClassHierarchyException("class " + klass + " is invalid, unexpected classloader");
throw new IllegalStateException("class " + klass + " is invalid, unexpected classloader");
}
}
}
@ -230,7 +231,7 @@ public class ClassHierarchy implements IClassHierarchy {
progressMonitor.worked(1);
}
}
} catch (IOException e) {
throw new ClassHierarchyException("factory.getLoader failed " + e);
} finally {
@ -293,7 +294,7 @@ public class ClassHierarchy implements IClassHierarchy {
try {
loadedSuperclasses = computeSuperclasses(klass);
loadedSuperInterfaces = klass.getAllImplementedInterfaces();
} catch (ClassHierarchyException e) {
} catch (Exception e) {
// a little cleanup
if (klass instanceof ShrikeClass) {
if (DEBUG) {
@ -317,11 +318,7 @@ public class ClassHierarchy implements IClassHierarchy {
while (node != null) {
IClass c = node.getJavaClass();
IClass superclass = null;
try {
superclass = c.getSuperclass();
} catch (ClassHierarchyException e1) {
Assertions.UNREACHABLE();
}
superclass = c.getSuperclass();
if (superclass != null) {
workingSuperclasses.remove(superclass);
Node supernode = findOrCreateNode(superclass);
@ -345,7 +342,7 @@ public class ClassHierarchy implements IClassHierarchy {
try {
// make sure we'll be able to load the interface!
computeSuperclasses(iface);
} catch (ClassHierarchyException e) {
} catch (IllegalStateException e) {
Warnings.add(ClassExclusion.create(iface.getReference(), e.getMessage()));
continue;
}
@ -553,11 +550,7 @@ public class ClassHierarchy implements IClassHierarchy {
return result;
} else {
IClass superclass = null;
try {
superclass = receiverClass.getSuperclass();
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
}
superclass = receiverClass.getSuperclass();
if (superclass == null) {
if (DEBUG) {
System.err.println(("resolveMethod(" + selector + ") failed: method not found"));
@ -756,13 +749,10 @@ public class ClassHierarchy implements IClassHierarchy {
superB = null;
}
while (A != null) {
if (superB.contains(A))
if (superB.contains(A)) {
return A;
try {
A = A.getSuperclass();
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
}
A = A.getSuperclass();
}
Assertions.UNREACHABLE("getLeastCommonSuperclass " + tempA + " " + B);
return null;
@ -833,19 +823,16 @@ public class ClassHierarchy implements IClassHierarchy {
}
private boolean slowIsSubclass(IClass sub, IClass sup) {
if (sub == sup)
if (sub == sup) {
return true;
else
try {
IClass parent = sub.getSuperclass();
if (parent == null)
return false;
else
return slowIsSubclass(parent, sup);
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
} else {
IClass parent = sub.getSuperclass();
if (parent == null) {
return false;
} else {
return slowIsSubclass(parent, sup);
}
}
}
/**

View File

@ -23,20 +23,16 @@ public class ClassHierarchyUtil {
* find the root of the inheritance tree for method m.
*/
public static IMethod getRootOfInheritanceTree(IMethod m) {
try {
IClass c = m.getDeclaringClass();
IClass parent = c.getSuperclass();
if (parent == null) {
return m;
} else {
MethodReference ref = MethodReference.findOrCreate(parent.getReference(), m.getSelector());
IMethod m2 = m.getClassHierarchy().resolveMethod(ref);
if (m2 != null && !m2.equals(m)) {
return getRootOfInheritanceTree(m2);
}
return m;
IClass c = m.getDeclaringClass();
IClass parent = c.getSuperclass();
if (parent == null) {
return m;
} else {
MethodReference ref = MethodReference.findOrCreate(parent.getReference(), m.getSelector());
IMethod m2 = m.getClassHierarchy().resolveMethod(ref);
if (m2 != null && !m2.equals(m)) {
return getRootOfInheritanceTree(m2);
}
} catch (ClassHierarchyException e) {
return m;
}
}
@ -45,20 +41,16 @@ public class ClassHierarchyUtil {
* Return the method that m overrides, or null if none
*/
public static IMethod getOverriden(IMethod m) {
try {
IClass c = m.getDeclaringClass();
IClass parent = c.getSuperclass();
if (parent == null) {
return null;
} else {
MethodReference ref = MethodReference.findOrCreate(parent.getReference(), m.getSelector());
IMethod m2 = m.getClassHierarchy().resolveMethod(ref);
if (m2 != null && !m2.equals(m)) {
return m2;
}
return null;
IClass c = m.getDeclaringClass();
IClass parent = c.getSuperclass();
if (parent == null) {
return null;
} else {
MethodReference ref = MethodReference.findOrCreate(parent.getReference(), m.getSelector());
IMethod m2 = m.getClassHierarchy().resolveMethod(ref);
if (m2 != null && !m2.equals(m)) {
return m2;
}
} catch (ClassHierarchyException e) {
return null;
}
}

View File

@ -72,13 +72,13 @@ public class BypassSyntheticClass extends SyntheticClass {
/*
* @see com.ibm.wala.classLoader.IClass#getSuperclass()
*/
public IClass getSuperclass() throws ClassHierarchyException {
public IClass getSuperclass() {
if (realType.isInterface()) {
IClass result = loader.lookupClass(TypeReference.JavaLangObject.getName());
if (result != null) {
return result;
} else {
throw new ClassHierarchyException("could not find java.lang.Object");
throw new IllegalStateException("could not find java.lang.Object");
}
} else
return realType;

View File

@ -131,7 +131,7 @@ public class ActionFormFactoryMethod extends SummarizedMethod {
return factoryClassRef.getName();
}
public IClass getSuperclass() throws ClassHierarchyException {
public IClass getSuperclass() {
return null;
}

View File

@ -23,7 +23,6 @@ import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.AbstractRootMethod;
import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.shrikeBT.IInvokeInstruction;
import com.ibm.wala.ssa.SSAInvokeInstruction;
@ -39,9 +38,7 @@ import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
/**
* This class provides an iterator of entrypoints that are implementations of org.apache.struts.action.Action
*
* @author sfink
* This class provides an iterator of {@link Entrypoint}s that are implementations of org.apache.struts.action.Action
*/
public class StrutsEntrypoints implements Iterable<Entrypoint>, EJBConstants {
@ -226,6 +223,7 @@ public class StrutsEntrypoints implements Iterable<Entrypoint>, EJBConstants {
* Add any methods that look like they might be DispatchAction targets, based on the method signature.
*
* TODO: instead, parse the struts xml directly.
*
* @param klass an Action
*/
private void addSpeculativeDispatchMethods(IClass klass, IClassHierarchy cha) {
@ -239,12 +237,7 @@ public class StrutsEntrypoints implements Iterable<Entrypoint>, EJBConstants {
entrypoints.put(m, new StrutsActionEntrypoint(klass, M, cha));
}
}
try {
c = c.getSuperclass();
} catch (ClassHierarchyException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
}
c = c.getSuperclass();
}
}
@ -331,8 +324,9 @@ public class StrutsEntrypoints implements Iterable<Entrypoint>, EJBConstants {
TypeName n = getParameterTypes(i)[0].getName();
if (n.equals(actionFormName)) {
// invoke a synthetic factory method that creates ActionForm objects
MethodReference declaredTarget = MethodReference.findOrCreate(ActionFormFactoryMethod.factoryClassRef, ActionFormFactoryMethod.name, ActionFormFactoryMethod.descr);
CallSiteReference site = CallSiteReference.make(0, declaredTarget , IInvokeInstruction.Dispatch.STATIC);
MethodReference declaredTarget = MethodReference.findOrCreate(ActionFormFactoryMethod.factoryClassRef,
ActionFormFactoryMethod.name, ActionFormFactoryMethod.descr);
CallSiteReference site = CallSiteReference.make(0, declaredTarget, IInvokeInstruction.Dispatch.STATIC);
SSAInvokeInstruction factoryInv = m.addInvocation(new int[0], site);
return factoryInv.getDef();
} else {
@ -373,8 +367,8 @@ public class StrutsEntrypoints implements Iterable<Entrypoint>, EJBConstants {
}
/**
* An entrypoint which assumes all ServletRequest and ServletResponses are of the HTTP flavor. TODO: get rid of this
* and just use {@link DefaultEntrypoint}? --MS
* An entrypoint which assumes all ServletRequest and ServletResponses are of the HTTP flavor. TODO: get rid of this and just use
* {@link DefaultEntrypoint}? --MS
*/
private static class StrutsPlugInEntrypoint extends DefaultEntrypoint {
@ -382,7 +376,7 @@ public class StrutsEntrypoints implements Iterable<Entrypoint>, EJBConstants {
super(method, cha);
}
}
/**
* return the set of classes that should be examined when searching for struts entrypoints.
*/

View File

@ -18,7 +18,6 @@ import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.ipa.callgraph.ClassTargetSelector;
import com.ibm.wala.ipa.callgraph.MethodTargetSelector;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.j2ee.BeanMetaData;
import com.ibm.wala.j2ee.DeploymentMetaData;
@ -30,7 +29,7 @@ import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.strings.Atom;
/**
* @author sfink
* Miscellaneous J2EE Utilities
*/
public class Util {
@ -49,9 +48,7 @@ public class Util {
}
/**
* @param bean
* @param cha
* governing class hierarchy
* @param cha governing class hierarchy
* @return the Set of CMR fields for this bean, including inherited CMRs
*/
public static Set<Object> getCMRFields(BeanMetaData bean, DeploymentMetaData dmd, ClassHierarchy cha) {
@ -66,12 +63,8 @@ public class Util {
if (Assertions.verifyAssertions) {
Assertions._assert(klass != null);
}
try {
IClass superKlass = klass.getSuperclass();
T = (superKlass == null) ? null : superKlass.getReference();
} catch (ClassHierarchyException e) {
Assertions.UNREACHABLE();
}
IClass superKlass = klass.getSuperclass();
T = (superKlass == null) ? null : superKlass.getReference();
}
return result;
}