private Set<CGNode> findRecursiveMethods(IProgressMonitor progress) throws CancelException { CallGraph cg = sdg.getCallGraph(); GraphReachability<CGNode, CGNode> reach = new GraphReachability<CGNode, CGNode>(cg, new TrueFilter()); progress.subTask("Searching recursive methods"); reach.solve(progress); Set<CGNode> recursive = HashSetFactory.make(); for (CGNode node : cg) { OrdinalSet<CGNode> rset = reach.getReachableSet(node); for (CGNode target : rset) { if (target != node) { OrdinalSet<CGNode> tset = reach.getReachableSet(target); if (tset.contains(node)) { recursive.add(node); break; } } } progress.worked(1); } progress.done(); return recursive; }
private static OrdinalSet<InstanceKey> findReachableInstances( final PointerAnalysis<InstanceKey> pts, final PointerKey pkStart) { final HeapGraph hg = pts.getHeapGraph(); if (!hg.containsNode(pkStart)) { return OrdinalSet.empty(); } final OrdinalSetMapping<InstanceKey> mapping = pts.getInstanceKeyMapping(); final BitVectorIntSet resultSet = new BitVectorIntSet(); final NumberedDFSDiscoverTimeIterator<Object> dfsDiscover = new NumberedDFSDiscoverTimeIterator<Object>(hg, pkStart); while (dfsDiscover.hasNext()) { Object obj = dfsDiscover.next(); if (obj instanceof InstanceKey) { InstanceKey ik = (InstanceKey) obj; final int ikNum = mapping.getMappedIndex(ik); resultSet.add(ikNum); } } final OrdinalSet<InstanceKey> reachable = new OrdinalSet<InstanceKey>(resultSet, mapping); return reachable; }
private Set<CallNode> compute(IProgressMonitor progress) throws CancelException { Set<CallNode> calls = HashSetFactory.make(); Set<CGNode> recursive = findRecursiveMethods(progress); Set<CGNode> loop = findLoopingMethods(progress); CallGraph cg = sdg.getCallGraph(); Graph<CGNode> inverted = GraphInverter.invert(cg); GraphReachability<CGNode, CGNode> reach = new GraphReachability<CGNode, CGNode>(inverted, new TrueFilter()); progress.subTask("Searching potential non-returning calls"); reach.solve(progress); Set<CGNode> roots = HashSetFactory.make(loop); roots.addAll(recursive); OrdinalSet<CGNode> potential = OrdinalSet.empty(); for (CGNode root : roots) { OrdinalSet<CGNode> reached = reach.getReachableSet(root); potential = OrdinalSet.unify(potential, reached); } Set<CGNode> terminating = HashSetFactory.make(); Set<CGNode> nonTerminating = HashSetFactory.make(); for (CGNode node : cg) { if (potential.contains(node)) { nonTerminating.add(node); } else { terminating.add(node); } } for (Call call : sdg.getAllCalls()) { if (nonTerminating.contains(call.callee.getCallGraphNode())) { calls.add(call.node); } } progress.done(); computeControlDependence(calls, progress); return calls; }
@Test public void testZeroOneContainerCopyOf() throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException { AnalysisScope scope = CallGraphTestUtil.makeJ2SEAnalysisScope( TestConstants.WALA_TESTDATA, CallGraphTestUtil.REGRESSION_EXCLUSIONS); ClassHierarchy cha = ClassHierarchy.make(scope); Iterable<Entrypoint> entrypoints = Util.makeMainEntrypoints(scope, cha, "Ldemandpa/TestArraysCopyOf"); AnalysisOptions options = CallGraphTestUtil.makeAnalysisOptions(scope, entrypoints); AnalysisCache cache = new AnalysisCache(); CallGraphBuilder builder = Util.makeZeroOneContainerCFABuilder(options, cache, cha, scope); CallGraph cg = builder.makeCallGraph(options, null); PointerAnalysis pa = builder.getPointerAnalysis(); CGNode mainMethod = AbstractPtrTest.findMainMethod(cg); PointerKey keyToQuery = AbstractPtrTest.getParam(mainMethod, "testThisVar", pa.getHeapModel()); OrdinalSet<? extends InstanceKey> pointsToSet = pa.getPointsToSet(keyToQuery); Assert.assertEquals(1, pointsToSet.size()); }