All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.toolkits.annotation.logic.LoopFinder Maven / Gradle / Ivy

The newest version!
package soot.jimple.toolkits.annotation.logic;

/*-
 * #%L
 * Soot - a J*va Optimization Framework
 * %%
 * Copyright (C) 2004 Jennifer Lhotak
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import soot.Body;
import soot.BodyTransformer;
import soot.Unit;
import soot.jimple.Stmt;
import soot.toolkits.graph.ExceptionalUnitGraphFactory;
import soot.toolkits.graph.MHGDominatorsFinder;
import soot.toolkits.graph.UnitGraph;

public class LoopFinder extends BodyTransformer {

  private Set loops;

  public LoopFinder() {
    loops = null;
  }

  protected void internalTransform(Body b, String phaseName, Map options) {
    getLoops(b);
  }

  public Set getLoops(Body b) {
    if (loops != null) {
      return loops;
    }
    return getLoops(ExceptionalUnitGraphFactory.createExceptionalUnitGraph(b));
  }

  public Set getLoops(UnitGraph g) {
    if (loops != null) {
      return loops;
    }

    MHGDominatorsFinder a = new MHGDominatorsFinder(g);
    Map> loops = new HashMap>();

    for (Unit u : g.getBody().getUnits()) {
      List succs = g.getSuccsOf(u);
      List dominaters = a.getDominators(u);
      List headers = new ArrayList();

      for (Unit succ : succs) {
        if (dominaters.contains(succ)) {
          // header succeeds and dominates s, we have a loop
          headers.add((Stmt) succ);
        }
      }

      for (Unit header : headers) {
        List loopBody = getLoopBodyFor(header, u, g);
        if (loops.containsKey(header)) {
          // merge bodies
          List lb1 = loops.get(header);
          loops.put((Stmt) header, union(lb1, loopBody));
        } else {
          loops.put((Stmt) header, loopBody);
        }
      }
    }

    Set ret = new HashSet();
    for (Map.Entry> entry : loops.entrySet()) {
      ret.add(new Loop(entry.getKey(), entry.getValue(), g));
    }

    this.loops = ret;
    return ret;
  }

  private List getLoopBodyFor(Unit header, Unit node, UnitGraph g) {
    List loopBody = new ArrayList();
    Deque stack = new ArrayDeque();

    loopBody.add((Stmt) header);
    stack.push(node);

    while (!stack.isEmpty()) {
      Stmt next = (Stmt) stack.pop();
      if (!loopBody.contains(next)) {
        // add next to loop body
        loopBody.add(0, next);
        // put all preds of next on stack
        for (Unit u : g.getPredsOf(next)) {
          stack.push(u);
        }
      }
    }

    assert (node == header && loopBody.size() == 1) || loopBody.get(loopBody.size() - 2) == node;
    assert loopBody.get(loopBody.size() - 1) == header;

    return loopBody;
  }

  private List union(List l1, List l2) {
    for (Stmt next : l2) {
      if (!l1.contains(next)) {
        l1.add(next);
      }
    }
    return l1;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy