Commit c6356b20 authored by Javier Costa's avatar Javier Costa
Browse files

Fixed data dependency

parent fd62f7f3
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ 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;
@@ -74,7 +75,7 @@ public abstract class Graph extends DirectedPseudograph<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);
    }
+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);
+4 −9
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;

/**
 * Represents a node in the various graphs ({@link CFG CFG},
@@ -45,9 +46,7 @@ public class GraphNode<N extends Node> implements Comparable<GraphNode<?>> {
                Utils.emptySet()
        );

        if (astNode instanceof Statement) {
            extractVariables((Statement) astNode);
        }
        extractVariables(astNode);
    }

    GraphNode(
@@ -67,12 +66,12 @@ public class GraphNode<N extends Node> implements Comparable<GraphNode<?>> {
        this.usedVariables = new HashSet<>(usedVariables);
    }

    private void extractVariables(@NotNull Statement statement) {
    private void extractVariables(@NotNull Node node) {
        new VariableExtractor()
                .setOnVariableDeclarationListener(this.declaredVariables::add)
                .setOnVariableDefinitionListener(this.definedVariables::add)
                .setOnVariableUseListener(this.usedVariables::add)
                .visit(statement);
                .visit(node);
    }

    public int getId() {
@@ -118,10 +117,6 @@ public class GraphNode<N extends Node> implements Comparable<GraphNode<?>> {
                && Objects.equals(astNode, other.astNode);
    }

    public boolean equalsWithASTNodeRange(Object o) {
        return equals(o) && ASTUtils.equalsWithRange(((GraphNode<?>) o).astNode, astNode);
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId(), getInstruction(), getAstNode());
+18 −2
Original line number Diff line number Diff line
package tfm.utils;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.stmt.*;

import java.util.Objects;
@@ -79,7 +81,21 @@ public class ASTUtils {
    }

    public static boolean equalsWithRange(Node n1, Node n2) {
        return Objects.equals(n1.getRange(), n2.getRange())
                && Objects.equals(n1, n2);
        return Objects.equals(n1.getRange(), n2.getRange()) && Objects.equals(n1, n2);
    }

    public static boolean equalsWithRangeInCU(Node n1, Node n2) {
        // Find the compilation unit of each node
        Optional<CompilationUnit> optionalCompilationUnit1 = n1.findCompilationUnit();
        Optional<CompilationUnit> optionalCompilationUnit2 = n2.findCompilationUnit();

        // If they are inside the same compilation unit, compare with range
        if (optionalCompilationUnit1.isPresent() && optionalCompilationUnit2.isPresent()) {
            return Objects.equals(optionalCompilationUnit1.get(), optionalCompilationUnit2.get())
                    && equalsWithRange(n1, n2);
        }

        // If not, just compare with range
        return equalsWithRange(n1, n2);
    }
}
Loading