Loading iacfg/src/main/java/es/upv/mist/slicing/graphs/icfg/ICFG.java +74 −2 Original line number Diff line number Diff line Loading @@ -86,10 +86,22 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< protected final Map<CallSCR, Set<IntraSCR>> transitiveMap = new HashMap<>(); /** The strongly connected components of the {@link ICFG}, computed while ignoring * interprocedural edges that connect {@link #cSCRs} nodes. <br> * Fulfils steps 2-3 of the Nanda-Ramesh topological numbers algorithm. */ * Fulfils steps 2-3 of the Nanda-Ramesh topological numbers' algorithm. */ protected IntraSCRGraph intraSCRs; /** Non-Recursive interprocedural Arcs from {@link #intraSCRs} */ protected Set<Triple<GraphNode<?>, GraphNode<?>, ControlFlowArc>> interprocNonRecArcs = new HashSet<>(); /** A list of all {@link #intraSCRs} that have an callSite type in Nanda-Ramesh algorithm */ protected Set<IntraSCR> callSiteIntraSCRs = new HashSet<>(); /** A list of all {@link #intraSCRs} that have an returnSite type in Nanda-Ramesh algorithm */ protected Set<IntraSCR> returnSiteIntraSCRs = new HashSet<>(); /** A map to locate the correspondent call node from a return node */ protected final Map<IntraSCR, IntraSCR> returnToCorrespondentCallSiteMap = new HashMap<>(); /** A map to locate the {@link #intraSCRs} within a call*/ protected final Map<IntraSCR, Set<IntraSCR>> callNodeProcessMap = new HashMap<>(); /** A map to get the topological number associated to the {@link #intraSCRs} */ protected final Map<Integer, IntraSCR> topologicalNumbersMap = new HashMap<>(); /** counter for topologicalNumbers */ protected int topologicalNumber = 0; public void build(NodeList<CompilationUnit> units) { createClassGraph(units); Loading @@ -111,7 +123,53 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< computeCallSCRs(); computeIntraSCRs(); buildISCR(); System.out.println("testing"); generateTopologicalNumbers(); } private void generateTopologicalNumbers() { Set<IntraSCR> proccessedIntraSCRs = new HashSet<>(); Stack<IntraSCR> callStack = new Stack<>(); // get exit node IntraSCR exitNode = null; for (IntraSCR cSCRNode : intraSCRs.vertexSet()) { if (intraSCRs.outDegreeOf(cSCRNode) == 0) { exitNode = cSCRNode; break; } } //callGetTopologicalNumber for exitNode (predecessors are visited inside) getTopologicalNumber(exitNode, proccessedIntraSCRs, callStack); } private <V> void getTopologicalNumber(IntraSCR node, Set<IntraSCR> proccessedIntraSCRs, Stack<IntraSCR> callStack) { if(proccessedIntraSCRs.contains(node)) { return; } for(IntraSCR predecessor : Graphs.predecessorListOf(intraSCRs, node)) { if(callSiteIntraSCRs.contains(predecessor) && !callStack.isEmpty() && predecessor == callStack.peek()) { callStack.pop(); getTopologicalNumber(predecessor, proccessedIntraSCRs, callStack); } else if(returnSiteIntraSCRs.contains(predecessor) ) { IntraSCR callNode = returnToCorrespondentCallSiteMap.get(predecessor); callStack.push(callNode); getTopologicalNumber(predecessor, proccessedIntraSCRs, callStack); if(callNodeProcessMap.containsKey(callNode)) { for (IntraSCR intraSCR : callNodeProcessMap.get(callNode)) { proccessedIntraSCRs.remove(intraSCR); } } } else { if(!callStack.isEmpty()) { callNodeProcessMap.computeIfAbsent(callStack.peek(), k -> new HashSet<>()).add(predecessor); } getTopologicalNumber(predecessor, proccessedIntraSCRs, callStack); } } node.addTopologicalNumber(topologicalNumber); topologicalNumber++; proccessedIntraSCRs.add(node); } private void addEdgesToIntraSCRs(Set<Triple<GraphNode<?>, GraphNode<?>, ControlFlowArc>> deletedArcs) { Loading Loading @@ -205,6 +263,7 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< } buildISCRGraph(mainIntraSCR, processedIntraSCRs); deleteCallReturnEdges(); deleteMainExitEdge(mainIntraSCR); getMainProcess(mainIntraSCR); } Loading @@ -222,6 +281,15 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< } } private void deleteMainExitEdge(IntraSCR mainIntraSCR) { IntraSCR exitNode = intraSCRs.outgoingEdgesOf(mainIntraSCR).stream() .map(intraSCRs::getEdgeTarget) .filter(target -> target.vertexSet().stream().anyMatch(node -> node instanceof MethodExitNode)) .findFirst().orElseThrow(); intraSCRs.removeEdge(mainIntraSCR, exitNode); } private void deleteCallReturnEdges() { Set<DefaultEdge> toBeDeletedSet = new HashSet<>(); for (DefaultEdge e : intraSCRs.edgeSet()) { Loading @@ -233,6 +301,7 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< for(GraphNode<?> src : source.vertexSet()) { for(GraphNode<?> tgt : target.vertexSet()) { if(src instanceof CallNode && tgt instanceof CallNode.Return) { returnToCorrespondentCallSiteMap.put(target, source); toBeDeletedSet.add(e); } } Loading Loading @@ -299,12 +368,15 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< if (graphNode instanceof CallNode) { for (Triple<GraphNode<?>, GraphNode<?>, ControlFlowArc> arc : interprocNonRecArcs) { if (graphNode.equals(arc.getFirst())) { callSiteIntraSCRs.add(intraSCR); @SuppressWarnings("unchecked") GraphNode<CallableDeclaration<?>> enterNode = (GraphNode<CallableDeclaration<?>>) arc.getSecond(); IntraSCR enterIntraSCR = getEnterIntraSCR(enterNode); buildISCRGraph(enterIntraSCR, processedIntraSCRs); } } } else if(graphNode instanceof CallNode.Return){ returnSiteIntraSCRs.add(intraSCR); } } else { throw new IllegalStateException("The intraSCRs is empty"); Loading iacfg/src/main/java/es/upv/mist/slicing/graphs/scrs/IntraSCR.java +13 −0 Original line number Diff line number Diff line Loading @@ -5,7 +5,9 @@ import es.upv.mist.slicing.graphs.icfg.ICFG; import es.upv.mist.slicing.nodes.GraphNode; import org.jgrapht.Graph; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; /** * A strongly connected region (or component) in a {@link ICFG}. Loading @@ -13,9 +15,20 @@ import java.util.Set; */ public class IntraSCR extends AbstractSCR<GraphNode<?>, Arc> { private static int nextId = 1; private final Set<Integer> topologicalNumberSet = new HashSet<>(); public IntraSCR(Graph<GraphNode<?>, Arc> base, Set<? extends GraphNode<?>> vertexSubset, Set<? extends Arc> edgeSubset) { super(base, vertexSubset, edgeSubset); this.id = nextId++; } public void addTopologicalNumber(Integer topologicalNumber) { this.topologicalNumberSet.add(topologicalNumber); } public String getTopologicalNumber() { return this.topologicalNumberSet.stream() .map(String::valueOf) .collect(Collectors.joining("-")); } } iacfg/src/test/java/es/upv/mist/slicing/graphs/icfg/GraphLogIntraSCR.java +1 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,7 @@ public abstract class GraphLogIntraSCR<G extends IntraSCRGraph> { protected DOTAttributes vertexAttributes(IntraSCR vertex) { DOTAttributes res = new DOTAttributes(); res.set("label", "X" + vertex.getId() + "\n" + vertex.vertexSet().stream() res.set("label", "X" + vertex.getId() + "\n" + "TOP-" + vertex.getTopologicalNumber() + "\n" + vertex.vertexSet().stream() .map(graphNode -> "%04d: %s".formatted(graphNode.getId(), graphNode.getLabel())) .sorted() .collect(Collectors.joining("\n"))); Loading iacfg/src/test/java/es/upv/mist/slicing/graphs/icfg/ICFGTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ public class ICFGTest { StaticJavaParser.getConfiguration().setAttributeComments(false); StaticTypeSolver.addTypeSolverJRE(); createGraph("TestInicial.java", "grafoInicial"); /*createGraph("TestInicial.java", "grafoInicial"); System.out.println("Grafo 1 generado..."); createGraph("TestGlobalVariables.java", "grafoGlobalVariables"); Loading @@ -28,6 +28,7 @@ public class ICFGTest { createGraph("TestExamplePaper.java", "grafoPaper"); System.out.println("Grafo 5 generado..."); */ createGraph("TestExamplePaperSimple.java", "grafoPaperSimple"); System.out.println("Grafo 6 generado..."); Loading Loading
iacfg/src/main/java/es/upv/mist/slicing/graphs/icfg/ICFG.java +74 −2 Original line number Diff line number Diff line Loading @@ -86,10 +86,22 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< protected final Map<CallSCR, Set<IntraSCR>> transitiveMap = new HashMap<>(); /** The strongly connected components of the {@link ICFG}, computed while ignoring * interprocedural edges that connect {@link #cSCRs} nodes. <br> * Fulfils steps 2-3 of the Nanda-Ramesh topological numbers algorithm. */ * Fulfils steps 2-3 of the Nanda-Ramesh topological numbers' algorithm. */ protected IntraSCRGraph intraSCRs; /** Non-Recursive interprocedural Arcs from {@link #intraSCRs} */ protected Set<Triple<GraphNode<?>, GraphNode<?>, ControlFlowArc>> interprocNonRecArcs = new HashSet<>(); /** A list of all {@link #intraSCRs} that have an callSite type in Nanda-Ramesh algorithm */ protected Set<IntraSCR> callSiteIntraSCRs = new HashSet<>(); /** A list of all {@link #intraSCRs} that have an returnSite type in Nanda-Ramesh algorithm */ protected Set<IntraSCR> returnSiteIntraSCRs = new HashSet<>(); /** A map to locate the correspondent call node from a return node */ protected final Map<IntraSCR, IntraSCR> returnToCorrespondentCallSiteMap = new HashMap<>(); /** A map to locate the {@link #intraSCRs} within a call*/ protected final Map<IntraSCR, Set<IntraSCR>> callNodeProcessMap = new HashMap<>(); /** A map to get the topological number associated to the {@link #intraSCRs} */ protected final Map<Integer, IntraSCR> topologicalNumbersMap = new HashMap<>(); /** counter for topologicalNumbers */ protected int topologicalNumber = 0; public void build(NodeList<CompilationUnit> units) { createClassGraph(units); Loading @@ -111,7 +123,53 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< computeCallSCRs(); computeIntraSCRs(); buildISCR(); System.out.println("testing"); generateTopologicalNumbers(); } private void generateTopologicalNumbers() { Set<IntraSCR> proccessedIntraSCRs = new HashSet<>(); Stack<IntraSCR> callStack = new Stack<>(); // get exit node IntraSCR exitNode = null; for (IntraSCR cSCRNode : intraSCRs.vertexSet()) { if (intraSCRs.outDegreeOf(cSCRNode) == 0) { exitNode = cSCRNode; break; } } //callGetTopologicalNumber for exitNode (predecessors are visited inside) getTopologicalNumber(exitNode, proccessedIntraSCRs, callStack); } private <V> void getTopologicalNumber(IntraSCR node, Set<IntraSCR> proccessedIntraSCRs, Stack<IntraSCR> callStack) { if(proccessedIntraSCRs.contains(node)) { return; } for(IntraSCR predecessor : Graphs.predecessorListOf(intraSCRs, node)) { if(callSiteIntraSCRs.contains(predecessor) && !callStack.isEmpty() && predecessor == callStack.peek()) { callStack.pop(); getTopologicalNumber(predecessor, proccessedIntraSCRs, callStack); } else if(returnSiteIntraSCRs.contains(predecessor) ) { IntraSCR callNode = returnToCorrespondentCallSiteMap.get(predecessor); callStack.push(callNode); getTopologicalNumber(predecessor, proccessedIntraSCRs, callStack); if(callNodeProcessMap.containsKey(callNode)) { for (IntraSCR intraSCR : callNodeProcessMap.get(callNode)) { proccessedIntraSCRs.remove(intraSCR); } } } else { if(!callStack.isEmpty()) { callNodeProcessMap.computeIfAbsent(callStack.peek(), k -> new HashSet<>()).add(predecessor); } getTopologicalNumber(predecessor, proccessedIntraSCRs, callStack); } } node.addTopologicalNumber(topologicalNumber); topologicalNumber++; proccessedIntraSCRs.add(node); } private void addEdgesToIntraSCRs(Set<Triple<GraphNode<?>, GraphNode<?>, ControlFlowArc>> deletedArcs) { Loading Loading @@ -205,6 +263,7 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< } buildISCRGraph(mainIntraSCR, processedIntraSCRs); deleteCallReturnEdges(); deleteMainExitEdge(mainIntraSCR); getMainProcess(mainIntraSCR); } Loading @@ -222,6 +281,15 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< } } private void deleteMainExitEdge(IntraSCR mainIntraSCR) { IntraSCR exitNode = intraSCRs.outgoingEdgesOf(mainIntraSCR).stream() .map(intraSCRs::getEdgeTarget) .filter(target -> target.vertexSet().stream().anyMatch(node -> node instanceof MethodExitNode)) .findFirst().orElseThrow(); intraSCRs.removeEdge(mainIntraSCR, exitNode); } private void deleteCallReturnEdges() { Set<DefaultEdge> toBeDeletedSet = new HashSet<>(); for (DefaultEdge e : intraSCRs.edgeSet()) { Loading @@ -233,6 +301,7 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< for(GraphNode<?> src : source.vertexSet()) { for(GraphNode<?> tgt : target.vertexSet()) { if(src instanceof CallNode && tgt instanceof CallNode.Return) { returnToCorrespondentCallSiteMap.put(target, source); toBeDeletedSet.add(e); } } Loading Loading @@ -299,12 +368,15 @@ public class ICFG extends es.upv.mist.slicing.graphs.Graph implements Buildable< if (graphNode instanceof CallNode) { for (Triple<GraphNode<?>, GraphNode<?>, ControlFlowArc> arc : interprocNonRecArcs) { if (graphNode.equals(arc.getFirst())) { callSiteIntraSCRs.add(intraSCR); @SuppressWarnings("unchecked") GraphNode<CallableDeclaration<?>> enterNode = (GraphNode<CallableDeclaration<?>>) arc.getSecond(); IntraSCR enterIntraSCR = getEnterIntraSCR(enterNode); buildISCRGraph(enterIntraSCR, processedIntraSCRs); } } } else if(graphNode instanceof CallNode.Return){ returnSiteIntraSCRs.add(intraSCR); } } else { throw new IllegalStateException("The intraSCRs is empty"); Loading
iacfg/src/main/java/es/upv/mist/slicing/graphs/scrs/IntraSCR.java +13 −0 Original line number Diff line number Diff line Loading @@ -5,7 +5,9 @@ import es.upv.mist.slicing.graphs.icfg.ICFG; import es.upv.mist.slicing.nodes.GraphNode; import org.jgrapht.Graph; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; /** * A strongly connected region (or component) in a {@link ICFG}. Loading @@ -13,9 +15,20 @@ import java.util.Set; */ public class IntraSCR extends AbstractSCR<GraphNode<?>, Arc> { private static int nextId = 1; private final Set<Integer> topologicalNumberSet = new HashSet<>(); public IntraSCR(Graph<GraphNode<?>, Arc> base, Set<? extends GraphNode<?>> vertexSubset, Set<? extends Arc> edgeSubset) { super(base, vertexSubset, edgeSubset); this.id = nextId++; } public void addTopologicalNumber(Integer topologicalNumber) { this.topologicalNumberSet.add(topologicalNumber); } public String getTopologicalNumber() { return this.topologicalNumberSet.stream() .map(String::valueOf) .collect(Collectors.joining("-")); } }
iacfg/src/test/java/es/upv/mist/slicing/graphs/icfg/GraphLogIntraSCR.java +1 −1 Original line number Diff line number Diff line Loading @@ -140,7 +140,7 @@ public abstract class GraphLogIntraSCR<G extends IntraSCRGraph> { protected DOTAttributes vertexAttributes(IntraSCR vertex) { DOTAttributes res = new DOTAttributes(); res.set("label", "X" + vertex.getId() + "\n" + vertex.vertexSet().stream() res.set("label", "X" + vertex.getId() + "\n" + "TOP-" + vertex.getTopologicalNumber() + "\n" + vertex.vertexSet().stream() .map(graphNode -> "%04d: %s".formatted(graphNode.getId(), graphNode.getLabel())) .sorted() .collect(Collectors.joining("\n"))); Loading
iacfg/src/test/java/es/upv/mist/slicing/graphs/icfg/ICFGTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ public class ICFGTest { StaticJavaParser.getConfiguration().setAttributeComments(false); StaticTypeSolver.addTypeSolverJRE(); createGraph("TestInicial.java", "grafoInicial"); /*createGraph("TestInicial.java", "grafoInicial"); System.out.println("Grafo 1 generado..."); createGraph("TestGlobalVariables.java", "grafoGlobalVariables"); Loading @@ -28,6 +28,7 @@ public class ICFGTest { createGraph("TestExamplePaper.java", "grafoPaper"); System.out.println("Grafo 5 generado..."); */ createGraph("TestExamplePaperSimple.java", "grafoPaperSimple"); System.out.println("Grafo 6 generado..."); Loading