Loading src/main/java/tfm/exec/PDGLog.java +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ public class PDGLog extends GraphLog<PDG> { Logger.log("Nodes with variable info"); Logger.log(graph.vertexSet().stream() .sorted(Comparator.comparingInt(GraphNode::getId)) .sorted(Comparator.comparingLong(GraphNode::getId)) .map(node -> String.format("GraphNode { id: %s, instruction: %s, declared: %s, defined: %s, used: %s }", node.getId(), Loading src/main/java/tfm/graphs/Graph.java +10 −143 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ import tfm.nodes.NodeFactory; import tfm.utils.ASTUtils; import java.util.*; import java.util.function.Consumer; import java.util.stream.Collectors; /** Loading @@ -17,59 +16,25 @@ import java.util.stream.Collectors; * */ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { protected static final int DEFAULT_VERTEX_START_ID = 0; private int nextVertexId; public Graph() { this(DEFAULT_VERTEX_START_ID); } protected Graph(int vertexStartId) { protected Graph() { super(null, null, false); this.nextVertexId = vertexStartId; } private <ASTNode extends Node> GraphNode<ASTNode> addNode(GraphNode<ASTNode> node) { this.addVertex(node); return node; } private <ASTNode extends Node> GraphNode<ASTNode> addNode(int id, String instruction, ASTNode node) { GraphNode<ASTNode> newNode = NodeFactory.graphNode(id, instruction, node); return this.addNode(newNode); } public <ASTNode extends Node> GraphNode<ASTNode> addNode(String instruction, ASTNode node) { return this.addNode(getNextVertexId(), instruction, node); } /** * Adds the given node to the graph. * * One must be careful with this method, as the given node will have * an id corresponding to the graph in which it was created, and may not fit * in the current graph. * * @param node the node to add to the graph * @param copyId whether to copy the node id or generate a new one * @return the node instance added to the graph */ public <ASTNode extends Node> GraphNode<ASTNode> addNode(GraphNode<ASTNode> node, boolean copyId) { GraphNode<ASTNode> copy = NodeFactory.computedGraphNode( copyId ? node.getId() : getNextVertexId(), node.getInstruction(), node.getAstNode(), node.getDeclaredVariables(), node.getDefinedVariables(), node.getUsedVariables() ); public <ASTNode extends Node> void addNode(GraphNode<ASTNode> node) { this.addVertex(node); } this.addVertex(copy); public <ASTNode extends Node> GraphNode<ASTNode> addNode(String instruction, ASTNode node) { GraphNode<ASTNode> newNode = NodeFactory.graphNode(instruction, node); return copy; this.addNode(newNode); return newNode; } @SuppressWarnings("unchecked") Loading @@ -80,7 +45,7 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { .map(node -> (GraphNode<ASTNode>) node); } public Optional<GraphNode<?>> findNodeById(int id) { public Optional<GraphNode<?>> findNodeById(long id) { return vertexSet().stream() .filter(node -> Objects.equals(node.getId(), id)) .findFirst(); Loading @@ -93,10 +58,6 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { .collect(Collectors.joining(System.lineSeparator())); } protected synchronized int getNextVertexId() { return nextVertexId++; } public List<GraphNode<?>> findDeclarationsOfVariable(String variable) { return vertexSet().stream() .filter(node -> node.getDeclaredVariables().contains(variable)) Loading @@ -115,98 +76,4 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { null, Arc::getDotAttributes); } /** * Modifies a current node in the graph by the changes done in the MutableGraphNode instance * inside the function passed as parameter * * @param id the id of the node to be modified * @param modifyFn a consumer which takes a MutableGraphNode as parameter */ public <ASTNode extends Node> void modifyNode(int id, Consumer<MutableGraphNode<ASTNode>> modifyFn) { this.findNodeById(id).ifPresent(node -> { Set<Arc> incomingArcs = new HashSet<>(incomingEdgesOf(node)); Set<Arc> outgoingArcs = new HashSet<>(outgoingEdgesOf(node)); this.removeVertex(node); MutableGraphNode<ASTNode> modifiedNode = new MutableGraphNode<>((GraphNode<ASTNode>) node); modifyFn.accept(modifiedNode); GraphNode<ASTNode> newNode = modifiedNode.toGraphNode(); this.addVertex(newNode); for (Arc incomingArc : incomingArcs) { GraphNode<?> from = getEdgeSource(incomingArc); this.addEdge(from, newNode, incomingArc); } for (Arc outgoingArc : outgoingArcs) { GraphNode<?> to = getEdgeTarget(outgoingArc); this.addEdge(newNode, to, outgoingArc); } }); } public static class MutableGraphNode<ASTNode extends Node> { private int id; private String instruction; private ASTNode astNode; private Set<String> declaredVariables; private Set<String> definedVariables; private Set<String> usedVariables; private boolean mustCompute; MutableGraphNode(GraphNode<ASTNode> node) { this.id = node.getId(); this.instruction = node.getInstruction(); this.astNode = node.getAstNode(); this.declaredVariables = node.getDeclaredVariables(); this.definedVariables = node.getDefinedVariables(); this.usedVariables = node.getUsedVariables(); } GraphNode<ASTNode> toGraphNode() { return mustCompute ? NodeFactory.graphNode(id, instruction, astNode) : NodeFactory.computedGraphNode( id, instruction, astNode, declaredVariables, definedVariables, usedVariables ); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getInstruction() { return instruction; } public void setInstruction(String instruction) { this.instruction = instruction; } public ASTNode getAstNode() { return astNode; } public void setAstNode(ASTNode astNode) { this.astNode = astNode; // If the AST node changes, we need to compute all variables for it mustCompute = true; } } } src/main/java/tfm/graphs/GraphWithRootNode.java +11 −5 Original line number Diff line number Diff line Loading @@ -10,12 +10,10 @@ import java.util.Optional; public abstract class GraphWithRootNode<ASTRootNode extends Node> extends Graph implements Buildable<MethodDeclaration> { protected final int ROOT_NODE_ID = 0; protected GraphNode<ASTRootNode> rootNode; public GraphWithRootNode() { super(1); protected GraphWithRootNode() { super(); } /** Loading @@ -31,7 +29,7 @@ public abstract class GraphWithRootNode<ASTRootNode extends Node> extends Graph return false; } GraphNode<ASTRootNode> root = NodeFactory.graphNode(ROOT_NODE_ID, instruction, rootNodeAst); GraphNode<ASTRootNode> root = NodeFactory.graphNode(instruction, rootNodeAst); this.rootNode = root; this.addVertex(root); Loading @@ -42,6 +40,14 @@ public abstract class GraphWithRootNode<ASTRootNode extends Node> extends Graph return Optional.ofNullable(rootNode); } public void setRootNode(GraphNode<ASTRootNode> rootNode) { if (!this.containsVertex(rootNode)) { throw new IllegalArgumentException("Cannot set root node: " + rootNode + " is not contained in graph!"); } this.rootNode = rootNode; } @Override public boolean removeVertex(GraphNode<?> graphNode) { if (Objects.equals(graphNode, rootNode)) { Loading src/main/java/tfm/graphs/cfg/CFG.java +1 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> { return findLastDefinitionsFrom(new HashSet<>(), startNode.getId(), startNode, variable); } private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Integer> visited, int startNode, GraphNode<?> currentNode, String variable) { private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Long> visited, long startNode, GraphNode<?> currentNode, String variable) { visited.add(currentNode.getId()); Set<GraphNode<?>> res = new HashSet<>(); Loading src/main/java/tfm/graphs/pdg/PDGBuilder.java +4 −4 Original line number Diff line number Diff line Loading @@ -38,10 +38,6 @@ public class PDGBuilder { if (!methodDeclaration.getBody().isPresent()) throw new IllegalStateException("Method needs to have a body"); this.pdg.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration); assert this.pdg.getRootNode().isPresent(); BlockStmt methodBody = methodDeclaration.getBody().get(); // build CFG Loading @@ -53,6 +49,10 @@ public class PDGBuilder { .filter(node -> !Objects.equals(node, cfg.getExitNode())) .forEach(node -> pdg.addVertex(node)); assert this.cfg.getRootNode().isPresent(); pdg.setRootNode(cfg.getRootNode().get()); // Build control dependency ControlDependencyBuilder controlDependencyBuilder = new ControlDependencyBuilder(pdg, cfg); controlDependencyBuilder.analyze(); Loading Loading
src/main/java/tfm/exec/PDGLog.java +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ public class PDGLog extends GraphLog<PDG> { Logger.log("Nodes with variable info"); Logger.log(graph.vertexSet().stream() .sorted(Comparator.comparingInt(GraphNode::getId)) .sorted(Comparator.comparingLong(GraphNode::getId)) .map(node -> String.format("GraphNode { id: %s, instruction: %s, declared: %s, defined: %s, used: %s }", node.getId(), Loading
src/main/java/tfm/graphs/Graph.java +10 −143 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ import tfm.nodes.NodeFactory; import tfm.utils.ASTUtils; import java.util.*; import java.util.function.Consumer; import java.util.stream.Collectors; /** Loading @@ -17,59 +16,25 @@ import java.util.stream.Collectors; * */ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { protected static final int DEFAULT_VERTEX_START_ID = 0; private int nextVertexId; public Graph() { this(DEFAULT_VERTEX_START_ID); } protected Graph(int vertexStartId) { protected Graph() { super(null, null, false); this.nextVertexId = vertexStartId; } private <ASTNode extends Node> GraphNode<ASTNode> addNode(GraphNode<ASTNode> node) { this.addVertex(node); return node; } private <ASTNode extends Node> GraphNode<ASTNode> addNode(int id, String instruction, ASTNode node) { GraphNode<ASTNode> newNode = NodeFactory.graphNode(id, instruction, node); return this.addNode(newNode); } public <ASTNode extends Node> GraphNode<ASTNode> addNode(String instruction, ASTNode node) { return this.addNode(getNextVertexId(), instruction, node); } /** * Adds the given node to the graph. * * One must be careful with this method, as the given node will have * an id corresponding to the graph in which it was created, and may not fit * in the current graph. * * @param node the node to add to the graph * @param copyId whether to copy the node id or generate a new one * @return the node instance added to the graph */ public <ASTNode extends Node> GraphNode<ASTNode> addNode(GraphNode<ASTNode> node, boolean copyId) { GraphNode<ASTNode> copy = NodeFactory.computedGraphNode( copyId ? node.getId() : getNextVertexId(), node.getInstruction(), node.getAstNode(), node.getDeclaredVariables(), node.getDefinedVariables(), node.getUsedVariables() ); public <ASTNode extends Node> void addNode(GraphNode<ASTNode> node) { this.addVertex(node); } this.addVertex(copy); public <ASTNode extends Node> GraphNode<ASTNode> addNode(String instruction, ASTNode node) { GraphNode<ASTNode> newNode = NodeFactory.graphNode(instruction, node); return copy; this.addNode(newNode); return newNode; } @SuppressWarnings("unchecked") Loading @@ -80,7 +45,7 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { .map(node -> (GraphNode<ASTNode>) node); } public Optional<GraphNode<?>> findNodeById(int id) { public Optional<GraphNode<?>> findNodeById(long id) { return vertexSet().stream() .filter(node -> Objects.equals(node.getId(), id)) .findFirst(); Loading @@ -93,10 +58,6 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { .collect(Collectors.joining(System.lineSeparator())); } protected synchronized int getNextVertexId() { return nextVertexId++; } public List<GraphNode<?>> findDeclarationsOfVariable(String variable) { return vertexSet().stream() .filter(node -> node.getDeclaredVariables().contains(variable)) Loading @@ -115,98 +76,4 @@ public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> { null, Arc::getDotAttributes); } /** * Modifies a current node in the graph by the changes done in the MutableGraphNode instance * inside the function passed as parameter * * @param id the id of the node to be modified * @param modifyFn a consumer which takes a MutableGraphNode as parameter */ public <ASTNode extends Node> void modifyNode(int id, Consumer<MutableGraphNode<ASTNode>> modifyFn) { this.findNodeById(id).ifPresent(node -> { Set<Arc> incomingArcs = new HashSet<>(incomingEdgesOf(node)); Set<Arc> outgoingArcs = new HashSet<>(outgoingEdgesOf(node)); this.removeVertex(node); MutableGraphNode<ASTNode> modifiedNode = new MutableGraphNode<>((GraphNode<ASTNode>) node); modifyFn.accept(modifiedNode); GraphNode<ASTNode> newNode = modifiedNode.toGraphNode(); this.addVertex(newNode); for (Arc incomingArc : incomingArcs) { GraphNode<?> from = getEdgeSource(incomingArc); this.addEdge(from, newNode, incomingArc); } for (Arc outgoingArc : outgoingArcs) { GraphNode<?> to = getEdgeTarget(outgoingArc); this.addEdge(newNode, to, outgoingArc); } }); } public static class MutableGraphNode<ASTNode extends Node> { private int id; private String instruction; private ASTNode astNode; private Set<String> declaredVariables; private Set<String> definedVariables; private Set<String> usedVariables; private boolean mustCompute; MutableGraphNode(GraphNode<ASTNode> node) { this.id = node.getId(); this.instruction = node.getInstruction(); this.astNode = node.getAstNode(); this.declaredVariables = node.getDeclaredVariables(); this.definedVariables = node.getDefinedVariables(); this.usedVariables = node.getUsedVariables(); } GraphNode<ASTNode> toGraphNode() { return mustCompute ? NodeFactory.graphNode(id, instruction, astNode) : NodeFactory.computedGraphNode( id, instruction, astNode, declaredVariables, definedVariables, usedVariables ); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getInstruction() { return instruction; } public void setInstruction(String instruction) { this.instruction = instruction; } public ASTNode getAstNode() { return astNode; } public void setAstNode(ASTNode astNode) { this.astNode = astNode; // If the AST node changes, we need to compute all variables for it mustCompute = true; } } }
src/main/java/tfm/graphs/GraphWithRootNode.java +11 −5 Original line number Diff line number Diff line Loading @@ -10,12 +10,10 @@ import java.util.Optional; public abstract class GraphWithRootNode<ASTRootNode extends Node> extends Graph implements Buildable<MethodDeclaration> { protected final int ROOT_NODE_ID = 0; protected GraphNode<ASTRootNode> rootNode; public GraphWithRootNode() { super(1); protected GraphWithRootNode() { super(); } /** Loading @@ -31,7 +29,7 @@ public abstract class GraphWithRootNode<ASTRootNode extends Node> extends Graph return false; } GraphNode<ASTRootNode> root = NodeFactory.graphNode(ROOT_NODE_ID, instruction, rootNodeAst); GraphNode<ASTRootNode> root = NodeFactory.graphNode(instruction, rootNodeAst); this.rootNode = root; this.addVertex(root); Loading @@ -42,6 +40,14 @@ public abstract class GraphWithRootNode<ASTRootNode extends Node> extends Graph return Optional.ofNullable(rootNode); } public void setRootNode(GraphNode<ASTRootNode> rootNode) { if (!this.containsVertex(rootNode)) { throw new IllegalArgumentException("Cannot set root node: " + rootNode + " is not contained in graph!"); } this.rootNode = rootNode; } @Override public boolean removeVertex(GraphNode<?> graphNode) { if (Objects.equals(graphNode, rootNode)) { Loading
src/main/java/tfm/graphs/cfg/CFG.java +1 −1 Original line number Diff line number Diff line Loading @@ -40,7 +40,7 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> { return findLastDefinitionsFrom(new HashSet<>(), startNode.getId(), startNode, variable); } private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Integer> visited, int startNode, GraphNode<?> currentNode, String variable) { private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Long> visited, long startNode, GraphNode<?> currentNode, String variable) { visited.add(currentNode.getId()); Set<GraphNode<?>> res = new HashSet<>(); Loading
src/main/java/tfm/graphs/pdg/PDGBuilder.java +4 −4 Original line number Diff line number Diff line Loading @@ -38,10 +38,6 @@ public class PDGBuilder { if (!methodDeclaration.getBody().isPresent()) throw new IllegalStateException("Method needs to have a body"); this.pdg.buildRootNode("ENTER " + methodDeclaration.getNameAsString(), methodDeclaration); assert this.pdg.getRootNode().isPresent(); BlockStmt methodBody = methodDeclaration.getBody().get(); // build CFG Loading @@ -53,6 +49,10 @@ public class PDGBuilder { .filter(node -> !Objects.equals(node, cfg.getExitNode())) .forEach(node -> pdg.addVertex(node)); assert this.cfg.getRootNode().isPresent(); pdg.setRootNode(cfg.getRootNode().get()); // Build control dependency ControlDependencyBuilder controlDependencyBuilder = new ControlDependencyBuilder(pdg, cfg); controlDependencyBuilder.analyze(); Loading