00001 package edu.ksu.cis.bandera.prog;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 import edu.ksu.cis.bandera.jext.LocalExpr;
00037 import java.util.*;
00038
00039
00040
00041
00042
00043 import edu.ksu.cis.bandera.annotation.*;
00044 import edu.ksu.cis.bandera.jjjc.*;
00045 import ca.mcgill.sable.soot.*;
00046 import ca.mcgill.sable.soot.jimple.*;
00047 import edu.ksu.cis.bandera.abstraction.*;
00048 import edu.ksu.cis.bandera.abstraction.typeinference.*;
00049 public class Inline {
00050 protected static Hashtable inlinedMethods = new Hashtable();
00051 Hashtable locals;
00052 AnnotationManager annotationManager;
00053 public static Hashtable newLocal2original = new Hashtable();
00054 public static TypeTable typeTable;
00055 public static boolean isMethodCompiled;
00056 protected java.util.Hashtable stmtLocalTable;
00057
00058
00059
00060 public Inline() {
00061 locals = new Hashtable();
00062 }
00063
00064
00065
00066
00067
00068
00069 public static void inline(ca.mcgill.sable.soot.SootMethod method, edu.ksu.cis.bandera.annotation.AnnotationManager annotationManager) {
00070 RenameExpression.fields = (List) inlinedMethods.get(method);
00071 if (RenameExpression.fields == null) {
00072 RenameExpression.fields = new Vector();
00073 Inline in = new Inline();
00074 in.inlineMethod(method, annotationManager);
00075 inlinedMethods.put(method, RenameExpression.fields);
00076 }
00077 }
00078
00079
00080
00081
00082
00083
00084 protected void inlineMethod(SootMethod method, AnnotationManager annotationManager) {
00085 if ((stmtLocalTable = annotationManager.getStmtLocalTable()) == null)
00086 annotationManager.setStmtLocalTable(stmtLocalTable = new Hashtable());
00087 ca.mcgill.sable.util.List traps = new ca.mcgill.sable.util.VectorList();
00088 this.annotationManager = annotationManager;
00089 ca.mcgill.sable.util.List stmts = inlineMethod(method, (List) null, (Local) null, (Stmt) null, "", traps, method);
00090 JimpleBody body = (JimpleBody) method.getBody(Jimple.v());
00091 body.getStmtList().clear();
00092 body.getStmtList().addAll(stmts);
00093 body.getTraps().clear();
00094 body.getTraps().addAll(traps);
00095 body.getLocals().clear();
00096 java.util.Enumeration e = locals.elements();
00097 while (e.hasMoreElements()) {
00098 Local lcl = (Local) e.nextElement();
00099 body.addLocal(lcl);
00100 }
00101 method.storeBody(Jimple.v(), body);
00102 List l = new Vector();
00103 l.addAll(RenameExpression.fields);
00104 inlinedMethods.put(method, l);
00105
00106
00107
00108
00109
00110
00111 try {
00112
00113 } catch (Exception e2) {
00114 e2.printStackTrace();
00115 }
00116 }
00117
00118
00119
00120
00121
00122
00123 protected ca.mcgill.sable.util.List inlineMethod(SootMethod method, List params, Value var, Stmt ret, String prefix, ca.mcgill.sable.util.List traps, SootMethod topMethod) {
00124 boolean isMethodCompiled = Inline.isMethodCompiled;
00125 Hashtable stmt2stmts = new Hashtable();
00126 RenameStatement rs = new RenameStatement(method, prefix, var, params, ret, locals, stmt2stmts, topMethod);
00127 RenameExpression re = rs.getRenameExpr();
00128 BuildAndStoreBody bd = new BuildAndStoreBody(Jimple.v(), new StoredBody(ClassFile.v()), 0);
00129 try {
00130 if (!method.isBodyStored(Jimple.v()))
00131 bd.resolveFor(method);
00132 } catch (Exception e) {
00133 ca.mcgill.sable.util.LinkedList lstPatch = new ca.mcgill.sable.util.LinkedList();
00134 Type retType = method.getReturnType();
00135 Stmt myStmt = null;
00136 Jimple j = Jimple.v();
00137 if (retType instanceof VoidType) {
00138 myStmt = j.newReturnVoidStmt();
00139 } else
00140 if (retType instanceof IntType || retType instanceof ByteType || retType instanceof BooleanType || retType instanceof CharType || retType instanceof ShortType) {
00141 myStmt = j.newReturnStmt(IntConstant.v(0));
00142 } else
00143 if (retType instanceof LongType) {
00144 myStmt = j.newReturnStmt(LongConstant.v(0));
00145 } else
00146 if (retType instanceof DoubleType) {
00147 myStmt = j.newReturnStmt(DoubleConstant.v(0.0));
00148 } else
00149 if (retType instanceof FloatType) {
00150 myStmt = j.newReturnStmt(FloatConstant.v(0));
00151 } else {
00152 myStmt = j.newReturnStmt(NullConstant.v());
00153 }
00154 lstPatch.addLast(myStmt);
00155 return lstPatch;
00156 }
00157 Inline.isMethodCompiled = CompilationManager.getCompiledClasses().get(method.getDeclaringClass().getName()) != null;
00158 JimpleBody body = (JimpleBody) method.getBody(Jimple.v());
00159 ca.mcgill.sable.util.List res = new ca.mcgill.sable.util.VectorList();
00160 int i;
00161 Stmt s;
00162 ca.mcgill.sable.util.List r;
00163 Set localSet = new HashSet();
00164 Stmt stmts[] = new Stmt[body.getStmtList().size()];
00165 System.arraycopy(body.getStmtList().toArray(), 0, stmts, 0, stmts.length);
00166 for (i = 0; i < stmts.length; i++) {
00167 s = stmts[i];
00168 InlinerChooseFixer.fix(s);
00169 if (s instanceof InvokeStmt) {
00170 InvokeStmt is = (InvokeStmt) s;
00171 if (!javaPrefix(((InvokeExpr) is.getInvokeExpr()).getMethod().getDeclaringClass().toString()) && !"Bandera".equals(((InvokeExpr) is.getInvokeExpr()).getMethod().getDeclaringClass().toString())) {
00172 InvokeExpr expr = (InvokeExpr) is.getInvokeExpr();
00173 List nparams = new Vector();
00174 if (expr instanceof NonStaticInvokeExpr) {
00175 nparams.add(re.renameExpr((Local) ((NonStaticInvokeExpr) expr).getBase()));
00176 }
00177 for (int j = 0; j < expr.getArgCount(); j++)
00178 nparams.add(re.renameExpr(expr.getArg(j)));
00179 String nprefix;
00180 if (expr.getMethod().getName().equals("<init>"))
00181 nprefix = prefix + expr.getMethod().getDeclaringClass() + "_const_";
00182 else
00183 nprefix = prefix + expr.getMethod().getName() + "_";
00184 ca.mcgill.sable.util.List ntraps = new ca.mcgill.sable.util.VectorList();
00185 Stmt nret = Jimple.v().newNopStmt();
00186
00187
00188
00189 if (expr instanceof VirtualInvokeExpr || expr instanceof InterfaceInvokeExpr) {
00190
00191 SootClass methodDecl = expr.getMethod().getDeclaringClass();
00192 String methodName = expr.getMethod().getName();
00193 ca.mcgill.sable.util.List paramTypes = expr.getMethod().getParameterTypes();
00194 Type retType = expr.getMethod().getReturnType();
00195 Vector pairs = InvokeResolver.getResolver().getPairs(methodDecl, methodName, paramTypes, retType);
00196 System.out.println("For expr " + expr.toString());
00197 System.out.println("Pairs are:");
00198 for (int pi = 0; pi < pairs.size(); pi++)
00199 System.out.println(" " + pairs.elementAt(pi));
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 Vector ifRecord = new Vector();
00216 ClassMethodPair currentPair;
00217 Stmt target;
00218 Local local = Jimple.v().newLocal(nprefix + "INLINETMP", ca.mcgill.sable.soot.BooleanType.v());
00219 locals.put(nprefix + "INLINETMP", local);
00220 if (typeTable.size() > 0)
00221
00222
00223 typeTable.put(local, ConcreteIntegralAbstraction.v());
00224 r = new ca.mcgill.sable.util.VectorList();
00225 for (int pi = 0; pi < pairs.size(); pi++) {
00226 currentPair = (ClassMethodPair) pairs.elementAt(pi);
00227 target = Jimple.v().newNopStmt();
00228 ifRecord.addElement(target);
00229 Value ioe = Jimple.v().newInstanceOfExpr((Local) nparams.get(0), RefType.v(currentPair.getInvClass().getName()));
00230 if (typeTable.size() > 0)
00231
00232
00233 typeTable.put(ioe, ConcreteIntegralAbstraction.v());
00234 r.add(Jimple.v().newAssignStmt(local, ioe));
00235 Value ee = Jimple.v().newEqExpr(local, IntConstant.v(1));
00236 r.add(Jimple.v().newIfStmt(ee, target));
00237 }
00238 for (int pi = 0; pi < pairs.size(); pi++) {
00239 currentPair = (ClassMethodPair) pairs.elementAt(pi);
00240 r.add((Stmt) ifRecord.elementAt(pi));
00241 r.addAll(inlineMethod(currentPair.getInvMethod(), new LinkedList(nparams), null, nret, nprefix + currentPair.getInvMethod().getDeclaringClass() + "_", ntraps, topMethod));
00242 }
00243 } else
00244
00245
00246
00247
00248
00249
00250
00251 r = inlineMethod(expr.getMethod(), nparams, null, nret, nprefix, ntraps, topMethod);
00252 r.add(nret);
00253 traps.addAll(ntraps);
00254 } else {
00255 r = new ca.mcgill.sable.util.VectorList();
00256 r.add(Jimple.v().newInvokeStmt(re.renameExpr(is.getInvokeExpr())));
00257 }
00258 stmt2stmts.put(s, r);
00259 } else
00260 if (s instanceof AssignStmt && ((AssignStmt) s).getRightOp() instanceof InvokeExpr) {
00261 InvokeExpr expr = (InvokeExpr) ((AssignStmt) s).getRightOp();
00262 String exprMethodClass = expr.getMethod().getDeclaringClass().toString();
00263 if (!javaPrefix(exprMethodClass) && !"Bandera".equals(exprMethodClass) && !"edu.ksu.cis.bandera.abstraction.Abstraction".equals(exprMethodClass)) {
00264 List nparams = new Vector();
00265 if (expr instanceof NonStaticInvokeExpr) {
00266 nparams.add(re.renameExpr((Local) ((NonStaticInvokeExpr) expr).getBase()));
00267 }
00268 for (int j = 0; j < expr.getArgCount(); j++)
00269 nparams.add(re.renameExpr(expr.getArg(j)));
00270 String nprefix;
00271 if (expr.getMethod().getName().equals("<init>"))
00272 nprefix = prefix + expr.getMethod().getDeclaringClass() + "_const_";
00273 else
00274 nprefix = prefix + expr.getMethod().getName() + "_";
00275 ca.mcgill.sable.util.List ntraps = new ca.mcgill.sable.util.VectorList();
00276 Stmt nret = Jimple.v().newNopStmt();
00277
00278
00279
00280 if (expr instanceof VirtualInvokeExpr || expr instanceof InterfaceInvokeExpr) {
00281
00282
00283 SootClass methodDecl = expr.getMethod().getDeclaringClass();
00284 String methodName = expr.getMethod().getName();
00285 ca.mcgill.sable.util.List paramTypes = expr.getMethod().getParameterTypes();
00286 Type retType = expr.getMethod().getReturnType();
00287 Vector pairs = InvokeResolver.getResolver().getPairs(methodDecl, methodName, paramTypes, retType);
00288 System.out.println("For expr " + expr.toString());
00289 System.out.println("Pairs are:");
00290 for (int pi = 0; pi < pairs.size(); pi++)
00291 System.out.println(" " + pairs.elementAt(pi));
00292 Vector ifRecord = new Vector();
00293 ClassMethodPair currentPair;
00294 Stmt target;
00295 Local local = Jimple.v().newLocal(nprefix + "INLINETMP", ca.mcgill.sable.soot.BooleanType.v());
00296 locals.put(nprefix + "INLINETMP", local);
00297 if (typeTable.size() > 0)
00298 typeTable.put(local, ConcreteIntegralAbstraction.v());
00299 r = new ca.mcgill.sable.util.VectorList();
00300 for (int pi = 0; pi < pairs.size(); pi++) {
00301 currentPair = (ClassMethodPair) pairs.elementAt(pi);
00302 target = Jimple.v().newNopStmt();
00303 ifRecord.addElement(target);
00304 Value ioe = Jimple.v().newInstanceOfExpr((Local) nparams.get(0), RefType.v(currentPair.getInvClass().getName()));
00305 if (typeTable.size() > 0)
00306
00307
00308 typeTable.put(ioe, ConcreteIntegralAbstraction.v());
00309 r.add(Jimple.v().newAssignStmt(local, ioe));
00310 Value ee = Jimple.v().newEqExpr(local, IntConstant.v(1));
00311 if (typeTable.size() > 0)
00312
00313
00314 typeTable.put(ee, ConcreteIntegralAbstraction.v());
00315 r.add(Jimple.v().newIfStmt(ee, target));
00316 }
00317 for (int pi = 0; pi < pairs.size(); pi++) {
00318 currentPair = (ClassMethodPair) pairs.elementAt(pi);
00319 r.add((Stmt) ifRecord.elementAt(pi));
00320 r.addAll(inlineMethod(currentPair.getInvMethod(), new LinkedList(nparams), re.renameExpr(((AssignStmt) s).getLeftOp()), nret, nprefix + currentPair.getInvMethod().getDeclaringClass() + "_", ntraps, topMethod));
00321 }
00322 } else
00323
00324
00325
00326
00327
00328
00329
00330 r = inlineMethod(expr.getMethod(), nparams, re.renameExpr(((AssignStmt) s).getLeftOp()), nret, nprefix, ntraps, topMethod);
00331 r.add(nret);
00332 traps.addAll(ntraps);
00333 } else {
00334 r = rs.renameStmt(s);
00335 }
00336 stmt2stmts.put(s, r);
00337 }
00338 }
00339 for (i = 0; i < stmts.length; i++) {
00340 s = stmts[i];
00341 r = rs.renameStmt(s);
00342 res.addAll(r);
00343 ca.mcgill.sable.util.Iterator it = r.iterator();
00344 if (annotationManager != null)
00345 while (it.hasNext()) {
00346 Stmt n = (Stmt) it.next();
00347 annotationManager.putInlineStmt(n, s, method);
00348 stmtLocalTable.put(n, localSet);
00349 }
00350 }
00351 ca.mcgill.sable.util.Iterator it = body.getTraps().iterator();
00352 while (it.hasNext()) {
00353 Trap t = (Trap) it.next();
00354 traps.add(Jimple.v().newTrap(t.getException(), (Stmt) rs.renameStmt((Stmt) t.getBeginUnit()).toArray()[0], (Stmt) rs.renameStmt((Stmt) t.getEndUnit()).toArray()[0], (Stmt) rs.renameStmt((Stmt) t.getHandlerUnit()).toArray()[0]));
00355 }
00356 java.util.Iterator it2 = locals.values().iterator();
00357 while (it2.hasNext()) {
00358 localSet.add(new LocalExpr(method, (Local) it2.next()));
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 Inline.isMethodCompiled = isMethodCompiled;
00387 return res;
00388 }
00389
00390
00391
00392
00393
00394 public static boolean javaPrefix(String s) {
00395 if (s.length() >= 4)
00396 return s.substring(0, 4).equals("java");
00397 else
00398 return false;
00399 }
00400 public static void main(String args[]) {
00401 Object m[];
00402 int i;
00403 SootClass cls;
00404 SootClassManager cm = new SootClassManager();
00405 int j = 0;
00406 for (j = 0; j < args.length / 2; j++) {
00407 cls = cm.getClass(args[j * 2]);
00408 cls.resolveIfNecessary();
00409 m = cls.getMethods().toArray();
00410 for (i = 0; i < m.length && !((SootMethod) m[i]).getName().equals(args[j * 2 + 1]); i++);
00411 BuildAndStoreBody bd = new BuildAndStoreBody(Jimple.v(), new StoredBody(ClassFile.v()), 0);
00412 if (i == m.length) {
00413 System.exit(0);
00414 }
00415 SootMethod method = (SootMethod) m[i];
00416 bd.resolveFor(method);
00417 method.getBody(Jimple.v()).printTo(new java.io.PrintWriter(System.out, true), 0);
00418 Inline.inline(method, null);
00419 method.getBody(Jimple.v()).printTo(new java.io.PrintWriter(System.out, true), 0);
00420 Transformations.cleanupCode((JimpleBody) method.getBody(Jimple.v()));
00421 method.getBody(Jimple.v()).printTo(new java.io.PrintWriter(System.out, true), 0);
00422 }
00423 }
00424 }