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 extends CGNode> 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;
}
}