From 321e925660d81f411dc9016965c7e6ec6cb1e09b Mon Sep 17 00:00:00 2001 From: Julian Dolby Date: Wed, 3 Apr 2013 12:12:43 -0400 Subject: [PATCH] work on CHA --- com.ibm.wala.cast.java.test.data/build.xml | 6 +- .../TypeInferencePrimAndStringOp.java | 9 + .../typeInference/AstJavaTypeInference.java | 14 +- .../ipa/cha/CrossLanguageClassHierarchy.java | 2 +- .../tests/callGraph/CHACallGraphTest.java | 41 +++ com.ibm.wala.core/META-INF/MANIFEST.MF | 1 + .../wala/ipa/callgraph/cha/CHACallGraph.java | 345 ++++++++++++++++++ .../callgraph/cha/CHAContextInterpreter.java | 30 ++ ...ntextInsensitiveCHAContextInterpreter.java | 40 ++ .../ipa/callgraph/impl/BasicCallGraph.java | 11 +- .../ipa/callgraph/impl/ExplicitCallGraph.java | 3 +- .../rta/ContextInsensitiveRTAInterpreter.java | 20 +- .../rta/RTAContextInterpreter.java | 13 +- .../com/ibm/wala/ipa/cha/ClassHierarchy.java | 2 +- .../com/ibm/wala/ipa/cha/IClassHierarchy.java | 2 +- .../META-INF/MANIFEST.MF | 2 +- .../launchers/JSProjectScopeTest.launch | 2 +- .../wala/ide/tests/util/EclipseTestUtil.java | 2 +- .../util/collections/ComposedIterator.java | 2 +- 19 files changed, 497 insertions(+), 50 deletions(-) create mode 100644 com.ibm.wala.cast.java.test.data/src/javaonepointfive/TypeInferencePrimAndStringOp.java create mode 100644 com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/callGraph/CHACallGraphTest.java create mode 100644 com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/CHACallGraph.java create mode 100644 com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/CHAContextInterpreter.java create mode 100644 com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/ContextInsensitiveCHAContextInterpreter.java diff --git a/com.ibm.wala.cast.java.test.data/build.xml b/com.ibm.wala.cast.java.test.data/build.xml index 9c23f2ccd..13a0c0aa4 100644 --- a/com.ibm.wala.cast.java.test.data/build.xml +++ b/com.ibm.wala.cast.java.test.data/build.xml @@ -49,11 +49,11 @@ - + - @@ -65,7 +65,7 @@ - + diff --git a/com.ibm.wala.cast.java.test.data/src/javaonepointfive/TypeInferencePrimAndStringOp.java b/com.ibm.wala.cast.java.test.data/src/javaonepointfive/TypeInferencePrimAndStringOp.java new file mode 100644 index 000000000..55a5b670e --- /dev/null +++ b/com.ibm.wala.cast.java.test.data/src/javaonepointfive/TypeInferencePrimAndStringOp.java @@ -0,0 +1,9 @@ +package javaonepointfive; + +public class TypeInferencePrimAndStringOp { + public static void main(String[] args) { + int a = 2; + String result = "a" + a; + } +} + diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/analysis/typeInference/AstJavaTypeInference.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/analysis/typeInference/AstJavaTypeInference.java index 1d5107744..12114eb4b 100644 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/analysis/typeInference/AstJavaTypeInference.java +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/analysis/typeInference/AstJavaTypeInference.java @@ -33,7 +33,7 @@ import com.ibm.wala.util.debug.Assertions; public class AstJavaTypeInference extends AstTypeInference { - protected final IClass stringClass; + protected IClass stringClass; protected class AstJavaTypeOperatorFactory extends AstTypeOperatorFactory implements AstJavaInstructionVisitor { public void visitBinaryOp(SSABinaryOpInstruction instruction) { @@ -96,7 +96,13 @@ public class AstJavaTypeInference extends AstTypeInference { public AstJavaTypeInference(IR ir, IClassHierarchy cha, boolean doPrimitives) { super(ir, cha, JavaPrimitiveType.BOOLEAN, doPrimitives); - this.stringClass = cha.lookupClass(TypeReference.JavaLangString); + } + + IClass getStringClass() { + if (stringClass == null) { + this.stringClass = cha.lookupClass(TypeReference.JavaLangString); + } + return stringClass; } protected void initialize() { @@ -125,12 +131,12 @@ public class AstJavaTypeInference extends AstTypeInference { TypeVariable r = (TypeVariable) rhs[i]; TypeAbstraction ta = r.getType(); if (ta instanceof PointType) { - if (ta.getType().equals(stringClass)) { + if (ta.getType().equals(getStringClass())) { meet = new PointType(ta.getType()); break; } } else if (ta instanceof ConeType) { - if (ta.getType().equals(stringClass)) { + if (ta.getType().equals(getStringClass())) { meet = new PointType(ta.getType()); break; } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/cha/CrossLanguageClassHierarchy.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/cha/CrossLanguageClassHierarchy.java index 27737bdb3..4956956de 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/cha/CrossLanguageClassHierarchy.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/cha/CrossLanguageClassHierarchy.java @@ -135,7 +135,7 @@ public class CrossLanguageClassHierarchy implements IClassHierarchy { return getHierarchy(c).getNumber(c); } - public Collection getPossibleTargets(MethodReference ref) { + public Set getPossibleTargets(MethodReference ref) { return getHierarchy(ref).getPossibleTargets(ref); } diff --git a/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/callGraph/CHACallGraphTest.java b/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/callGraph/CHACallGraphTest.java new file mode 100644 index 000000000..aad8d8361 --- /dev/null +++ b/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/callGraph/CHACallGraphTest.java @@ -0,0 +1,41 @@ +package com.ibm.wala.core.tests.callGraph; + +import java.io.IOException; + +import org.junit.Test; + +import com.ibm.wala.core.tests.util.TestConstants; +import com.ibm.wala.ipa.callgraph.AnalysisScope; +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ipa.callgraph.Entrypoint; +import com.ibm.wala.ipa.callgraph.cha.CHACallGraph; +import com.ibm.wala.ipa.callgraph.impl.AllApplicationEntrypoints; +import com.ibm.wala.ipa.cha.ClassHierarchy; +import com.ibm.wala.ipa.cha.ClassHierarchyException; +import com.ibm.wala.util.CancelException; + +public class CHACallGraphTest { + @Test public void testJava_cup() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { + testCHA(TestConstants.JAVA_CUP, TestConstants.JAVA_CUP_MAIN); + } + + public static CallGraph testCHA(String scopeFile, String mainClass) throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { + AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope(scopeFile, CallGraphTestUtil.REGRESSION_EXCLUSIONS); + ClassHierarchy cha = ClassHierarchy.make(scope); + Iterable entrypoints; + if (mainClass == null) { + entrypoints = new AllApplicationEntrypoints(scope, cha); + } else { + entrypoints = com.ibm.wala.ipa.callgraph.impl.Util.makeMainEntrypoints(scope, cha, mainClass); + } + + CHACallGraph CG = new CHACallGraph(cha); + CG.init(entrypoints); + + return CG; + } + + public static void main(String[] args) throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { + testCHA(args[0], args.length>1? args[1]: null); + } +} diff --git a/com.ibm.wala.core/META-INF/MANIFEST.MF b/com.ibm.wala.core/META-INF/MANIFEST.MF index c117271fc..c92918699 100644 --- a/com.ibm.wala.core/META-INF/MANIFEST.MF +++ b/com.ibm.wala.core/META-INF/MANIFEST.MF @@ -28,6 +28,7 @@ Export-Package: ., com.ibm.wala.demandpa.util, com.ibm.wala.escape, com.ibm.wala.ipa.callgraph, + com.ibm.wala.ipa.callgraph.cha, com.ibm.wala.ipa.callgraph.impl, com.ibm.wala.ipa.callgraph.propagation, com.ibm.wala.ipa.callgraph.propagation.cfa, diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/CHACallGraph.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/CHACallGraph.java new file mode 100644 index 000000000..e2c1ef269 --- /dev/null +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/CHACallGraph.java @@ -0,0 +1,345 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package com.ibm.wala.ipa.callgraph.cha; + +import java.lang.ref.SoftReference; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.classLoader.NewSiteReference; +import com.ibm.wala.ipa.callgraph.AnalysisCache; +import com.ibm.wala.ipa.callgraph.AnalysisOptions; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.Context; +import com.ibm.wala.ipa.callgraph.Entrypoint; +import com.ibm.wala.ipa.callgraph.impl.BasicCallGraph; +import com.ibm.wala.ipa.callgraph.impl.Everywhere; +import com.ibm.wala.ipa.callgraph.impl.FakeRootMethod; +import com.ibm.wala.ipa.callgraph.impl.FakeWorldClinitMethod; +import com.ibm.wala.ipa.cha.IClassHierarchy; +import com.ibm.wala.shrikeBT.IInvokeInstruction; +import com.ibm.wala.ssa.DefUse; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.util.CancelException; +import com.ibm.wala.util.collections.ComposedIterator; +import com.ibm.wala.util.collections.EmptyIterator; +import com.ibm.wala.util.collections.Filter; +import com.ibm.wala.util.collections.FilterIterator; +import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.collections.HashSetFactory; +import com.ibm.wala.util.collections.Iterator2Collection; +import com.ibm.wala.util.collections.IteratorUtil; +import com.ibm.wala.util.collections.MapIterator; +import com.ibm.wala.util.collections.NonNullSingletonIterator; +import com.ibm.wala.util.functions.Function; +import com.ibm.wala.util.graph.NumberedEdgeManager; +import com.ibm.wala.util.intset.IntSet; +import com.ibm.wala.util.intset.IntSetUtil; +import com.ibm.wala.util.intset.MutableIntSet; + +public class CHACallGraph extends BasicCallGraph { + private final IClassHierarchy cha; + private final AnalysisOptions options; + private final AnalysisCache cache; + + private boolean isInitialized = false; + + private class CHANode extends NodeImpl { + + protected CHANode(IMethod method, Context C) { + super(method, C); + } + + public IR getIR() { + assert false; + return null; + } + + public DefUse getDU() { + assert false; + return null; + } + + public Iterator iterateNewSites() { + assert false; + return null; + } + + public Iterator iterateCallSites() { + return getInterpreter(this).iterateCallSites(this); + } + + @Override + public boolean equals(Object obj) { + return obj.getClass()==getClass() && getMethod().equals(((CHANode)obj).getMethod()); + } + + @Override + public int hashCode() { + return getMethod().hashCode(); + } + + @Override + public boolean addTarget(CallSiteReference reference, CGNode target) { + return false; + } + + } + + public CHACallGraph(IClassHierarchy cha) { + this.cha = cha; + this.options = new AnalysisOptions(); + this.cache = new AnalysisCache(); + setInterpreter(new ContextInsensitiveCHAContextInterpreter()); + } + + public void init(Iterable entrypoints) throws CancelException { + super.init(); + + CGNode root = getFakeRootNode(); + int programCounter = 0; + for(Entrypoint e : entrypoints) { + root.addTarget(e.makeSite(programCounter++), null); + } + closure(root, true); + isInitialized = true; + } + + public IClassHierarchy getClassHierarchy() { + return cha; + } + + private Iterator getPossibleTargets(CallSiteReference site) { + if (site.isDispatch()) { + return cha.getPossibleTargets(site.getDeclaredTarget()).iterator(); + } else { + IMethod m = cha.resolveMethod(site.getDeclaredTarget()); + if (m != null) { + return new NonNullSingletonIterator(m); + } else { + return EmptyIterator.instance(); + } + } + } + + public Set getPossibleTargets(CGNode node, CallSiteReference site) { + return Iterator2Collection.toSet( + new MapIterator( + new FilterIterator( + getPossibleTargets(site), + new Filter() { + public boolean accepts(IMethod o) { + return !o.isAbstract(); + } + } + ), + new Function() { + public CGNode apply(IMethod object) { + try { + return findOrCreateNode(object, Everywhere.EVERYWHERE); + } catch (CancelException e) { + assert false : e.toString(); + return null; + } + } + })); + } + + public int getNumberOfTargets(CGNode node, CallSiteReference site) { + return IteratorUtil.count(getPossibleTargets(site)); + } + + public Iterator getPossibleSites(final CGNode src, final CGNode target) { + return + new FilterIterator(getInterpreter(src).iterateCallSites(src), + new Filter() { + public boolean accepts(CallSiteReference o) { + return getPossibleTargets(src, o).contains(target); + } + }); + } + + private class CHARootNode extends CHANode { + private final Set calls = HashSetFactory.make(); + + protected CHARootNode(IMethod method, Context C) { + super(method, C); + } + + @Override + public Iterator iterateCallSites() { + return calls.iterator(); + } + + @Override + public boolean addTarget(CallSiteReference reference, CGNode target) { + return calls.add(reference); + } + } + + @Override + protected CGNode makeFakeRootNode() throws CancelException { + return new CHARootNode(new FakeRootMethod(cha, options, cache), Everywhere.EVERYWHERE); + } + + @Override + protected CGNode makeFakeWorldClinitNode() throws CancelException { + return new CHARootNode(new FakeWorldClinitMethod(cha, options, cache), Everywhere.EVERYWHERE); + } + + private void closure(CGNode n, boolean fromRoot) throws CancelException { + for(Iterator sites = n.iterateCallSites(); sites.hasNext(); ) { + Iterator methods = getPossibleTargets(sites.next()); + while (methods.hasNext()) { + IMethod target = methods.next(); + if (!target.isAbstract()) { + CGNode callee = getNode(target, Everywhere.EVERYWHERE); + if (callee == null) { + callee = findOrCreateNode(target, Everywhere.EVERYWHERE); + if (fromRoot) { + registerEntrypoint(callee); + } + } + } + } + } + } + + private int clinitPC = 0; + + @Override + public CGNode findOrCreateNode(IMethod method, Context C) throws CancelException { + assert C.equals(Everywhere.EVERYWHERE); + assert !method.isAbstract(); + + CGNode n = getNode(method, C); + if (n == null) { + assert !isInitialized; + n = makeNewNode(method, C); + + IMethod clinit = method.getDeclaringClass().getClassInitializer(); + if (clinit != null && getNode(clinit, Everywhere.EVERYWHERE) == null) { + CGNode cln = makeNewNode(clinit, Everywhere.EVERYWHERE); + CGNode clinits = getFakeWorldClinitNode(); + clinits.addTarget(CallSiteReference.make(clinitPC++, clinit.getReference(), IInvokeInstruction.Dispatch.STATIC), cln); + } + } + return n; + } + + private CGNode makeNewNode(IMethod method, Context C) throws CancelException { + CGNode n; + Key k = new Key(method, C); + n = new CHANode(method, C); + registerNode(k, n); + closure(n, false); + return n; + } + + @Override + protected NumberedEdgeManager getEdgeManager() { + return new NumberedEdgeManager() { + private final Map>> predecessors = HashMapFactory.make(); + + private Set getPreds(CGNode n) { + if (predecessors.containsKey(n) && predecessors.get(n).get() != null) { + return predecessors.get(n).get(); + } else { + Set preds = HashSetFactory.make(); + for(CGNode node : CHACallGraph.this) { + if (getPossibleSites(node, n).hasNext()) { + preds.add(node); + } + } + predecessors.put(n, new SoftReference>(preds)); + return preds; + } + } + + public Iterator getPredNodes(CGNode n) { + return getPreds(n).iterator(); + } + + public int getPredNodeCount(CGNode n) { + return getPreds(n).size(); + } + + public Iterator getSuccNodes(final CGNode n) { + return new FilterIterator(new ComposedIterator(n.iterateCallSites()) { + @Override + public Iterator makeInner(CallSiteReference outer) { + return getPossibleTargets(n, outer).iterator(); + } + }, + new Filter() { + private final MutableIntSet nodes = IntSetUtil.make(); + public boolean accepts(CGNode o) { + if (nodes.contains(o.getGraphNodeId())) { + return false; + } else { + nodes.add(o.getGraphNodeId()); + return true; + } + } + }); + } + + public int getSuccNodeCount(CGNode N) { + return IteratorUtil.count(getSuccNodes(N)); + } + + public void addEdge(CGNode src, CGNode dst) { + assert false; + } + + public void removeEdge(CGNode src, CGNode dst) throws UnsupportedOperationException { + assert false; + } + + public void removeAllIncidentEdges(CGNode node) throws UnsupportedOperationException { + assert false; + } + + public void removeIncomingEdges(CGNode node) throws UnsupportedOperationException { + assert false; + } + + public void removeOutgoingEdges(CGNode node) throws UnsupportedOperationException { + assert false; + } + + public boolean hasEdge(CGNode src, CGNode dst) { + return getPossibleSites(src, dst).hasNext(); + } + + public IntSet getSuccNodeNumbers(CGNode node) { + MutableIntSet result = IntSetUtil.make(); + for(Iterator ss = getSuccNodes(node); ss.hasNext(); ) { + result.add(ss.next().getGraphNodeId()); + } + return result; + } + + public IntSet getPredNodeNumbers(CGNode node) { + MutableIntSet result = IntSetUtil.make(); + for(Iterator ss = getPredNodes(node); ss.hasNext(); ) { + result.add(ss.next().getGraphNodeId()); + } + return result; + } + + }; + } + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/CHAContextInterpreter.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/CHAContextInterpreter.java new file mode 100644 index 000000000..c6ca08d66 --- /dev/null +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/CHAContextInterpreter.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package com.ibm.wala.ipa.callgraph.cha; + +import java.util.Iterator; + +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.ipa.callgraph.CGNode; + +public interface CHAContextInterpreter { + + /** + * Does this object understand the given method? The caller had better check this before inquiring on other properties. + */ + public boolean understands(CGNode node); + + /** + * @return an Iterator of the call statements that may execute in a given method for a given context + */ + public abstract Iterator iterateCallSites(CGNode node); + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/ContextInsensitiveCHAContextInterpreter.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/ContextInsensitiveCHAContextInterpreter.java new file mode 100644 index 000000000..fe2321fbd --- /dev/null +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/cha/ContextInsensitiveCHAContextInterpreter.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package com.ibm.wala.ipa.callgraph.cha; + +import java.util.Iterator; + +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.CodeScanner; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.shrikeCT.InvalidClassFileException; +import com.ibm.wala.util.debug.Assertions; + +public class ContextInsensitiveCHAContextInterpreter implements CHAContextInterpreter { + + public boolean understands(CGNode node) { + return true; + } + + public Iterator iterateCallSites(CGNode node) { + if (node == null) { + throw new IllegalArgumentException("node is null"); + } + try { + return CodeScanner.getCallSites(node.getMethod()).iterator(); + } catch (InvalidClassFileException e) { + e.printStackTrace(); + Assertions.UNREACHABLE(); + return null; + } + } + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/BasicCallGraph.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/BasicCallGraph.java index f2c1f6ad9..fadca3c22 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/BasicCallGraph.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/BasicCallGraph.java @@ -23,7 +23,6 @@ import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.propagation.ReceiverInstanceContext; -import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.shrikeBT.IInvokeInstruction; import com.ibm.wala.types.MethodReference; @@ -42,7 +41,7 @@ import com.ibm.wala.util.graph.traverse.DFS; /** * Basic data structure support for a call graph. */ -public abstract class BasicCallGraph extends AbstractNumberedGraph implements CallGraph { +public abstract class BasicCallGraph extends AbstractNumberedGraph implements CallGraph { private static final boolean DEBUG = false; @@ -61,7 +60,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph imple /** * An object that handles context interpreter functions */ - private SSAContextInterpreter interpreter; + private T interpreter; /** * Set of nodes that are entrypoints for this analysis @@ -81,7 +80,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph imple * * TODO: this is a bit redundant with the nodes Map. Restructure these data structures for space efficiency. */ - final private Map> mr2Nodes = HashMapFactory.make(); + protected final Map> mr2Nodes = HashMapFactory.make(); public BasicCallGraph() { super(); @@ -303,7 +302,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph imple * @param node a call graph node we want information about * @return an object that knows how to interpret information about the node */ - protected SSAContextInterpreter getInterpreter(CGNode node) { + protected T getInterpreter(CGNode node) { if (interpreter == null) { throw new IllegalStateException("must register an interpreter for this call graph"); } @@ -344,7 +343,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph imple return getNode(N.getMethod(), N.getContext()) != null; } - public void setInterpreter(SSAContextInterpreter interpreter) { + public void setInterpreter(T interpreter) { this.interpreter = interpreter; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/ExplicitCallGraph.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/ExplicitCallGraph.java index 62d25d789..275f61f6e 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/ExplicitCallGraph.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/ExplicitCallGraph.java @@ -23,6 +23,7 @@ import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.Context; +import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.shrikeBT.BytecodeConstants; import com.ibm.wala.ssa.DefUse; @@ -50,7 +51,7 @@ import com.ibm.wala.util.intset.SparseIntSet; /** * A call graph which explicitly holds the target for each call site in each node. */ -public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstants { +public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstants { protected final IClassHierarchy cha; diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/rta/ContextInsensitiveRTAInterpreter.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/rta/ContextInsensitiveRTAInterpreter.java index 0abca5ba6..901c6743f 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/rta/ContextInsensitiveRTAInterpreter.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/rta/ContextInsensitiveRTAInterpreter.java @@ -19,6 +19,7 @@ import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.NewSiteReference; import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.cha.ContextInsensitiveCHAContextInterpreter; import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter; import com.ibm.wala.shrikeCT.InvalidClassFileException; import com.ibm.wala.types.FieldReference; @@ -27,7 +28,7 @@ import com.ibm.wala.util.debug.Assertions; /** * Default implementation of MethodContextInterpreter for context-insensitive analysis */ -public abstract class ContextInsensitiveRTAInterpreter implements RTAContextInterpreter, SSAContextInterpreter { +public abstract class ContextInsensitiveRTAInterpreter extends ContextInsensitiveCHAContextInterpreter implements RTAContextInterpreter, SSAContextInterpreter { private final AnalysisCache analysisCache; @@ -52,19 +53,6 @@ public abstract class ContextInsensitiveRTAInterpreter implements RTAContextInte } } - public Iterator iterateCallSites(CGNode node) { - if (node == null) { - throw new IllegalArgumentException("node is null"); - } - try { - return CodeScanner.getCallSites(node.getMethod()).iterator(); - } catch (InvalidClassFileException e) { - e.printStackTrace(); - Assertions.UNREACHABLE(); - return null; - } - } - public Iterator iterateFieldsRead(CGNode node) { if (node == null) { throw new IllegalArgumentException("node is null"); @@ -91,10 +79,6 @@ public abstract class ContextInsensitiveRTAInterpreter implements RTAContextInte } } - public boolean understands(CGNode node) { - return true; - } - public boolean recordFactoryType(CGNode node, IClass klass) { // not a factory type return false; diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/rta/RTAContextInterpreter.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/rta/RTAContextInterpreter.java index 20bfd318f..971d3c041 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/rta/RTAContextInterpreter.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/rta/RTAContextInterpreter.java @@ -12,31 +12,22 @@ package com.ibm.wala.ipa.callgraph.propagation.rta; import java.util.Iterator; -import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.NewSiteReference; import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.cha.CHAContextInterpreter; import com.ibm.wala.types.FieldReference; /** * This object will analyze a method in a context and return information needed for RTA. */ -public interface RTAContextInterpreter { - /** - * Does this object understand the given method? The caller had better check this before inquiring on other properties. - */ - public boolean understands(CGNode node); +public interface RTAContextInterpreter extends CHAContextInterpreter { /** * @return an Iterator of the types that may be allocated by a given method in a given context. */ public abstract Iterator iterateNewSites(CGNode node); - /** - * @return an Iterator of the call statements that may execute in a given method for a given context - */ - public abstract Iterator iterateCallSites(CGNode node); - /** * @return iterator of FieldReference */ diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java index 703bce2da..231e6e773 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java @@ -389,7 +389,7 @@ public class ClassHierarchy implements IClassHierarchy { * @return the set of IMethods that this call can resolve to. * @throws IllegalArgumentException if ref is null */ - public Collection getPossibleTargets(MethodReference ref) { + public Set getPossibleTargets(MethodReference ref) { if (ref == null) { throw new IllegalArgumentException("ref is null"); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/IClassHierarchy.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/IClassHierarchy.java index 3ac22de70..1730b76ce 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/IClassHierarchy.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/IClassHierarchy.java @@ -52,7 +52,7 @@ public interface IClassHierarchy extends Iterable { * @return the set of IMethods that this call can resolve to. * @throws IllegalArgumentException if ref is null */ - public Collection getPossibleTargets(MethodReference ref); + public Set getPossibleTargets(MethodReference ref); /** * Find the possible targets of a call to a method reference where the receiver is of a certain type diff --git a/com.ibm.wala.ide.jsdt.tests/META-INF/MANIFEST.MF b/com.ibm.wala.ide.jsdt.tests/META-INF/MANIFEST.MF index 6a398529e..a0b2ac609 100644 --- a/com.ibm.wala.ide.jsdt.tests/META-INF/MANIFEST.MF +++ b/com.ibm.wala.ide.jsdt.tests/META-INF/MANIFEST.MF @@ -9,7 +9,7 @@ Require-Bundle: com.ibm.wala.core;bundle-version="1.1.3", com.ibm.wala.cast.js;bundle-version="1.0.0", com.ibm.wala.cast.js.rhino;bundle-version="1.0.0", com.ibm.wala.ide.jsdt;bundle-version="1.0.0", - org.eclipse.wst.jsdt.core;bundle-version="1.1.202", + org.eclipse.wst.jsdt.core, org.eclipse.equinox.common;bundle-version="3.6.100", com.ibm.wala.ide.tests;bundle-version="1.1.3", org.eclipse.core.runtime;bundle-version="3.8.0" diff --git a/com.ibm.wala.ide.jsdt.tests/launchers/JSProjectScopeTest.launch b/com.ibm.wala.ide.jsdt.tests/launchers/JSProjectScopeTest.launch index 7752ae2e4..ae1c3177c 100644 --- a/com.ibm.wala.ide.jsdt.tests/launchers/JSProjectScopeTest.launch +++ b/com.ibm.wala.ide.jsdt.tests/launchers/JSProjectScopeTest.launch @@ -26,7 +26,7 @@ - + diff --git a/com.ibm.wala.ide.tests/src/com/ibm/wala/ide/tests/util/EclipseTestUtil.java b/com.ibm.wala.ide.tests/src/com/ibm/wala/ide/tests/util/EclipseTestUtil.java index e3369a6cd..71e9cfc05 100644 --- a/com.ibm.wala.ide.tests/src/com/ibm/wala/ide/tests/util/EclipseTestUtil.java +++ b/com.ibm.wala.ide.tests/src/com/ibm/wala/ide/tests/util/EclipseTestUtil.java @@ -114,7 +114,7 @@ public class EclipseTestUtil { IPath path = new Path("testdata").append(filename); URL url = FileLocator.find(bundle, path, null); - assert url != null; + assert url != null : bundle.toString() + " path " + path.toString(); try { URL fileURL = FileLocator.toFileURL(url); File file = new File(fileURL.getPath()); diff --git a/com.ibm.wala.util/src/com/ibm/wala/util/collections/ComposedIterator.java b/com.ibm.wala.util/src/com/ibm/wala/util/collections/ComposedIterator.java index 48ab315d2..56b46277c 100644 --- a/com.ibm.wala.util/src/com/ibm/wala/util/collections/ComposedIterator.java +++ b/com.ibm.wala.util/src/com/ibm/wala/util/collections/ComposedIterator.java @@ -31,7 +31,7 @@ public abstract class ComposedIterator implements Iterator { break; } } - if (!inner.hasNext()) { + if (inner != null && !inner.hasNext()) { inner = null; } }