checkpoint
[org.ibex.arenaj.git] / src / edu / berkeley / cs / megacz / Transformer.java
1 package edu.berkeley.cs.megacz;
2 import soot.*;
3 import soot.jimple.*;
4 import soot.util.*;
5 import java.io.*;
6 import java.util.*;
7
8 public class Transformer extends SceneTransformer {    
9
10     public static final int initialSize = 100;
11
12     private static Transformer instance = new Transformer();
13     private Transformer() {
14     }
15     public static Transformer v() { return instance; }
16    
17     public static void main(String[] args)  {
18         if(args.length == 0) {
19             System.out.println("Syntax: java " + v().getClass().getName() + " [soot options]");
20             System.exit(0);
21         }
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);
26         soot.Main.main(args);
27     }
28
29     static int tfr = 0;
30     public static Local viaLocal(Value v, Body b, Unit u) {
31         Local l = Jimple.v().newLocal("tmpRef" + (tfr++), v.getType());
32         b.getLocals().add(l);
33         b.getUnits().insertBefore(Jimple.v().newAssignStmt(l, v), u);
34         return l;
35     }
36
37     HashMap map = new HashMap();
38     HashSet size_added = new HashSet();
39
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;
45     }
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);
52         Type t = f.type();
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(),
55                                      t.makeArrayType(),
56                                      0);
57         oc.addField(nf);
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));
65         map.put(sig, nf);
66         return nf;
67     }
68
69     private Body body;
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());
75             mc.addField(f);
76
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)));
80
81             map.put(c, f);
82         }
83         return Scene.v().makeFieldRef(mc, name, IntType.v(), false);
84     }
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());
90             mc.addField(f);
91
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)));
95
96             map.put(c, f);
97         }
98         return Scene.v().makeFieldRef(mc, name, IntType.v(), false);
99     }
100
101     public boolean isGladiatorType(Type t) {
102         return (t instanceof RefType) && isGladiator(((RefType)t).getSootClass());
103     }
104
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);
111         }
112         return Scene.v().makeMethodRef(mr.declaringClass(),
113                                        mr.name(),
114                                        l2,
115                                        isGladiatorType(mr.returnType()) ? IntType.v() : mr.returnType(),
116                                        mr.isStatic());
117     }
118
119     boolean done = false;
120     public void internalTransform(String phaseName, Map options) {
121         System.out.println("=============");
122         if (done) return;
123         done = true;
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"));
131     }
132
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,
138                                            new LinkedList());
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));
156
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));
161
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(),
172                                                                                     l4)));
173             Type ot = Scene.v().getSootClass("java.lang.Object").getType();
174             List types = new LinkedList();
175             types.add(ot);
176             types.add(IntType.v());
177             types.add(ot);
178             types.add(IntType.v());
179             types.add(IntType.v());
180             SootMethodRef arrayCopy =
181                 Scene.v().makeMethodRef(Scene.v().getSootClass("java.lang.System"),
182                                         "arraycopy",
183                                         types,
184                                         VoidType.v(),
185                                         true);
186             List args = new LinkedList();
187             args.add(ll0);
188             args.add(IntConstant.v(0));
189             args.add(ll);
190             args.add(IntConstant.v(0));
191             args.add(l3);
192             body.getUnits().add(Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr(arrayCopy, args)));
193             body.getUnits().add(Jimple.v().newAssignStmt(ifr,ll));
194         }
195
196         body.getUnits().add(stmt);
197     }
198
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());
214             }
215         }
216
217         //if (isGladiator(c)) fixClass(c);
218
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();
233                 //l2.add(t);
234                 l2.add(isGladiatorType(t) ? IntType.v() : t);
235                 //if (isGladiatorType(t)) System.out.println("ought to swap " + t);
236             }
237             Type t = m.getReturnType();
238             c.removeMethod(m);
239             if (isGladiatorType(t)) {
240                 t = IntType.v();
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));
247                         }
248                     }
249                 }
250             }
251             SootMethod meth = new SootMethod(m.getName(), l2, t, m.getModifiers());
252             meth.setActiveBody(m.getActiveBody());
253             c.addMethod(meth);
254         }
255
256     }
257
258     protected Body fixBody(Body body) {
259         this.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());
264         }
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));
273                 }
274             }
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();
280                     
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));
286                         }
287                         if (boe.getOp2().getType() instanceof PrimType && boe.getOp1().getType() instanceof NullType) {
288                             System.out.println("*************************");
289                             boe.setOp1(IntConstant.v(-1));
290                         }
291                     }
292
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);
298                             qq = 0;
299                             break;
300                         }
301                         mr = convert(mr);
302                         ie.setMethodRef(mr);
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();
313                                 list.add(val);
314                                 units.insertBefore(Jimple.v().newInvokeStmt(Jimple.v().newSpecialInvokeExpr(loc,
315                                                                                                             intMethod.makeRef(),
316                                                                                                             list)),
317                                                    s);
318                                 b.setValue(loc);
319                             }
320                             if (val != null && val.getType() instanceof NullType && mr.parameterType(i) instanceof IntType) {
321                                 b.setValue(IntConstant.v(-1));
322                             }
323                         }
324
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);
336                             vb.setValue(ll);
337                         }
338
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();
350                             list2.add(loc);
351                             vb.setValue(viaLocal(Jimple.v().newStaticInvokeExpr(mr, list2), body, s));
352                         }
353
354                     } else if (v instanceof InstanceFieldRef) {
355                         InstanceFieldRef ifr = (InstanceFieldRef)v;
356                         SootFieldRef fr = ifr.getFieldRef();
357                         Type t = fr.type();
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());
363                             vb.setValue(ar);
364                         }
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));
369                         }
370                     }
371                 }
372             }
373         }
374         return body;
375     }
376 }