Package dk.brics.xact.analysis.dataflow

Source Code of dk.brics.xact.analysis.dataflow.DataflowAnalyzer$WorkList

package dk.brics.xact.analysis.dataflow;

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import dk.brics.xact.analysis.Debug;
import dk.brics.xact.analysis.flowgraph.Edge;
import dk.brics.xact.analysis.flowgraph.FlowGraph;
import dk.brics.xact.analysis.flowgraph.Statement;
import dk.brics.xact.analysis.flowgraph.VariableFilter;

/**
* Performs a dataflow analysis on a flow graph, given an {@link AnalysisInterface} instance.
*/
public class DataflowAnalyzer<ElementType> {

  private FlowGraph graph;

  private AnalysisInterface<ElementType> lat;
 
  private Map<Statement,ElementType> before = new LinkedHashMap<Statement,ElementType>();
 
  private Map<Statement,ElementType> after = new LinkedHashMap<Statement,ElementType>();
 
  private Set<Statement> visited = new HashSet<Statement>();
 
  private WorkList wl;
 
  /**
   * Constructs a {@link DataflowAnalyzer} for analyzing the given flow graph.
   */
  public DataflowAnalyzer(FlowGraph graph, AnalysisInterface<ElementType> lat) {
    this.graph = graph;
    this.lat = lat;
    for (Statement s : graph.getNodes()) {
      before.put(s, lat.newBottomElement());
      after.put(s, lat.newBottomElement());
    }
  }
 
  /**
   * Computes the least fixed point iteratively.
   */
  public void run() {
    boolean forward = lat.isForward();
    // initialize worklist
    wl = new WorkList(graph);
    for (Statement s : lat.getInitial(graph))
      wl.put(s);
    // iterate until fixed point
    int steps = 0;
    while (!wl.isEmpty()) {
      Statement s = wl.removeFirst();
      boolean changed;
      if (forward)
        changed = lat.transfer(before.get(s), s, after.get(s));
      else
        changed = lat.transfer(after.get(s), s, before.get(s));
      steps++;
      if (!visited.contains(s)) {
        changed = true;
        visited.add(s);
      }
      if (changed) {
        if (forward) {
          for (Edge<Statement,VariableFilter> se : graph.getOutEdges(s)) {
            Statement ss = se.getTo();
            if (lat.merge(after.get(s), se.getData(), before.get(ss)) || !visited.contains(ss))
              wl.put(ss);
          }
        } else {
          for (Edge<Statement,VariableFilter> se : graph.getInEdges(s)) {
            Statement ss = se.getFrom();
            if (lat.merge(before.get(s), se.getData(), after.get(ss)) || !visited.contains(ss))
              wl.put(ss);
          }
        }
      }
    }
    Debug.println(3, true, "Iteration steps: " + steps + ", steps/nodes: " + (float)steps/graph.getNodes().size());
  }
 
  /**
   * Returns the lattice element for the flow into the given statement.
   */
  public ElementType getFlowIn(Statement s) {
    return before.get(s);
  }
 
  /**
   * Returns the lattice element for the flow out of the given statement.
   */
  public ElementType getFlowOut(Statement s) {
    return after.get(s);
  }
 
  private static class WorkList {
   
    private TreeMap<Integer,Statement> list = new TreeMap<Integer,Statement>();

    private HashMap<Statement,Integer> order = new HashMap<Statement,Integer>();
   
    /**
     * Constructs a new empty worklist.
     * Nodes are ordered according to their distance from the entries.
     */
    public WorkList(FlowGraph graph) {
      LinkedList<Statement> queue = new LinkedList<Statement>();
      HashMap<Statement,Integer> indegree = new HashMap<Statement,Integer>();
      int o = 0;
      queue.addAll(graph.getEntries());
      while (!queue.isEmpty()) {
        Statement s = queue.removeFirst();
        if (!order.containsKey(s)) {
          int so = o++;
          order.put(s, so);
          for (Edge<Statement,VariableFilter> out : graph.getOutEdges(s)) {
            Statement s2 = out.getTo();
            if (indegree.containsKey(s2))
              indegree.put(s2, indegree.get(s2)+1);
            else
              indegree.put(s2, 1);
            if (indegree.get(s2) == graph.getInEdges(s2).size())
              queue.addFirst(s2);
            else
              queue.addLast(s2);
          }         
        }
      }
      // add remaining statements
      for (Statement stm : graph.getNodes()) {
        if (!order.containsKey(stm)) {
          order.put(stm, o++);
        }
      }
    }
   
    public void put(Statement s) {
      list.put(order.get(s), s);
    }
   
    public boolean isEmpty() {
      return list.isEmpty();
    }
   
    public Statement removeFirst() {
      return list.remove(list.firstKey());
    }
  }
}
TOP

Related Classes of dk.brics.xact.analysis.dataflow.DataflowAnalyzer$WorkList

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.