001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1997-1999 Raja Vallee-Rai
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: package soot.jbco.jimpleTransformations;
021:
022: import java.util.ArrayList;
023: import java.util.Iterator;
024: import java.util.Map;
025: import java.util.Vector;
026: import soot.*;
027: import soot.jbco.util.Rand;
028: import soot.jbco.*;
029: import soot.jimple.*;
030: import soot.toolkits.graph.BriefUnitGraph;
031: import soot.toolkits.scalar.*;
032: import soot.util.*;
033:
034: /**
035: * @author Michael Batchelder
036: *
037: * Created on 10-Jul-2006
038: */
039: public class AddSwitches extends BodyTransformer implements
040: IJbcoTransform {
041:
042: int switchesadded = 0;
043:
044: public void outputSummary() {
045: out.println("Switches added: " + switchesadded);
046: }
047:
048: public static String dependancies[] = new String[] {
049: "wjtp.jbco_fr", "jtp.jbco_adss", "bb.jbco_ful" };
050:
051: public String[] getDependancies() {
052: return dependancies;
053: }
054:
055: public static String name = "jtp.jbco_adss";
056:
057: public String getName() {
058: return name;
059: }
060:
061: public boolean checkTraps(Unit u, Body b) {
062: Iterator it = b.getTraps().iterator();
063: while (it.hasNext()) {
064: Trap t = (Trap) it.next();
065: if (t.getBeginUnit() == u || t.getEndUnit() == u
066: || t.getHandlerUnit() == u)
067: return true;
068: }
069:
070: return false;
071: }
072:
073: protected void internalTransform(Body b, String phaseName,
074: Map options) {
075: if (b.getMethod().getSignature().indexOf("<clinit>") >= 0)
076: return;
077: int weight = soot.jbco.Main.getWeight(phaseName, b.getMethod()
078: .getSignature());
079: if (weight == 0)
080: return;
081:
082: New2InitFlowAnalysis fa = new New2InitFlowAnalysis(
083: new BriefUnitGraph(b));
084:
085: Vector zeroheight = new Vector();
086: PatchingChain units = b.getUnits();
087:
088: Unit first = null;
089: Iterator it = units.snapshotIterator();
090: while (it.hasNext()) {
091: Unit unit = (Unit) it.next();
092: if (unit instanceof IdentityStmt)
093: continue;
094: first = unit;
095: break;
096: }
097:
098: it = units.snapshotIterator();
099: while (it.hasNext()) {
100: Unit unit = (Unit) it.next();
101: if (unit instanceof IdentityStmt || checkTraps(unit, b))
102: continue;
103: // very conservative estimate about where new-<init> ranges are
104: if (((FlowSet) fa.getFlowAfter(unit)).size() == 0
105: && ((FlowSet) fa.getFlowBefore(unit)).size() == 0)
106: zeroheight.add(unit);
107: }
108:
109: if (zeroheight.size() < 3)
110: return;
111:
112: int idx = 0;
113: Unit u = null;
114: for (int i = 0; i < zeroheight.size(); i++) {
115: idx = Rand.getInt(zeroheight.size() - 1) + 1;
116: u = (Unit) zeroheight.get(idx);
117: if (u.fallsThrough())
118: break;
119: u = null;
120: }
121: // couldn't find a unit that fell through
122: if (u == null || Rand.getInt(10) > weight)
123: return;
124:
125: zeroheight.remove(idx);
126: while (zeroheight.size() > (weight > 3 ? weight : 3)) {
127: zeroheight.remove(Rand.getInt(zeroheight.size()));
128: }
129:
130: Chain locals = b.getLocals();
131: ArrayList targs = new ArrayList();
132: targs.addAll(zeroheight);
133:
134: SootField ops[] = FieldRenamer.getRandomOpaques();
135:
136: Local b1 = Jimple.v().newLocal("addswitchesbool1",
137: BooleanType.v());
138: locals.add(b1);
139: Local b2 = Jimple.v().newLocal("addswitchesbool2",
140: BooleanType.v());
141: locals.add(b2);
142:
143: if (ops[0].getType() instanceof PrimType) {
144: units.insertBefore(Jimple.v().newAssignStmt(b1,
145: Jimple.v().newStaticFieldRef(ops[0].makeRef())), u);
146: } else {
147: RefType rt = (RefType) ops[0].getType();
148: SootMethod m = rt.getSootClass().getMethodByName(
149: "booleanValue");
150: Local B = Jimple.v().newLocal("addswitchesBOOL1", rt);
151: locals.add(B);
152: units.insertBefore(Jimple.v().newAssignStmt(B,
153: Jimple.v().newStaticFieldRef(ops[0].makeRef())), u);
154: units.insertBefore(Jimple.v().newAssignStmt(
155: b1,
156: Jimple.v().newVirtualInvokeExpr(B, m.makeRef(),
157: new ArrayList())), u);
158: }
159: if (ops[1].getType() instanceof PrimType) {
160: units.insertBefore(Jimple.v().newAssignStmt(b2,
161: Jimple.v().newStaticFieldRef(ops[1].makeRef())), u);
162: } else {
163: RefType rt = (RefType) ops[1].getType();
164: SootMethod m = rt.getSootClass().getMethodByName(
165: "booleanValue");
166: Local B = Jimple.v().newLocal("addswitchesBOOL2", rt);
167: locals.add(B);
168: units.insertBefore(Jimple.v().newAssignStmt(B,
169: Jimple.v().newStaticFieldRef(ops[1].makeRef())), u);
170: units.insertBefore(Jimple.v().newAssignStmt(
171: b2,
172: Jimple.v().newVirtualInvokeExpr(B, m.makeRef(),
173: new ArrayList())), u);
174: }
175:
176: IfStmt ifstmt = Jimple.v().newIfStmt(
177: Jimple.v().newNeExpr(b1, b2), u);
178: units.insertBefore(ifstmt, u);
179:
180: Local l = Jimple.v().newLocal("addswitchlocal", IntType.v());
181: locals.add(l);
182: units.insertBeforeNoRedirect(Jimple.v().newAssignStmt(l,
183: IntConstant.v(0)), first);
184: units.insertAfter(Jimple.v().newTableSwitchStmt(l, 1,
185: zeroheight.size(), targs, u), ifstmt);
186:
187: switchesadded += zeroheight.size() + 1;
188:
189: Iterator tit = targs.iterator();
190: while (tit.hasNext()) {
191: Unit nxt = (Unit) tit.next();
192: if (Rand.getInt(5) < 4) {
193: units.insertBefore(Jimple.v().newAssignStmt(
194: l,
195: Jimple.v().newAddExpr(l,
196: IntConstant.v(Rand.getInt(3) + 1))),
197: nxt);
198: }
199: }
200:
201: ifstmt.setTarget(u);
202: }
203: }
|