Example #1
0
  /**
   * Utility method used in the construction of {@link UnitGraph}s, to be called only after the
   * unitToPreds and unitToSuccs maps have been built.
   *
   * <p><code>UnitGraph</code> provides an implementation of <code>buildHeadsAndTails()</code> which
   * defines the graph's set of heads to include the first {@link Unit} in the graph's body,
   * together with any other <tt>Unit</tt> which has no predecessors. It defines the graph's set of
   * tails to include all <tt>Unit</tt>s with no successors. Subclasses of <code>UnitGraph</code>
   * may override this method to change the criteria for classifying a node as a head or tail.
   */
  protected void buildHeadsAndTails() {
    List tailList = new ArrayList();
    List headList = new ArrayList();

    for (Iterator unitIt = unitChain.iterator(); unitIt.hasNext(); ) {
      Unit s = (Unit) unitIt.next();
      List succs = (List) unitToSuccs.get(s);
      if (succs.size() == 0) {
        tailList.add(s);
      }
      List preds = (List) unitToPreds.get(s);
      if (preds.size() == 0) {
        headList.add(s);
      }
    }

    // Add the first Unit, even if it is the target of
    // a branch.
    Unit entryPoint = (Unit) unitChain.getFirst();
    if (!headList.contains(entryPoint)) {
      headList.add(entryPoint);
    }

    tails = Collections.unmodifiableList(tailList);
    heads = Collections.unmodifiableList(headList);
  }
Example #2
0
 /**
  * Utility method that replaces the values of a {@link Map}, which must be instances of {@link
  * List}, with unmodifiable equivalents.
  *
  * @param map The map whose values are to be made unmodifiable.
  */
 protected static void makeMappedListsUnmodifiable(Map map) {
   for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
     Map.Entry entry = (Map.Entry) it.next();
     List value = (List) entry.getValue();
     if (value.size() == 0) {
       entry.setValue(Collections.EMPTY_LIST);
     } else {
       entry.setValue(Collections.unmodifiableList(value));
     }
   }
 }
  /**
   * Computes the analysis given a UnitGraph computed from a method body. It is recommended that a
   * ExceptionalUnitGraph (or similar) be provided for correct results in the case of exceptional
   * control flow.
   *
   * @param g a graph on which to compute the analysis.
   * @see ExceptionalUnitGraph
   */
  public SimpleLiveLocals(UnitGraph graph) {
    if (Options.v().time()) Timers.v().liveTimer.start();

    if (Options.v().verbose())
      G.v()
          .out
          .println(
              "["
                  + graph.getBody().getMethod().getName()
                  + "]     Constructing SimpleLiveLocals...");

    SimpleLiveLocalsAnalysis analysis = new SimpleLiveLocalsAnalysis(graph);

    if (Options.v().time()) Timers.v().livePostTimer.start();

    // Build unitToLocals map
    {
      unitToLocalsAfter = new HashMap<Unit, List>(graph.size() * 2 + 1, 0.7f);
      unitToLocalsBefore = new HashMap<Unit, List>(graph.size() * 2 + 1, 0.7f);

      Iterator unitIt = graph.iterator();

      while (unitIt.hasNext()) {
        Unit s = (Unit) unitIt.next();

        FlowSet set = (FlowSet) analysis.getFlowBefore(s);
        unitToLocalsBefore.put(s, Collections.unmodifiableList(set.toList()));

        set = (FlowSet) analysis.getFlowAfter(s);
        unitToLocalsAfter.put(s, Collections.unmodifiableList(set.toList()));
      }
    }

    if (Options.v().time()) Timers.v().livePostTimer.end();

    if (Options.v().time()) Timers.v().liveTimer.end();
  }
Example #4
0
  /**
   * Utility method that produces a new map from the {@link Unit}s of this graph's body to the union
   * of the values stored in the two argument {@link Map}s, used to combine the maps of exceptional
   * and unexceptional predecessors and successors into maps of all predecessors and successors. The
   * values stored in both argument maps must be {@link List}s of {@link Unit}s, which are assumed
   * not to contain any duplicate <tt>Unit</tt>s.
   *
   * @param mapA The first map to be combined.
   * @param mapB The second map to be combined.
   */
  protected Map combineMapValues(Map mapA, Map mapB) {
    // The duplicate screen
    Map result = new HashMap(mapA.size() * 2 + 1, 0.7f);
    for (Iterator chainIt = unitChain.iterator(); chainIt.hasNext(); ) {
      Unit unit = (Unit) chainIt.next();
      List listA = (List) mapA.get(unit);
      if (listA == null) {
        listA = Collections.EMPTY_LIST;
      }
      List listB = (List) mapB.get(unit);
      if (listB == null) {
        listB = Collections.EMPTY_LIST;
      }

      int resultSize = listA.size() + listB.size();
      if (resultSize == 0) {
        result.put(unit, Collections.EMPTY_LIST);
      } else {
        List resultList = new ArrayList(resultSize);
        Iterator listIt = null;
        // As a minor optimization of the duplicate screening,
        // copy the longer list first.
        if (listA.size() >= listB.size()) {
          resultList.addAll(listA);
          listIt = listB.iterator();
        } else {
          resultList.addAll(listB);
          listIt = listA.iterator();
        }
        while (listIt.hasNext()) {
          Object element = listIt.next();
          // It is possible for there to be both an exceptional
          // and an unexceptional edge connecting two Units
          // (though probably not in a class generated by
          // javac), so we need to screen for duplicates. On the
          // other hand, we expect most of these lists to have
          // only one or two elements, so it doesn't seem worth
          // the cost to build a Set to do the screening.
          if (!resultList.contains(element)) {
            resultList.add(element);
          }
        }
        result.put(unit, Collections.unmodifiableList(resultList));
      }
    }
    return result;
  }