001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1999 Phong Co
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: /*
021: * Modified by the Sable Research Group and others 1997-1999.
022: * See the 'credits' file distributed with Soot for the complete list of
023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
024: */
025:
026: package soot.jimple.toolkits.scalar;
027:
028: import soot.options.*;
029:
030: import soot.util.*;
031: import soot.*;
032: import soot.jimple.*;
033:
034: import java.util.*;
035:
036: public class UnconditionalBranchFolder extends BodyTransformer {
037: public UnconditionalBranchFolder(Singletons.Global g) {
038: }
039:
040: public static UnconditionalBranchFolder v() {
041: return G
042: .v()
043: .soot_jimple_toolkits_scalar_UnconditionalBranchFolder();
044: }
045:
046: static final int JUMPOPT_TYPES = 6;
047: int numFound[], numFixed[];
048:
049: HashMap<Stmt, Stmt> stmtMap;
050:
051: protected void internalTransform(Body b, String phaseName,
052: Map options) {
053: StmtBody body = (StmtBody) b;
054:
055: if (Options.v().verbose())
056: G.v().out.println("[" + body.getMethod().getName()
057: + "] Folding unconditional branches...");
058:
059: // allocate counters once only
060: if (numFound == null) {
061: numFound = new int[JUMPOPT_TYPES + 1];
062: numFixed = new int[JUMPOPT_TYPES + 1];
063: }
064:
065: for (int i = 0; i <= JUMPOPT_TYPES; i++) {
066: numFound[i] = 0;
067: numFixed[i] = 0;
068: }
069:
070: Chain units = body.getUnits();
071: stmtMap = new HashMap<Stmt, Stmt>();
072:
073: // find goto and if-goto statements
074: Iterator stmtIt = units.iterator();
075: Stmt stmt, target, newTarget;
076: while (stmtIt.hasNext()) {
077: stmt = (Stmt) stmtIt.next();
078: if (stmt instanceof GotoStmt) {
079:
080: target = (Stmt) ((GotoStmt) stmt).getTarget();
081:
082: if (stmtIt.hasNext()) {
083: // check for goto -> next statement
084: if (units.getSuccOf(stmt) == target) {
085: stmtIt.remove();
086: updateCounters(6, true);
087: }
088: }
089:
090: if (target instanceof GotoStmt) {
091: newTarget = getFinalTarget(target);
092: if (newTarget == null)
093: newTarget = stmt;
094: ((GotoStmt) stmt).setTarget(newTarget);
095: updateCounters(1, true);
096: } else if (target instanceof IfStmt) {
097: updateCounters(3, false);
098: }
099: } else if (stmt instanceof IfStmt) {
100: target = ((IfStmt) stmt).getTarget();
101:
102: if (target instanceof GotoStmt) {
103: newTarget = getFinalTarget(target);
104: if (newTarget == null)
105: newTarget = stmt;
106: ((IfStmt) stmt).setTarget(newTarget);
107: updateCounters(2, true);
108: } else if (target instanceof IfStmt) {
109: updateCounters(4, false);
110: }
111: }
112: }
113: if (Options.v().verbose())
114: G.v().out.println("[" + body.getMethod().getName()
115: + "] " + numFixed[0] + " of " + numFound[0]
116: + " branches folded.");
117:
118: } // optimizeJumps
119:
120: private void updateCounters(int type, boolean fixed) {
121:
122: if ((type < 0) || (type > JUMPOPT_TYPES))
123: return;
124:
125: numFound[0]++;
126: numFound[type]++;
127: if (fixed) {
128: numFixed[0]++;
129: numFixed[type]++;
130: }
131: }
132:
133: private Stmt getFinalTarget(Stmt stmt) {
134: Stmt finalTarget = null, target;
135:
136: // if not a goto, this is the final target
137: if (!(stmt instanceof GotoStmt))
138: return stmt;
139:
140: // first map this statement to itself, so we can detect cycles
141: stmtMap.put(stmt, stmt);
142:
143: target = (Stmt) ((GotoStmt) stmt).getTarget();
144:
145: // check if target is in statement map
146: if (stmtMap.containsKey(target)) {
147: // see if it maps to itself
148: finalTarget = stmtMap.get(target);
149: if (finalTarget == target)
150: // this is part of a cycle
151: finalTarget = null;
152: } else
153: finalTarget = getFinalTarget(target);
154:
155: stmtMap.put(stmt, finalTarget);
156: return finalTarget;
157: } // getFinalTarget
158:
159: } // JumpOptimizer
|