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: /*
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.toolkits.scalar;
027:
028: import soot.options.*;
029:
030: import soot.*;
031: import soot.util.*;
032: import java.util.*;
033: import soot.jimple.*;
034:
035: /**
036: * A BodyTransformer that attemps to minimize the number of local variables used in
037: * Body by 'reusing' them when possible. Implemented as a singleton.
038: * For example the code:
039: *
040: * for(int i; i < k; i++);
041: * for(int j; j < k; j++);
042: *
043: * would be transformed into:
044: * for(int i; i < k; i++);
045: * for(int i; i < k; i++);
046: *
047: * assuming to further conflicting uses of i and j.
048: *
049: * Note: LocalSplitter is corresponds to the inverse transformation.
050: *
051: * @see BodyTransformer
052: * @see Body
053: * @see LocalSplitter
054: */
055: public class LocalPacker extends BodyTransformer {
056: public LocalPacker(Singletons.Global g) {
057: }
058:
059: public static LocalPacker v() {
060: return G.v().soot_toolkits_scalar_LocalPacker();
061: }
062:
063: protected void internalTransform(Body body, String phaseName,
064: Map options) {
065: boolean isUnsplit = PhaseOptions.getBoolean(options,
066: "unsplit-original-locals");
067:
068: if (Options.v().verbose())
069: G.v().out.println("[" + body.getMethod().getName()
070: + "] Packing locals...");
071:
072: Map<Local, Object> localToGroup = new DeterministicHashMap(body
073: .getLocalCount() * 2 + 1, 0.7f);
074: // A group represents a bunch of locals which may potentially intefere with each other
075: // 2 separate groups can not possibly interfere with each other
076: // (coloring say ints and doubles)
077:
078: Map<Object, Integer> groupToColorCount = new HashMap<Object, Integer>(
079: body.getLocalCount() * 2 + 1, 0.7f);
080: Map<Local, Integer> localToColor = new HashMap<Local, Integer>(
081: body.getLocalCount() * 2 + 1, 0.7f);
082: Map localToNewLocal;
083:
084: // Assign each local to a group, and set that group's color count to 0.
085: {
086: Iterator localIt = body.getLocals().iterator();
087:
088: while (localIt.hasNext()) {
089: Local l = (Local) localIt.next();
090: Object g = l.getType();
091:
092: localToGroup.put(l, g);
093:
094: if (!groupToColorCount.containsKey(g)) {
095: groupToColorCount.put(g, new Integer(0));
096: }
097: }
098: }
099:
100: // Assign colors to the parameter locals.
101: {
102: Iterator codeIt = body.getUnits().iterator();
103:
104: while (codeIt.hasNext()) {
105: Unit s = (Unit) codeIt.next();
106:
107: if (s instanceof IdentityUnit
108: && ((IdentityUnit) s).getLeftOp() instanceof Local) {
109: Local l = (Local) ((IdentityUnit) s).getLeftOp();
110:
111: Object group = localToGroup.get(l);
112: int count = groupToColorCount.get(group).intValue();
113:
114: localToColor.put(l, new Integer(count));
115:
116: count++;
117:
118: groupToColorCount.put(group, new Integer(count));
119: }
120: }
121: }
122:
123: // Call the graph colorer.
124: if (isUnsplit)
125: FastColorer.unsplitAssignColorsToLocals(body, localToGroup,
126: localToColor, groupToColorCount);
127: else
128: FastColorer.assignColorsToLocals(body, localToGroup,
129: localToColor, groupToColorCount);
130:
131: // Map each local to a new local.
132: {
133: List originalLocals = new ArrayList();
134: localToNewLocal = new HashMap(body.getLocalCount() * 2 + 1,
135: 0.7f);
136: Map groupIntToLocal = new HashMap(
137: body.getLocalCount() * 2 + 1, 0.7f);
138:
139: originalLocals.addAll(body.getLocals());
140: body.getLocals().clear();
141:
142: Iterator localIt = originalLocals.iterator();
143:
144: while (localIt.hasNext()) {
145: Local original = (Local) localIt.next();
146:
147: Object group = localToGroup.get(original);
148: int color = localToColor.get(original).intValue();
149: GroupIntPair pair = new GroupIntPair(group, color);
150:
151: Local newLocal;
152:
153: if (groupIntToLocal.containsKey(pair))
154: newLocal = (Local) groupIntToLocal.get(pair);
155: else {
156: newLocal = (Local) original.clone();
157: newLocal.setType((Type) group);
158:
159: // Icky fix. But I guess it works. -PL
160: // It is no substitute for really understanding the
161: // problem, though. I'll leave that to someone
162: // who really understands the local naming stuff.
163: // Does such a person exist?
164:
165: int signIndex = newLocal.getName().indexOf("#");
166:
167: if (signIndex != -1)
168: newLocal.setName(newLocal.getName().substring(
169: 0, signIndex));
170:
171: groupIntToLocal.put(pair, newLocal);
172: body.getLocals().add(newLocal);
173: }
174:
175: localToNewLocal.put(original, newLocal);
176: }
177: }
178:
179: // Go through all valueBoxes of this method and perform changes
180: {
181: Iterator codeIt = body.getUnits().iterator();
182:
183: while (codeIt.hasNext()) {
184: Unit s = (Unit) codeIt.next();
185:
186: Iterator boxIt;
187: boxIt = s.getUseBoxes().iterator();
188: while (boxIt.hasNext()) {
189: ValueBox box = (ValueBox) boxIt.next();
190:
191: if (box.getValue() instanceof Local) {
192: Local l = (Local) box.getValue();
193: box.setValue((Local) localToNewLocal.get(l));
194: }
195: }
196: boxIt = s.getDefBoxes().iterator();
197: while (boxIt.hasNext()) {
198: ValueBox box = (ValueBox) boxIt.next();
199:
200: if (box.getValue() instanceof Local) {
201: Local l = (Local) box.getValue();
202: box.setValue((Local) localToNewLocal.get(l));
203: }
204: }
205: }
206: }
207: }
208: }
|