1 package edu.berkeley.cs.megacz;
8 public class Transformer extends SceneTransformer {
10 public static final int initialSize = 100;
12 private static Transformer instance = new Transformer();
13 private Transformer() {
15 public static Transformer v() { return instance; }
17 public static void main(String[] args) {
18 if(args.length == 0) {
19 System.out.println("Syntax: java " + v().getClass().getName() + " [soot options]");
22 //PackManager.v().allPacks().add(v());
23 PackManager.v().getPack("wjtp").add(new Transform("wjtp.tx", Transformer.v()));
24 // Just in case, resolve the PrintStream SootClass.
25 Scene.v().addBasicClass("java.io.PrintStream",SootClass.SIGNATURES);
30 public static Local viaLocal(Value v, Body b, Unit u) {
31 Local l = Jimple.v().newLocal("tmpRef" + (tfr++), v.getType());
33 b.getUnits().insertBefore(Jimple.v().newAssignStmt(l, v), u);
37 HashMap map = new HashMap();
38 HashSet size_added = new HashSet();
40 public boolean isGladiator(SootClass c) { return c.implementsInterface("edu.berkeley.cs.megacz.Gladiator"); }
41 public boolean isGladiatorField(SootField f)
42 { return isGladiator(f.getDeclaringClass()) && !f.getName().equals("this") && f.getName().indexOf('$')==-1; }
43 public boolean isGladiatorFieldRef(SootFieldRef f) {
44 return isGladiator(f.declaringClass()) && !f.name().equals("this") && f.name().indexOf('$')==-1;
46 public SootField getGladiatorField(SootField f) { return getGladiatorField(f.makeRef()); }
47 public SootField getGladiatorField(SootFieldRef f) {
48 SootClass c = f.declaringClass();
49 SootClass oc = Scene.v().getSootClass(c.getName().substring(0, c.getName().lastIndexOf('$')));
50 String sig = f.declaringClass().getName()+"."+f.name();
51 if (map.get(sig) != null) return (SootField)map.get(sig);
53 if (t instanceof RefType && isGladiator(((RefType)t).getSootClass())) t = IntType.v();
54 SootField nf = new SootField(c.getShortName().substring(c.getShortName().lastIndexOf('$')+1) + "$" + f.name(),
58 Body body = oc.getMethod("<init>", new LinkedList()).getActiveBody();
59 Expr newArr = Jimple.v().newNewArrayExpr(t, IntConstant.v(initialSize));
60 Local newArrLocal = Jimple.v().newLocal("tmpRef" + (tfr++), f.type().makeArrayType());
61 body.getLocals().add(newArrLocal);
62 InstanceFieldRef ifr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), nf.makeRef());
63 body.getUnits().addFirst(Jimple.v().newAssignStmt(ifr, newArrLocal));
64 body.getUnits().addFirst(Jimple.v().newAssignStmt(newArrLocal, newArr));
70 public SootFieldRef getGladiatorFieldSizeRef(SootClass c) {
71 SootClass mc = Scene.v().getMainClass();
72 String name = c.getShortName().substring(c.getShortName().lastIndexOf('$')+1) + "$$size";
73 if (map.get(name) == null) {
74 SootField f = new SootField(name, IntType.v());
77 Body body = mc.getMethod("<init>", new LinkedList()).getActiveBody();
78 InstanceFieldRef ifr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), f.makeRef());
79 body.getUnits().addFirst(Jimple.v().newAssignStmt(ifr, IntConstant.v(0)));
83 return Scene.v().makeFieldRef(mc, name, IntType.v(), false);
85 public SootFieldRef getGladiatorFieldMaxRef(SootClass c) {
86 SootClass mc = Scene.v().getMainClass();
87 String name = c.getShortName().substring(c.getShortName().lastIndexOf('$')+1) + "$$max";
88 if (map.get(name) == null) {
89 SootField f = new SootField(name, IntType.v());
92 Body body = mc.getMethod("<init>", new LinkedList()).getActiveBody();
93 InstanceFieldRef ifr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), f.makeRef());
94 body.getUnits().addFirst(Jimple.v().newAssignStmt(ifr, IntConstant.v(initialSize)));
98 return Scene.v().makeFieldRef(mc, name, IntType.v(), false);
101 public boolean isGladiatorType(Type t) {
102 return (t instanceof RefType) && isGladiator(((RefType)t).getSootClass());
105 public SootMethodRef convert(SootMethodRef mr) {
106 List l = mr.parameterTypes();
107 List l2 = new LinkedList();
108 for(Iterator it2 = l.iterator(); it2.hasNext();) {
109 Type t = (Type)it2.next();
110 l2.add(isGladiatorType(t) ? IntType.v() : t);
112 return Scene.v().makeMethodRef(mr.declaringClass(),
115 isGladiatorType(mr.returnType()) ? IntType.v() : mr.returnType(),
119 boolean done = false;
120 public void internalTransform(String phaseName, Map options) {
121 System.out.println("=============");
124 //nuke(Scene.v().getSootClass("edu.berkeley.cs.megacz.Test$Inner"));
125 //nuke(Scene.v().getSootClass("edu.berkeley.cs.megacz.Test"));
126 //nuke(Scene.v().getSootClass("org.ibex.graphics.Mesh"));
127 //nuke(Scene.v().getSootClass("org.ibex.graphics.Mesh$Triangle"));
128 fixClass(Scene.v().getSootClass("edu.berkeley.cs.megacz.GCBench$Node"));
129 nuke(Scene.v().getSootClass("edu.berkeley.cs.megacz.GCBench$Node"));
130 nuke(Scene.v().getSootClass("edu.berkeley.cs.megacz.GCBench"));
133 public void fixClass(SootClass sc) {
134 SootClass mc = Scene.v().getMainClass();
135 String incFuncName = sc.getShortName().substring(sc.getShortName().lastIndexOf('$')+1) + "$$inc";
136 SootMethod method = new SootMethod(incFuncName, new LinkedList(),
137 IntType.v(), Modifier.PRIVATE,
139 mc.addMethod(method);
140 method.setActiveBody(body = Jimple.v().newBody(method));
141 body.setMethod(method);
142 ((JimpleBody)body).insertIdentityStmts();
143 Local l = Jimple.v().newLocal("tmpRef" + (tfr++), IntType.v());
144 body.getLocals().add(l);
145 Local l2 = Jimple.v().newLocal("tmpRef" + (tfr++), IntType.v());
146 body.getLocals().add(l2);
147 Local l3 = Jimple.v().newLocal("tmpRef" + (tfr++), IntType.v());
148 body.getLocals().add(l3);
149 InstanceFieldRef sfr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), getGladiatorFieldSizeRef(sc));
150 body.getUnits().add(Jimple.v().newAssignStmt(l, sfr));
151 body.getUnits().add(Jimple.v().newAssignStmt(l2, Jimple.v().newAddExpr(l, IntConstant.v(1))));
152 InstanceFieldRef maxField = Jimple.v().newInstanceFieldRef(body.getThisLocal(), getGladiatorFieldMaxRef(sc));
153 body.getUnits().add(Jimple.v().newAssignStmt(l3, maxField));
154 Stmt stmt = Jimple.v().newReturnStmt(l2);
155 body.getUnits().add(Jimple.v().newIfStmt(Jimple.v().newLtExpr(l2, l3), stmt));
157 Local l4 = Jimple.v().newLocal("tmpRef" + (tfr++), IntType.v());
158 body.getLocals().add(l4);
159 body.getUnits().add(Jimple.v().newAssignStmt(l4, Jimple.v().newShlExpr(l3, IntConstant.v(1))));
160 body.getUnits().add(Jimple.v().newAssignStmt(maxField, l4));
162 for(Iterator it = sc.getFields().iterator(); it.hasNext();) {
163 SootField f = getGladiatorField((SootField)it.next());
164 InstanceFieldRef ifr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), f.makeRef());
165 Local ll0 = Jimple.v().newLocal("tmpRef" + (tfr++), f.getType());
166 body.getLocals().add(ll0);
167 body.getUnits().add(Jimple.v().newAssignStmt(ll0, ifr));
168 Local ll = Jimple.v().newLocal("tmpRef" + (tfr++), f.getType());
169 body.getLocals().add(ll);
170 body.getUnits().add(Jimple.v().newAssignStmt(ll,
171 Jimple.v().newNewArrayExpr(((ArrayType)f.getType()).getElementType(),
173 Type ot = Scene.v().getSootClass("java.lang.Object").getType();
174 List types = new LinkedList();
176 types.add(IntType.v());
178 types.add(IntType.v());
179 types.add(IntType.v());
180 SootMethodRef arrayCopy =
181 Scene.v().makeMethodRef(Scene.v().getSootClass("java.lang.System"),
186 List args = new LinkedList();
188 args.add(IntConstant.v(0));
190 args.add(IntConstant.v(0));
192 body.getUnits().add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(arrayCopy, args)));
193 body.getUnits().add(Jimple.v().newAssignStmt(ifr,ll));
196 body.getUnits().add(stmt);
199 public void nuke(SootClass c) {
200 for(Iterator it = c.getFields().iterator(); it.hasNext();) {
201 SootField f = (SootField)it.next();
202 Type t = f.getType();
203 if (t instanceof RefType) {
204 RefType rt = (RefType)t;
205 SootClass sc = rt.getSootClass();
206 if (isGladiator(sc)) f.setType(IntType.v());
207 } else if (t instanceof ArrayType) {
208 ArrayType at = (ArrayType)t;
209 t = at.getElementType();
210 if (!(t instanceof RefType)) continue;
211 RefType rt = (RefType)t;
212 SootClass sc = rt.getSootClass();
213 if (isGladiator(sc)) f.setType(IntType.v().makeArrayType());
217 //if (isGladiator(c)) fixClass(c);
219 List list = new LinkedList(); list.addAll(c.getMethods());
220 for(Iterator it = list.iterator(); it.hasNext();) {
221 SootMethod m = (SootMethod)it.next();
222 if (isGladiator(c) && m.getName().equals("<init>")) continue;
223 if (m.hasActiveBody() && !m.isStatic()) m.setActiveBody(fixBody(m.getActiveBody()));
224 if (m.getName().equals("<init>")) continue;
225 if (m.getName().equals("<clinit>")) continue;
226 //if (map.get(m) != null) continue;
227 //map.put(m, Boolean.TRUE);
228 System.out.println(m.getName() + " -- " + m.getActiveBody());
229 List l2 = new LinkedList();
230 List l = m.getParameterTypes();
231 for(Iterator it2 = l.iterator(); it2.hasNext();) {
232 Type t = (Type)it2.next();
234 l2.add(isGladiatorType(t) ? IntType.v() : t);
235 //if (isGladiatorType(t)) System.out.println("ought to swap " + t);
237 Type t = m.getReturnType();
239 if (isGladiatorType(t)) {
241 Body bod = m.getActiveBody();
242 for(Iterator stmtIt = bod.getUnits().snapshotIterator(); stmtIt.hasNext();) {
243 Stmt s = (Stmt) stmtIt.next();
244 if (s instanceof ReturnStmt) {
245 if (((ReturnStmt)s).getOp().getType() instanceof NullType) {
246 ((ReturnStmt)s).getOpBox().setValue(IntConstant.v(-1));
251 SootMethod meth = new SootMethod(m.getName(), l2, t, m.getModifiers());
252 meth.setActiveBody(m.getActiveBody());
258 protected Body fixBody(Body body) {
260 Chain units = body.getUnits();
261 for(Iterator it = body.getLocals().snapshotIterator(); it.hasNext();) {
262 Local l = (Local)it.next();
263 if (isGladiatorType(l.getType())) l.setType(IntType.v());
265 for(int qq=0; qq<2; qq++) for(Iterator stmtIt = units.snapshotIterator(); stmtIt.hasNext();) {
266 Stmt s = (Stmt) stmtIt.next();
267 List l = s.getUseAndDefBoxes();
268 if (s instanceof DefinitionStmt) {
269 DefinitionStmt ds = (DefinitionStmt)s;
270 if (ds.getLeftOp().getType() instanceof PrimType && ds.getRightOp().getType() instanceof NullType) {
271 System.out.println("*************************");
272 ds.getRightOpBox().setValue(IntConstant.v(-1));
275 for(Iterator it = l.iterator(); it.hasNext();) {
276 Object o = it.next();
277 if (o instanceof ValueBox) {
278 ValueBox vb = (ValueBox)o;
279 Value v = vb.getValue();
281 if (v instanceof BinopExpr) {
282 BinopExpr boe = (BinopExpr)v;
283 if (boe.getOp1().getType() instanceof PrimType && boe.getOp2().getType() instanceof NullType) {
284 System.out.println("*************************");
285 boe.setOp2(IntConstant.v(-1));
287 if (boe.getOp2().getType() instanceof PrimType && boe.getOp1().getType() instanceof NullType) {
288 System.out.println("*************************");
289 boe.setOp1(IntConstant.v(-1));
293 if (v instanceof InvokeExpr) {
294 InvokeExpr ie = (InvokeExpr)v;
295 SootMethodRef mr = ie.getMethodRef();
296 if (isGladiator(mr.declaringClass())) {
297 body.getUnits().remove(s);
303 for(int i=0; i<ie.getArgCount(); i++) {
304 ValueBox b = ie.getArgBox(i);
305 Value val = b.getValue();
306 if (mr.parameterType(i) instanceof RefType && val.getType() instanceof PrimType) {
307 SootClass intClass = Scene.v().getSootClass("java.lang.Integer");
308 List typelist = new LinkedList();
309 typelist.add(IntType.v());
310 SootMethod intMethod = intClass.getMethod("<init>", typelist);
311 Local loc = viaLocal(Jimple.v().newNewExpr(RefType.v(intClass)), body, s);
312 List list = new LinkedList();
314 units.insertBefore(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(loc,
320 if (val != null && val.getType() instanceof NullType && mr.parameterType(i) instanceof IntType) {
321 b.setValue(IntConstant.v(-1));
325 } else if (v instanceof NewExpr) {
326 NewExpr ne = (NewExpr)v;
327 if (isGladiatorType(ne.getBaseType())) {
328 System.out.println("******");
329 SootClass mc = Scene.v().getMainClass();
330 SootClass sc = ((RefType)ne.getBaseType()).getSootClass();
331 System.out.println(sc);
332 String incFuncName = sc.getShortName().substring(sc.getShortName().lastIndexOf('$')+1) + "$$inc";
333 SootMethodRef smr = Scene.v().makeMethodRef(mc, incFuncName, new LinkedList(), IntType.v(), false);
334 Expr invokeExpr = Jimple.v().newSpecialInvokeExpr(body.getThisLocal(), smr);
335 Local ll = viaLocal(invokeExpr, body, s);
339 } else if (v instanceof CastExpr) {
340 CastExpr ce = (CastExpr)v;
341 if (isGladiatorType(ce.getCastType())) {
342 //SootClass intClass = Scene.v().getSootClass("java.lang.Integer");
343 //SootClass intClass = Scene.v().getSootClass("java.lang.Integer");
344 SootClass mc = Scene.v().getMainClass();
345 LinkedList list = new LinkedList();
346 list.add(Scene.v().getSootClass("java.lang.Object").getType());
347 SootMethodRef mr = Scene.v().makeMethodRef(mc, "zap", list, IntType.v(), true);
348 Local loc = viaLocal(ce.getOp(), body, s);
349 List list2 = new LinkedList();
351 vb.setValue(viaLocal(Jimple.v().newStaticInvokeExpr(mr, list2), body, s));
354 } else if (v instanceof InstanceFieldRef) {
355 InstanceFieldRef ifr = (InstanceFieldRef)v;
356 SootFieldRef fr = ifr.getFieldRef();
358 if (isGladiatorFieldRef(fr)) {
359 SootClass mc = Scene.v().getMainClass();
360 SootFieldRef sf = getGladiatorField(fr).makeRef();
361 InstanceFieldRef sfr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), sf);
362 ArrayRef ar = Jimple.v().newArrayRef(viaLocal(sfr, body, s), ifr.getBase());
365 if ((t instanceof RefType) && isGladiator(((RefType)t).getSootClass())) {
366 SootClass tc = ((RefType)t).getSootClass();
367 SootClass mc = Scene.v().getMainClass();
368 ifr.setFieldRef(Scene.v().makeFieldRef(mc, fr.name(), IntType.v(), false));