Loading sdg-core/src/main/java/tfm/graphs/sdg/SDG.java +7 −1 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.NameExpr; import com.github.javaparser.ast.stmt.ExpressionStmt; import tfm.arcs.Arc; import tfm.arcs.pdg.ControlDependencyArc; import tfm.arcs.pdg.DataDependencyArc; import tfm.arcs.sdg.CallArc; Loading @@ -13,6 +14,7 @@ import tfm.arcs.sdg.SummaryArc; import tfm.graphs.Buildable; import tfm.graphs.Graph; import tfm.graphs.cfg.CFG; import tfm.graphs.sdg.sumarcs.AnalysisSummaryArcsBuilder; import tfm.graphs.sdg.sumarcs.NaiveSummaryArcsBuilder; import tfm.nodes.GraphNode; import tfm.nodes.VariableAction; Loading @@ -21,7 +23,10 @@ import tfm.slicing.Slice; import tfm.slicing.Sliceable; import tfm.slicing.SlicingCriterion; import tfm.utils.Context; import tfm.utils.Logger; import java.io.StringWriter; import java.io.Writer; import java.util.*; import java.util.stream.Collectors; Loading @@ -48,8 +53,9 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat nodeList.accept(createBuilder(), new Context()); Set<GraphNode<?>> vertices = Set.copyOf(vertexSet()); vertices.forEach(n -> new MethodCallReplacerVisitor(this).startVisit(n)); new NaiveSummaryArcsBuilder(this).visit(); compilationUnits = nodeList; // new NaiveSummaryArcsBuilder(this).visit(); new AnalysisSummaryArcsBuilder(this).visit(); built = true; } Loading sdg-core/src/main/java/tfm/graphs/sdg/sumarcs/AnalysisSummaryArcsBuilder.java +78 −15 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ package tfm.graphs.sdg.sumarcs; import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.MethodCallExpr; import tfm.arcs.Arc; import tfm.arcs.sdg.CallArc; import tfm.graphs.CallGraph; Loading @@ -16,11 +15,18 @@ import tfm.utils.Utils; import java.util.*; import java.util.stream.Collectors; public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { /** * Performs a fixed point analysis over the call graph of a given SDG */ public class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { private static class SummaryArcPair { FormalIONode in; FormalIONode out; GraphNode<?> out; // out node is either FormalIONode or METHOD_OUTPUT SummaryArcPair(FormalIONode in, GraphNode<?> out) { this.in = in; this.out = out; } } private final SDG sdg; Loading Loading @@ -50,7 +56,6 @@ public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { return vertexDataMap.get(vertex); } // Al acabar, los summary edges estan colocados @Override public void visit() { assert !built; Loading Loading @@ -86,8 +91,6 @@ public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { GraphNode<MethodDeclaration> methodDeclarationNode = optionalMethodDeclarationNode.get(); // Copiar los summaries que hay en 'vertexDataMap' a todas las llamadas a metodo contenidas en este vertices (ver outgoingEdges) // Get call arcs from this declaration Set<CallArc> methodCallExprNodes = sdg.incomingEdgesOf(methodDeclarationNode).stream() .filter(Arc::isCallArc) Loading @@ -99,18 +102,29 @@ public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { for (SummaryArcPair summaryArcPair : vertexDataMap.getOrDefault(declaration, Utils.emptySet())) { FormalIONode inFormalNode = summaryArcPair.in; FormalIONode outFormalNode = summaryArcPair.out; GraphNode<?> outFormalNode = summaryArcPair.out; Optional<ActualIONode> optionalIn = sdg.outgoingEdgesOf(methodCallNode).stream() .filter(arc -> (sdg.getEdgeTarget(arc)).getNodeType() == NodeType.ACTUAL_IN) .filter(arc -> (sdg.getEdgeTarget(arc)).getNodeType().is(NodeType.ACTUAL_IN)) .map(arc -> (ActualIONode) sdg.getEdgeTarget(arc)) .filter(actualIONode -> actualIONode.matchesFormalIO(inFormalNode)) .findFirst(); Optional<ActualIONode> optionalOut = sdg.outgoingEdgesOf(methodCallNode).stream() .filter(arc -> (sdg.getEdgeTarget(arc)).getNodeType() == NodeType.ACTUAL_OUT) .map(arc -> (ActualIONode) sdg.getEdgeTarget(arc)) .filter(actualIONode -> actualIONode.matchesFormalIO(outFormalNode)) Optional<? extends GraphNode<?>> optionalOut = sdg.outgoingEdgesOf(methodCallNode).stream() .map(sdg::getEdgeTarget) .filter(node -> node.getNodeType().is(NodeType.ACTUAL_OUT)) .filter(actualNode -> { if (actualNode instanceof ActualIONode) { return outFormalNode instanceof FormalIONode && ((ActualIONode) actualNode).matchesFormalIO((FormalIONode) outFormalNode); } // otherwise, actualNode must be METHOD_CALL_RETURN if (actualNode.getNodeType() != NodeType.METHOD_CALL_RETURN) { return false; } return outFormalNode.getNodeType() == NodeType.METHOD_CALL_NORMAL_RETURN; }) .findFirst(); if (optionalIn.isEmpty() || optionalOut.isEmpty()) { Loading @@ -123,8 +137,57 @@ public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { } protected Set<SummaryArcPair> computeSummaryArcs(CallableDeclaration<?> declaration) { // Para cada formal-out, hacer slice intraprocedural. Anotar los formal-in incluidos. IMPORTANTE, SUMMARY SON INTRAPROC. // TODO return null; Optional<GraphNode<MethodDeclaration>> optionalMethodDeclarationNode = sdg.findNodeByASTNode(declaration.asMethodDeclaration()); if (optionalMethodDeclarationNode.isEmpty()) { return Utils.emptySet(); } GraphNode<MethodDeclaration> methodDeclarationNode = optionalMethodDeclarationNode.get(); // Get formal out nodes from declaration Set<GraphNode<?>> formalOutNodes = sdg.outgoingEdgesOf(methodDeclarationNode).stream() .filter(Arc::isControlDependencyArc) .map(sdg::getEdgeTarget) .filter(node -> node.getNodeType().is(NodeType.FORMAL_OUT)) .collect(Collectors.toSet()); Set<SummaryArcPair> res = new HashSet<>(); for (GraphNode<?> formalOutNode : formalOutNodes) { for (FormalIONode formalInNode : findReachableFormalInNodes(formalOutNode)) { res.add(new SummaryArcPair(formalInNode, formalOutNode)); } } return res; } private Set<FormalIONode> findReachableFormalInNodes(GraphNode<?> formalOutNode) { return this.doFindReachableFormalInNodes(formalOutNode, Utils.emptySet()); } private Set<FormalIONode> doFindReachableFormalInNodes(GraphNode<?> root, Set<Long> visited) { visited.add(root.getId()); Set<FormalIONode> res = Utils.emptySet(); if (root.getNodeType().is(NodeType.FORMAL_IN)) { res.add((FormalIONode) root); } else { for (Arc arc : sdg.incomingEdgesOf(root)) { GraphNode<?> nextNode = sdg.getEdgeSource(arc); if (visited.contains(nextNode.getId())) { continue; } if (arc.isDataDependencyArc() || arc.isControlDependencyArc() || arc.isSummaryArc()) { res.addAll(this.doFindReachableFormalInNodes(nextNode, visited)); } } } return res; } } sdg-core/src/test/res/programs/sdg/Example1.java +2 −2 File changed.Contains only whitespace changes. Show changes Loading
sdg-core/src/main/java/tfm/graphs/sdg/SDG.java +7 −1 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ import com.github.javaparser.ast.NodeList; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.NameExpr; import com.github.javaparser.ast.stmt.ExpressionStmt; import tfm.arcs.Arc; import tfm.arcs.pdg.ControlDependencyArc; import tfm.arcs.pdg.DataDependencyArc; import tfm.arcs.sdg.CallArc; Loading @@ -13,6 +14,7 @@ import tfm.arcs.sdg.SummaryArc; import tfm.graphs.Buildable; import tfm.graphs.Graph; import tfm.graphs.cfg.CFG; import tfm.graphs.sdg.sumarcs.AnalysisSummaryArcsBuilder; import tfm.graphs.sdg.sumarcs.NaiveSummaryArcsBuilder; import tfm.nodes.GraphNode; import tfm.nodes.VariableAction; Loading @@ -21,7 +23,10 @@ import tfm.slicing.Slice; import tfm.slicing.Sliceable; import tfm.slicing.SlicingCriterion; import tfm.utils.Context; import tfm.utils.Logger; import java.io.StringWriter; import java.io.Writer; import java.util.*; import java.util.stream.Collectors; Loading @@ -48,8 +53,9 @@ public class SDG extends Graph implements Sliceable, Buildable<NodeList<Compilat nodeList.accept(createBuilder(), new Context()); Set<GraphNode<?>> vertices = Set.copyOf(vertexSet()); vertices.forEach(n -> new MethodCallReplacerVisitor(this).startVisit(n)); new NaiveSummaryArcsBuilder(this).visit(); compilationUnits = nodeList; // new NaiveSummaryArcsBuilder(this).visit(); new AnalysisSummaryArcsBuilder(this).visit(); built = true; } Loading
sdg-core/src/main/java/tfm/graphs/sdg/sumarcs/AnalysisSummaryArcsBuilder.java +78 −15 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ package tfm.graphs.sdg.sumarcs; import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.expr.MethodCallExpr; import tfm.arcs.Arc; import tfm.arcs.sdg.CallArc; import tfm.graphs.CallGraph; Loading @@ -16,11 +15,18 @@ import tfm.utils.Utils; import java.util.*; import java.util.stream.Collectors; public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { /** * Performs a fixed point analysis over the call graph of a given SDG */ public class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { private static class SummaryArcPair { FormalIONode in; FormalIONode out; GraphNode<?> out; // out node is either FormalIONode or METHOD_OUTPUT SummaryArcPair(FormalIONode in, GraphNode<?> out) { this.in = in; this.out = out; } } private final SDG sdg; Loading Loading @@ -50,7 +56,6 @@ public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { return vertexDataMap.get(vertex); } // Al acabar, los summary edges estan colocados @Override public void visit() { assert !built; Loading Loading @@ -86,8 +91,6 @@ public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { GraphNode<MethodDeclaration> methodDeclarationNode = optionalMethodDeclarationNode.get(); // Copiar los summaries que hay en 'vertexDataMap' a todas las llamadas a metodo contenidas en este vertices (ver outgoingEdges) // Get call arcs from this declaration Set<CallArc> methodCallExprNodes = sdg.incomingEdgesOf(methodDeclarationNode).stream() .filter(Arc::isCallArc) Loading @@ -99,18 +102,29 @@ public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { for (SummaryArcPair summaryArcPair : vertexDataMap.getOrDefault(declaration, Utils.emptySet())) { FormalIONode inFormalNode = summaryArcPair.in; FormalIONode outFormalNode = summaryArcPair.out; GraphNode<?> outFormalNode = summaryArcPair.out; Optional<ActualIONode> optionalIn = sdg.outgoingEdgesOf(methodCallNode).stream() .filter(arc -> (sdg.getEdgeTarget(arc)).getNodeType() == NodeType.ACTUAL_IN) .filter(arc -> (sdg.getEdgeTarget(arc)).getNodeType().is(NodeType.ACTUAL_IN)) .map(arc -> (ActualIONode) sdg.getEdgeTarget(arc)) .filter(actualIONode -> actualIONode.matchesFormalIO(inFormalNode)) .findFirst(); Optional<ActualIONode> optionalOut = sdg.outgoingEdgesOf(methodCallNode).stream() .filter(arc -> (sdg.getEdgeTarget(arc)).getNodeType() == NodeType.ACTUAL_OUT) .map(arc -> (ActualIONode) sdg.getEdgeTarget(arc)) .filter(actualIONode -> actualIONode.matchesFormalIO(outFormalNode)) Optional<? extends GraphNode<?>> optionalOut = sdg.outgoingEdgesOf(methodCallNode).stream() .map(sdg::getEdgeTarget) .filter(node -> node.getNodeType().is(NodeType.ACTUAL_OUT)) .filter(actualNode -> { if (actualNode instanceof ActualIONode) { return outFormalNode instanceof FormalIONode && ((ActualIONode) actualNode).matchesFormalIO((FormalIONode) outFormalNode); } // otherwise, actualNode must be METHOD_CALL_RETURN if (actualNode.getNodeType() != NodeType.METHOD_CALL_RETURN) { return false; } return outFormalNode.getNodeType() == NodeType.METHOD_CALL_NORMAL_RETURN; }) .findFirst(); if (optionalIn.isEmpty() || optionalOut.isEmpty()) { Loading @@ -123,8 +137,57 @@ public abstract class AnalysisSummaryArcsBuilder extends SummaryArcsBuilder { } protected Set<SummaryArcPair> computeSummaryArcs(CallableDeclaration<?> declaration) { // Para cada formal-out, hacer slice intraprocedural. Anotar los formal-in incluidos. IMPORTANTE, SUMMARY SON INTRAPROC. // TODO return null; Optional<GraphNode<MethodDeclaration>> optionalMethodDeclarationNode = sdg.findNodeByASTNode(declaration.asMethodDeclaration()); if (optionalMethodDeclarationNode.isEmpty()) { return Utils.emptySet(); } GraphNode<MethodDeclaration> methodDeclarationNode = optionalMethodDeclarationNode.get(); // Get formal out nodes from declaration Set<GraphNode<?>> formalOutNodes = sdg.outgoingEdgesOf(methodDeclarationNode).stream() .filter(Arc::isControlDependencyArc) .map(sdg::getEdgeTarget) .filter(node -> node.getNodeType().is(NodeType.FORMAL_OUT)) .collect(Collectors.toSet()); Set<SummaryArcPair> res = new HashSet<>(); for (GraphNode<?> formalOutNode : formalOutNodes) { for (FormalIONode formalInNode : findReachableFormalInNodes(formalOutNode)) { res.add(new SummaryArcPair(formalInNode, formalOutNode)); } } return res; } private Set<FormalIONode> findReachableFormalInNodes(GraphNode<?> formalOutNode) { return this.doFindReachableFormalInNodes(formalOutNode, Utils.emptySet()); } private Set<FormalIONode> doFindReachableFormalInNodes(GraphNode<?> root, Set<Long> visited) { visited.add(root.getId()); Set<FormalIONode> res = Utils.emptySet(); if (root.getNodeType().is(NodeType.FORMAL_IN)) { res.add((FormalIONode) root); } else { for (Arc arc : sdg.incomingEdgesOf(root)) { GraphNode<?> nextNode = sdg.getEdgeSource(arc); if (visited.contains(nextNode.getId())) { continue; } if (arc.isDataDependencyArc() || arc.isControlDependencyArc() || arc.isSummaryArc()) { res.addAll(this.doFindReachableFormalInNodes(nextNode, visited)); } } } return res; } }
sdg-core/src/test/res/programs/sdg/Example1.java +2 −2 File changed.Contains only whitespace changes. Show changes