Unverified Commit 5273de58 authored by Javier Costa's avatar Javier Costa Committed by GitHub
Browse files

Merge pull request #25 from jacosro/22-fix-data-dependency

Fix data dependency 
parents 4276420b b3e8abee
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -31,8 +31,9 @@ public class PDGLog extends GraphLog<PDG> {
        Logger.log(graph.vertexSet().stream()
                .sorted(Comparator.comparingInt(GraphNode::getId))
                .map(node ->
                        String.format("GraphNode { id: %s, declared: %s, defined: %s, used: %s }",
                        String.format("GraphNode { id: %s, instruction: %s, declared: %s, defined: %s, used: %s }",
                                node.getId(),
                                node.getInstruction(),
                                node.getDeclaredVariables(),
                                node.getDefinedVariables(),
                                node.getUsedVariables())
+4 −3
Original line number Diff line number Diff line
package tfm.graphs;

import com.github.javaparser.ast.Node;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DirectedPseudograph;
import org.jgrapht.io.DOTExporter;
import tfm.arcs.Arc;
import tfm.nodes.GraphNode;
import tfm.nodes.NodeFactory;
import tfm.utils.ASTUtils;

import java.util.*;
import java.util.function.Consumer;
@@ -14,7 +15,7 @@ import java.util.stream.Collectors;
/**
 *
 * */
public abstract class Graph extends DefaultDirectedGraph<GraphNode<?>, Arc> {
public abstract class Graph extends DirectedPseudograph<GraphNode<?>, Arc> {

    protected static final int DEFAULT_VERTEX_START_ID = 0;

@@ -74,7 +75,7 @@ public abstract class Graph extends DefaultDirectedGraph<GraphNode<?>, Arc> {
    @SuppressWarnings("unchecked")
    public <ASTNode extends Node> Optional<GraphNode<ASTNode>> findNodeByASTNode(ASTNode astNode) {
        return vertexSet().stream()
                .filter(node -> Objects.equals(node.getAstNode(), astNode))
                .filter(node -> ASTUtils.equalsWithRangeInCU(node.getAstNode(), astNode))
                .findFirst()
                .map(node -> (GraphNode<ASTNode>) node);
    }
+3 −3
Original line number Diff line number Diff line
@@ -37,10 +37,10 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> {
    public Set<GraphNode<?>> findLastDefinitionsFrom(GraphNode<?> startNode, String variable) {
        if (!this.containsVertex(startNode))
            throw new NodeNotFoundException(startNode, this);
        return findLastDefinitionsFrom(new HashSet<>(), startNode, startNode, variable);
        return findLastDefinitionsFrom(new HashSet<>(), startNode.getId(), startNode, variable);
    }

    private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Integer> visited, GraphNode<?> startNode, GraphNode<?> currentNode, String variable) {
    private Set<GraphNode<?>> findLastDefinitionsFrom(Set<Integer> visited, int startNode, GraphNode<?> currentNode, String variable) {
        visited.add(currentNode.getId());

        Set<GraphNode<?>> res = new HashSet<>();
@@ -50,7 +50,7 @@ public class CFG extends GraphWithRootNode<MethodDeclaration> {
                continue;
            GraphNode<?> from = getEdgeSource(arc);

            if (!Objects.equals(startNode, from) && visited.contains(from.getId())) {
            if (!Objects.equals(startNode, from.getId()) && visited.contains(from.getId())) {
                continue;
            }

+11 −56
Original line number Diff line number Diff line
package tfm.graphs.pdg;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.stmt.*;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import tfm.graphs.cfg.CFG;
import tfm.graphs.pdg.PDG;
import tfm.nodes.GraphNode;
import tfm.variables.VariableExtractor;

import java.util.Optional;
import java.util.Set;

class DataDependencyBuilder extends VoidVisitorAdapter<Void> {

@@ -43,17 +39,13 @@ class DataDependencyBuilder extends VoidVisitorAdapter<Void> {

    @Override
    public void visit(ForStmt forStmt, Void ignored) {
        GraphNode<ForStmt> forNode = pdg.findNodeByASTNode(forStmt).get();

        forStmt.getInitialization().stream()
                .map(ExpressionStmt::new)
                .forEach(expressionStmt -> buildDataDependency(forNode, expressionStmt));
        forStmt.getInitialization()
                .forEach(this::buildDataDependency);

        buildDataDependency(forStmt); // Only for comparison

        forStmt.getUpdate().stream()
                .map(ExpressionStmt::new)
                .forEach(expressionStmt -> buildDataDependency(forNode, expressionStmt));
        forStmt.getUpdate()
                .forEach(this::buildDataDependency);

        forStmt.getBody().accept(this, null);
    }
@@ -79,51 +71,14 @@ class DataDependencyBuilder extends VoidVisitorAdapter<Void> {
        switchEntryStmt.getStatements().accept(this, null);
    }

    private void buildDataDependency(Statement statement) {
        buildDataDependency(pdg.findNodeByASTNode(statement).get());
    private void buildDataDependency(Node node) {
        buildDataDependency(pdg.findNodeByASTNode(node).get());
    }

    private void buildDataDependency(GraphNode<?> node) {
        new VariableExtractor()
                .setOnVariableUseListener(variable -> {
                    node.addUsedVariable(variable);

                    Optional<? extends GraphNode<?>> nodeOptional = cfg.findNodeByASTNode(node.getAstNode());

                    if (!nodeOptional.isPresent()) {
                        return;
                    }

                    GraphNode<?> cfgNode = nodeOptional.get();

                    Set<GraphNode<?>> lastDefinitions = cfg.findLastDefinitionsFrom(cfgNode, variable);

                    for (GraphNode<?> definitionNode : lastDefinitions) {
                        pdg.findNodeByASTNode(definitionNode.getAstNode())
                                .ifPresent(pdgNode -> pdg.addDataDependencyArc(pdgNode, node, variable));
                    }
                })
                .setOnVariableDefinitionListener(node::addDefinedVariable)
                .setOnVariableDeclarationListener(node::addDeclaredVariable)
                .visit(node.getAstNode());
        for (String usedVariable : node.getUsedVariables()) {
            cfg.findLastDefinitionsFrom(node, usedVariable)
                    .forEach(definitionNode -> pdg.addDataDependencyArc(definitionNode, node, usedVariable));
        }

    // For statement special case
    private void buildDataDependency(GraphNode<?> forNode, Statement statement) {
        new VariableExtractor()
                .setOnVariableUseListener(variable -> {
                    forNode.addUsedVariable(variable);

                    Optional<? extends GraphNode<?>> nodeOptional = cfg.findNodeByASTNode(statement);

                    if (!nodeOptional.isPresent()) {
                        return;
                    }

                    pdg.addDataDependencyArc(forNode, forNode, variable);
                })
                .setOnVariableDefinitionListener(forNode::addDefinedVariable)
                .setOnVariableDeclarationListener(forNode::addDeclaredVariable)
                .visit(statement);
    }
}
+5 −3
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@ import com.github.javaparser.ast.stmt.BlockStmt;
import tfm.graphs.cfg.CFG;
import tfm.nodes.GraphNode;

import java.util.Objects;

/**
 * Populates a {@link PDG}, given a complete {@link CFG}, an empty {@link PDG} and an AST root node.
 * For now it only accepts {@link MethodDeclaration} as root, as it can only receive a single CFG.
@@ -47,9 +49,9 @@ public class PDGBuilder {
            cfg.build(methodDeclaration);

        // Copy nodes from CFG to PDG
        for (GraphNode<?> node : cfg.vertexSet())
            if (!node.equals(cfg.getExitNode()))
                pdg.addVertex(node);
        cfg.vertexSet().stream()
                .filter(node -> !Objects.equals(node, cfg.getExitNode()))
                .forEach(node -> pdg.addVertex(node));

        // Build control dependency
        ControlDependencyBuilder controlDependencyBuilder = new ControlDependencyBuilder(pdg, cfg);
Loading