Commit 2d6dc639 authored by Carlos Galindo's avatar Carlos Galindo
Browse files

tmp (breaks 3 tests)

parent 9ba011a1
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ public abstract class BackwardDataFlowAnalysis<V, E, D> {
                Set<V> mayAffectVertex = graph.outgoingEdgesOf(vertex).stream()
                        .map(graph::getEdgeTarget).collect(Collectors.toCollection(ASTUtils::newIdentityHashSet));
                D newValue = compute(vertex, mayAffectVertex);
                if (!Objects.equals(vertexDataMap.get(vertex), newValue)) {
                if (!dataMatch(vertexDataMap.get(vertex), newValue)) {
                    vertexDataMap.put(vertex, newValue);
                    graph.incomingEdgesOf(vertex).stream().map(graph::getEdgeSource).forEach(newWorkList::add);
                }
@@ -47,6 +47,11 @@ public abstract class BackwardDataFlowAnalysis<V, E, D> {
        built = true;
    }

    /** Checks whether the computed value has changed or not. */
    protected boolean dataMatch(D oldData, D newData) {
        return Objects.equals(oldData, newData);
    }

    /** Compute a new value for a given vertex, given a set of nodes that might affect its value. */
    protected abstract D compute(V vertex, Set<V> predecessors);

+44 −20
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ public abstract class InterproceduralActionFinder<A extends VariableAction> exte
    /** Entry-point to the class. Performs the analysis and then saves the results to the CFG nodes. */
    public void save() {
        if (!built) analyze();
        graph.vertexSet().forEach(this::saveDeclaration);
        graph.vertexSet().forEach(this::saveDeclarationFormalNodes);
    }

    /** Obtains the StoredAction object with information on which actions have been stored. */
@@ -47,21 +47,31 @@ public abstract class InterproceduralActionFinder<A extends VariableAction> exte
        return actionStoredMap.get(vertex).get(action);
    }

    /** Save the current set of actions associated to the given declaration. It will avoid saving
     *  duplicates by default, so this method may be called multiple times safely. */
    protected void saveDeclaration(CallGraph.Vertex vertex) {
    /** Save the current set of actions associated with the given declaration. This method will
     *  only generate actual-in and actual-out nodes. It is idempotent, and won't generate duplicates. */
    protected void saveDeclarationActualNodes(CallGraph.Vertex vertex) {
        var actions = vertexDataMap.get(vertex);
        // Update stored action map
        actionStoredMap.computeIfAbsent(vertex, v -> new HashMap<>());
        for (A a : actions)
            actionStoredMap.get(vertex).computeIfAbsent(a, __ -> new StoredAction());
        // FORMAL: per declaration (1)
        for (A a : actions)
            getStored(vertex, a).storeFormal(() -> sandBoxedHandler(vertex, a, this::handleFormalAction));
        // ACTUAL: per call (n)
        for (CallGraph.Edge<?> edge : graph.incomingEdgesOf(vertex))
            actions.stream().sorted(new ParameterFieldSorter(edge)).forEach(a ->
                    getStored(vertex, a).storeActual(edge, e -> sandBoxedHandler(e, a, this::handleActualAction)));
                    getStored(vertex, a).storeActual(edge, a, e -> sandBoxedHandler(e, a, this::handleActualAction)));
    }

    /** Save the current set of actions associated with the given declaration. This method will
     *  only generate formal-in and formal-out nodes. It is idempotent, and won't generate duplicates. */
    protected void saveDeclarationFormalNodes(CallGraph.Vertex vertex) {
        var actions = vertexDataMap.get(vertex);
        // Update stored action map
        actionStoredMap.computeIfAbsent(vertex, __ -> new HashMap<>());
        for (A a : actions)
            actionStoredMap.get(vertex).computeIfAbsent(a, __ -> new StoredAction());
        // 1 formal per declaration and action
        for (A a : actions)
            getStored(vertex, a).storeFormal(a, () -> sandBoxedHandler(vertex, a, this::handleFormalAction));
    }

    /** A sandbox to avoid resolution errors when a variable is included that is a class name
@@ -100,10 +110,8 @@ public abstract class InterproceduralActionFinder<A extends VariableAction> exte

    @Override
    protected Set<A> compute(CallGraph.Vertex vertex, Set<CallGraph.Vertex> predecessors) {
        saveDeclaration(vertex);
        Set<A> newValue = new HashSet<>(vertexDataMap.get(vertex));
        newValue.addAll(initialValue(vertex));
        return newValue;
        saveDeclarationActualNodes(vertex);
        return initialValue(vertex);
    }

    @Override
@@ -136,6 +144,21 @@ public abstract class InterproceduralActionFinder<A extends VariableAction> exte
     *  filter unwanted items (only if the filter is specific to that type). */
    protected abstract Stream<A> mapAndFilterActionStream(Stream<VariableAction> stream, CFG cfg);

    @Override
    protected boolean dataMatch(Set<A> oldData, Set<A> newData) {
        if (oldData == newData)
            return true;
        if (oldData.size() != newData.size())
            return false;
        HashMap<String, A> map = new HashMap<>();
        for (A a : oldData)
            map.put(a.getName(), a);
        for (A b : newData)
            if (!VariableAction.objectTreeMatches(map.get(b.getName()), b))
                return false;
        return true;
    }

    // ===========================================================
    // ========================= SUBCLASSES ======================
    // ===========================================================
@@ -168,27 +191,28 @@ public abstract class InterproceduralActionFinder<A extends VariableAction> exte
     *  have been saved to the graph or not. */
    protected static class StoredAction {
        /** Whether the action has been saved as actual node for each call. */
        private final Map<CallGraph.Edge<?>, Boolean> actualStoredMap = new HashMap<>();
        private final Map<CallGraph.Edge<?>, VariableAction> actualStoredMap = new HashMap<>();

        /** Whether the action has been saved as formal node. */
        protected boolean formalStored = false;
        protected VariableAction formalStored = null;

        private StoredAction() {}

        /** If this action has not yet been saved as formal node, use the argument to do so, then mark it as stored. */
        private void storeFormal(Runnable save) {
            if (!formalStored) {
        private void storeFormal(VariableAction action, Runnable save) {
            if (formalStored == null || !VariableAction.objectTreeMatches(action, formalStored)) {
                save.run();
                formalStored = true;
                formalStored = action;
            }
        }

        /** If this action has not yet been saved as actual node for the given edge,
         * use the consumer to do so, then mark it as stored. */
        private void storeActual(CallGraph.Edge<?> edge, Consumer<CallGraph.Edge<?>> save) {
            if (!actualStoredMap.getOrDefault(edge, false)) {
        private void storeActual(CallGraph.Edge<?> edge, VariableAction action, Consumer<CallGraph.Edge<?>> save) {
            VariableAction storedAction = actualStoredMap.get(edge);
            if (storedAction == null || !VariableAction.objectTreeMatches(storedAction, action)) {
                save.accept(edge);
                actualStoredMap.put(edge, true);
                actualStoredMap.put(edge, action);
            }
        }
    }
+14 −16
Original line number Diff line number Diff line
@@ -29,15 +29,14 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Usag
    }

    @Override
    public void save() {
        super.save();
        markTransferenceToRoot();
    protected void saveDeclarationActualNodes(CallGraph.Vertex vertex) {
        super.saveDeclarationActualNodes(vertex);
        graph.incomingEdgesOf(vertex).forEach(this::markTransferenceToRoot);
    }

    /** For every variable action -scope-in- or -arg-in- in the graph,
     *  runs {@link ExpressionObjectTreeFinder#locateAndMarkTransferenceToRoot(Expression, VariableAction)}. */
    protected void markTransferenceToRoot() {
        for (CallGraph.Edge<?> edge : graph.edgeSet()) {
    protected void markTransferenceToRoot(CallGraph.Edge<?> edge) {
        for (ActualIONode actualIn : locateActualInNode(edge)) {
            for (VariableAction va : edge.getGraphNode().getVariableActions()) {
                if (va instanceof Movable && ((Movable) va).getRealNode().equals(actualIn)) {
@@ -54,7 +53,6 @@ public class InterproceduralUsageFinder extends InterproceduralActionFinder<Usag
            }
        }
    }
    }

    @Override
    protected void handleFormalAction(CallGraph.Vertex vertex, Usage use) {
+1 −1
Original line number Diff line number Diff line
@@ -444,7 +444,7 @@ public class ObjectTree implements Cloneable {
        if (o == null || getClass() != o.getClass()) return false;
        ObjectTree tree = (ObjectTree) o;
        return Objects.equals(getMemberName(), tree.getMemberName()) &&
                childrenMap.values().equals(tree.childrenMap.values());
                childrenMap.equals(tree.childrenMap);
    }

    @Override
+15 −1
Original line number Diff line number Diff line
@@ -239,6 +239,20 @@ public abstract class VariableAction {
        connection.applySDG(sdg);
    }

    public static boolean objectTreeMatches(VariableAction a, VariableAction b) {
        if (a == b)
            return true;
        if (a == null || b == null)
            return false;
        boolean aHasTree = a.hasObjectTree() && a.getObjectTree().hasChildren();
        boolean bHasTree = b.hasObjectTree() && b.getObjectTree().hasChildren();
        if (aHasTree != bHasTree)
            return false;
        if (!aHasTree)
            return true;
        return a.getObjectTree().equals(b.getObjectTree());
    }

    // ======================================================
    // =================== ROOT ACTIONS =====================
    // ======================================================