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.bafTransformations;
021:
022: import java.util.*;
023:
024: import soot.*;
025: import soot.util.*;
026: import soot.baf.*;
027: import soot.jbco.IJbcoTransform;
028: import soot.jbco.util.Rand;
029: import soot.jimple.*;
030:
031: public class LocalsToBitField extends BodyTransformer implements
032: IJbcoTransform {
033:
034: int replaced = 0;
035: int locals = 0;
036:
037: public static String dependancies[] = new String[] { "jtp.jbco_jl",
038: "bb.jbco_plvb", "bb.jbco_ful", "bb.lp" };
039:
040: public String[] getDependancies() {
041: return dependancies;
042: }
043:
044: public static String name = "bb.jbco_plvb";
045:
046: public String getName() {
047: return name;
048: }
049:
050: public void outputSummary() {
051: out.println("Local fields inserted into bitfield: " + replaced);
052: out.println("Original number of locals: " + locals);
053: }
054:
055: @SuppressWarnings("fallthrough")
056: protected void internalTransform(Body b, String phaseName,
057: Map options) {
058:
059: int weight = soot.jbco.Main.getWeight(phaseName, b.getMethod()
060: .getSignature());
061: if (weight == 0)
062: return;
063:
064: // build mapping of baf locals to jimple locals
065: Chain bLocals = b.getLocals();
066: PatchingChain u = b.getUnits();
067:
068: Unit first = null;
069: ArrayList<Value> params = new ArrayList<Value>();
070: Iterator uit = u.iterator();
071: while (uit.hasNext()) {
072: Unit unit = (Unit) uit.next();
073: if (unit instanceof IdentityInst) {
074: IdentityInst ii = (IdentityInst) unit;
075: if (ii.getRightOpBox().getValue() instanceof ParameterRef) {
076: Value v = ii.getLeftOp();
077: if (v instanceof Local) {
078: params.add(v);
079: first = unit;
080: }
081: }
082: }
083: }
084:
085: // build mapping of baf locals to jimple locals
086: HashMap<Local, Local> bafToJLocals = new HashMap<Local, Local>();
087: Iterator jlocIt = soot.jbco.Main.methods2JLocals.get(
088: b.getMethod()).iterator();
089: while (jlocIt.hasNext()) {
090: Local jl = (Local) jlocIt.next();
091: Iterator blocIt = bLocals.iterator();
092: while (blocIt.hasNext()) {
093: Local bl = (Local) blocIt.next();
094: if (bl.getName().equals(jl.getName())) {
095: bafToJLocals.put(bl, jl);
096: break;
097: }
098: }
099: }
100:
101: ArrayList<Local> booleans = new ArrayList<Local>();
102: ArrayList<Local> bytes = new ArrayList<Local>();
103: ArrayList<Local> chars = new ArrayList<Local>();
104: ArrayList<Local> ints = new ArrayList<Local>();
105: HashMap<Local, Integer> sizes = new HashMap<Local, Integer>();
106: Iterator blocs = bLocals.iterator();
107: while (blocs.hasNext()) {
108: Local bl = (Local) blocs.next();
109: if (params.contains(bl))
110: continue;
111:
112: locals++;
113: Local jlocal = bafToJLocals.get(bl);
114: if (jlocal != null) {
115: Type t = jlocal.getType();
116: if (t instanceof PrimType
117: && !(t instanceof DoubleType || t instanceof LongType)
118: && Rand.getInt(10) <= weight) {
119: if (t instanceof BooleanType) {
120: booleans.add(bl);
121: sizes.put(bl, new Integer(1));
122: } else if (t instanceof ByteType) {
123: bytes.add(bl);
124: sizes.put(bl, new Integer(8));
125: } else if (t instanceof CharType) {// || t instanceof ShortType) {
126: chars.add(bl);
127: sizes.put(bl, new Integer(16));
128: } else if (t instanceof IntType) {
129: ints.add(bl);
130: sizes.put(bl, new Integer(32));
131: }
132: }
133: }
134: }
135:
136: int count = 0;
137: HashMap bafToNewLocs = new HashMap();
138: int total = booleans.size() + bytes.size() * 8 + chars.size()
139: * 16 + ints.size() * 32;
140: HashMap<Local, Map<Local, Integer>> newLocs = new HashMap<Local, Map<Local, Integer>>();
141: while (total >= 32
142: && booleans.size() + bytes.size() + chars.size()
143: + ints.size() > 2) {
144: Local nloc = Baf.v().newLocal("newDumby" + count++,
145: LongType.v()); //soot.jbco.util.Rand.getInt(2) > 0 ? DoubleType.v() : LongType.v());
146: HashMap<Local, Integer> nlocMap = new HashMap<Local, Integer>();
147:
148: boolean done = false;
149: int index = 0;
150: while (index < 64 && !done) {
151: int max = 64 - index;
152: max = max > 31 ? 4 : max > 15 ? 3 : max > 7 ? 2 : 1;
153: int rand = Rand.getInt(max);
154: max = index;
155: switch (rand) {
156: case 3:
157: if (ints.size() > 0) {
158: Local l = ints.remove(Rand.getInt(ints.size()));
159: nlocMap.put(l, new Integer(index));
160: index = index + 32;
161: bafToNewLocs.put(l, nloc);
162: index = getNewIndex(index, ints, chars, bytes,
163: booleans);
164: break;
165: }
166: case 2:
167: if (chars.size() > 0) {
168: Local l = chars.remove(Rand
169: .getInt(chars.size()));
170: nlocMap.put(l, new Integer(index));
171: index = index + 16;
172: bafToNewLocs.put(l, nloc);
173: index = getNewIndex(index, ints, chars, bytes,
174: booleans);
175: break;
176: }
177: case 1:
178: if (bytes.size() > 0) {
179: Local l = bytes.remove(Rand
180: .getInt(bytes.size()));
181: nlocMap.put(l, new Integer(index));
182: index = index + 8;
183: bafToNewLocs.put(l, nloc);
184: index = getNewIndex(index, ints, chars, bytes,
185: booleans);
186: break;
187: }
188: case 0:
189: if (booleans.size() > 0) {
190: Local l = booleans.remove(Rand.getInt(booleans
191: .size()));
192: nlocMap.put(l, new Integer(index++));
193: bafToNewLocs.put(l, nloc);
194: index = getNewIndex(index, ints, chars, bytes,
195: booleans);
196: break;
197: }
198: } // end switch
199: if (max == index)
200: done = true;
201: }
202: newLocs.put(nloc, nlocMap);
203: bLocals.add(nloc);
204: if (first != null) {
205: u.insertAfter(Baf.v().newStoreInst(LongType.v(), nloc),
206: first);
207: u.insertAfter(Baf.v().newPushInst(LongConstant.v(0)),
208: first);
209: } else {
210: u.addFirst(Baf.v().newStoreInst(LongType.v(), nloc));
211: u.addFirst(Baf.v().newPushInst(LongConstant.v(0)));
212: }
213: total = booleans.size() + bytes.size() * 8 + chars.size()
214: * 16 + ints.size() * 32;
215: }
216:
217: if (bafToNewLocs.size() == 0)
218: return;
219:
220: Iterator it = u.snapshotIterator();
221: while (it.hasNext()) {
222: Unit unit = (Unit) it.next();
223: if (unit instanceof StoreInst) {
224: StoreInst si = (StoreInst) unit;
225: Local bafLoc = si.getLocal();
226: Local nloc = (Local) bafToNewLocs.get(bafLoc);
227: if (nloc != null) {
228: Local jloc = bafToJLocals.get(bafLoc);
229:
230: int index = (newLocs.get(nloc).get(bafLoc))
231: .intValue();
232: int size = sizes.get(bafLoc).intValue();
233: long longmask = 0xFFFFFFFFFFFFFFFFL ^ ((size == 1 ? 0x1L
234: : size == 8 ? 0xFFL : size == 16 ? 0xFFFFL
235: : 0xFFFFFFFFL) << index);
236:
237: u.insertBefore(Baf.v().newPrimitiveCastInst(
238: jloc.getType(), LongType.v()), unit);
239: if (index > 0) {
240: u.insertBefore(Baf.v().newPushInst(
241: IntConstant.v(index)), unit);
242: u.insertBefore(
243: Baf.v().newShlInst(LongType.v()), unit);
244: }
245: u
246: .insertBefore(
247: Baf
248: .v()
249: .newPushInst(
250: LongConstant
251: .v(longmask ^ 0xFFFFFFFFFFFFFFFFL)),
252: unit);
253: u.insertBefore(Baf.v().newAndInst(LongType.v()),
254: unit);
255: u.insertBefore(Baf.v().newLoadInst(LongType.v(),
256: nloc), unit);
257: u.insertBefore(Baf.v().newPushInst(
258: LongConstant.v(longmask)), unit);
259: u.insertBefore(Baf.v().newAndInst(LongType.v()),
260: unit);
261: u.insertBefore(Baf.v().newXorInst(LongType.v()),
262: unit);
263: u.insertBefore(Baf.v().newStoreInst(LongType.v(),
264: nloc), unit);
265: u.remove(unit);
266: }
267: } else if (unit instanceof LoadInst) {
268: LoadInst li = (LoadInst) unit;
269: Local bafLoc = li.getLocal();
270: Local nloc = (Local) bafToNewLocs.get(bafLoc);
271: if (nloc != null) {
272: int index = (newLocs.get(nloc).get(bafLoc))
273: .intValue();
274: int size = sizes.get(bafLoc).intValue();
275: long longmask = (size == 1 ? 0x1L
276: : size == 8 ? 0xFFL : size == 16 ? 0xFFFFL
277: : 0xFFFFFFFFL) << index;
278:
279: u.insertBefore(Baf.v().newLoadInst(LongType.v(),
280: nloc), unit);
281: u.insertBefore(Baf.v().newPushInst(
282: LongConstant.v(longmask)), unit);
283: u.insertBefore(Baf.v().newAndInst(LongType.v()),
284: unit);
285: if (index > 0) {
286: u.insertBefore(Baf.v().newPushInst(
287: IntConstant.v(index)), unit);
288: u.insertBefore(
289: Baf.v().newShrInst(LongType.v()), unit);
290: }
291:
292: Type origType = bafToJLocals.get(bafLoc).getType();
293: Type t = getType(origType);
294: u.insertBefore(Baf.v().newPrimitiveCastInst(
295: LongType.v(), t), unit);
296: if (!(origType instanceof IntType)
297: && !(origType instanceof BooleanType))
298: u.insertBefore(Baf.v().newPrimitiveCastInst(t,
299: origType), unit);
300: u.remove(unit);
301: }
302: } else if (unit instanceof IncInst) {
303: IncInst ii = (IncInst) unit;
304: Local bafLoc = ii.getLocal();
305: Local nloc = (Local) bafToNewLocs.get(bafLoc);
306: if (nloc != null) {
307: Type jlocType = getType(bafToJLocals.get(bafLoc)
308: .getType());
309:
310: int index = (newLocs.get(nloc).get(bafLoc))
311: .intValue();
312: int size = sizes.get(bafLoc).intValue();
313: long longmask = (size == 1 ? 0x1L
314: : size == 8 ? 0xFFL : size == 16 ? 0xFFFFL
315: : 0xFFFFFFFFL) << index;
316:
317: u.insertBefore(Baf.v()
318: .newPushInst(ii.getConstant()), unit);
319: u.insertBefore(Baf.v().newLoadInst(LongType.v(),
320: nloc), unit);
321: u.insertBefore(Baf.v().newPushInst(
322: LongConstant.v(longmask)), unit);
323: u.insertBefore(Baf.v().newAndInst(LongType.v()),
324: unit);
325: if (index > 0) {
326: u.insertBefore(Baf.v().newPushInst(
327: IntConstant.v(index)), unit);
328: u.insertBefore(
329: Baf.v().newShrInst(LongType.v()), unit);
330: }
331: u.insertBefore(Baf.v().newPrimitiveCastInst(
332: LongType.v(), ii.getConstant().getType()),
333: unit);
334: u.insertBefore(Baf.v().newAddInst(
335: ii.getConstant().getType()), unit);
336: u.insertBefore(Baf.v().newPrimitiveCastInst(
337: jlocType, LongType.v()), unit);
338: if (index > 0) {
339: u.insertBefore(Baf.v().newPushInst(
340: IntConstant.v(index)), unit);
341: u.insertBefore(
342: Baf.v().newShlInst(LongType.v()), unit);
343: }
344:
345: longmask = 0xFFFFFFFFFFFFFFFFL ^ longmask;
346: u.insertBefore(Baf.v().newLoadInst(LongType.v(),
347: nloc), unit);
348: u.insertBefore(Baf.v().newPushInst(
349: LongConstant.v(longmask)), unit);
350: u.insertBefore(Baf.v().newAndInst(LongType.v()),
351: unit);
352: u.insertBefore(Baf.v().newXorInst(LongType.v()),
353: unit);
354: u.insertBefore(Baf.v().newStoreInst(LongType.v(),
355: nloc), unit);
356: u.remove(unit);
357: }
358: }
359: }
360:
361: it = bLocals.snapshotIterator();
362: while (it.hasNext()) {
363: Local l = (Local) it.next();
364: if (bafToNewLocs.containsKey(l)) {
365: bLocals.remove(l);
366: replaced++;
367: }
368: }
369: }
370:
371: private Type getType(Type t) {
372: if (t instanceof BooleanType || t instanceof CharType
373: || t instanceof ShortType || t instanceof ByteType)
374: return IntType.v();
375: else
376: return t;
377: }
378:
379: private int getNewIndex(int index, List<Local> ints,
380: List<Local> chars, List<Local> bytes, List<Local> booleans) {
381: int max = 0;
382: if (booleans.size() > 0 && index < 63)
383: max = 64;
384: else if (bytes.size() > 0 && index < 56)
385: max = 57;
386: else if (chars.size() > 0 && index < 48)
387: max = 49;
388: else if (ints.size() > 0 && index < 32)
389: max = 33;
390:
391: if (max != 0) {
392: int rand = Rand.getInt(4);
393: max = max - index;
394: if (max > rand)
395: max = rand;
396: else if (max != 1)
397: max = Rand.getInt(max);
398: index += max;
399: }
400: return index;
401: }
402: }
|