Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

Inline.java

00001 package edu.ksu.cis.bandera.prog;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998-2001 SAnToS Laboratories (santos@cis.ksu.edu)  *
00006 
00007  * All rights reserved.                                              *
00008  *                                                                   *
00009  * This work was done as a project in the SAnToS Laboratory,         *
00010  * Department of Computing and Information Sciences, Kansas State    *
00011  * University, USA (http://www.cis.ksu.edu/santos).                  *
00012  * It is understood that any modification not identified as such is  *
00013  * not covered by the preceding statement.                           *
00014  *                                                                   *
00015  * This work is free software; you can redistribute it and/or        *
00016  * modify it under the terms of the GNU Library General Public       *
00017  * License as published by the Free Software Foundation; either      *
00018  * version 2 of the License, or (at your option) any later version.  *
00019  *                                                                   *
00020  * This work is distributed in the hope that it will be useful,      *
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00023  * Library General Public License for more details.                  *
00024  *                                                                   *
00025  * You should have received a copy of the GNU Library General Public *
00026  * License along with this toolkit; if not, write to the             *
00027  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00028  * Boston, MA  02111-1307, USA.                                      *
00029  *                                                                   *
00030  * Java is a trademark of Sun Microsystems, Inc.                     *
00031  *                                                                   *
00032  * To submit a bug report, send a comment, or get the latest news on *
00033  * this project and other SAnToS projects, please visit the web-site *
00034  *                http://www.cis.ksu.edu/santos                      *
00035  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00036 import edu.ksu.cis.bandera.jext.LocalExpr;
00037 import java.util.*;
00038 /**
00039  * Insert the type's description here.
00040  * Creation date: (2/21/00 11:34:07 AM)
00041  * @author: 
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  * Inline2 constructor comment.
00059  */
00060 public Inline() {
00061     locals = new Hashtable();
00062 }
00063 /**
00064  * Insert the method's description here.
00065  * Creation date: (2/21/00 11:37:38 AM)
00066  * @param method ca.mcgill.sable.soot.SootMethod
00067  * @param annotationManager edu.ksu.cis.bandera.annotation.AnnotationManager
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  * Insert the method's description here.
00080  * Creation date: (2/21/00 11:39:52 AM)
00081  * @param method ca.mcgill.sable.soot.SootMethod
00082  * @param annotationManager edu.ksu.cis.bandera.annotation.AnnotationManager
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     //System.out.println(method.getDeclaringClass());
00106     //body.printTo(new java.io.PrintWriter(System.out, true));
00107     //Transformations.aggregate((JimpleBody) method.getBody(Jimple.v()));
00108     //Transformations.packLocals((JimpleBody) method.getBody(Jimple.v()));
00109     //Transformations.removeUnusedLocals((JimpleBody) method.getBody(Jimple.v()));
00110     //Transformations.cleanupCode((JimpleBody) method.getBody(Jimple.v()));
00111     try {
00112         //body.printTo(new java.io.PrintWriter(System.out, true));
00113     } catch (Exception e2) {
00114         e2.printStackTrace();
00115     }
00116 }
00117 /**
00118  * Insert the method's description here.
00119  * Creation date: (2/21/00 11:39:52 AM)
00120  * @param method ca.mcgill.sable.soot.SootMethod
00121  * @param annotationManager edu.ksu.cis.bandera.annotation.AnnotationManager
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                 //Begin Hierarchy Analysis  
00188 
00189                 if (expr instanceof VirtualInvokeExpr || expr instanceof InterfaceInvokeExpr) {
00190                     // Get Tuple for this InvokeExpr
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                     // Generate code as follows:
00201                     //  if (this instanceof Tuple(1).1) goto l1
00202                     //  if (this instanceof Tuple(2).1) goto l2
00203                     //  error
00204                     //  l1: nop
00205                     //      ... inlined body jumps to ret ...
00206                     //  l2: nop
00207                     //      ... inlined body jumps to ret ...
00208                     //  ret:
00209                     //
00210                     // This works because the tuples are in
00211                     // leaves-first order from the inheritence
00212                     // tree (so the cascading instanceof tests
00213                     // find the least matching type).
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                     //End Hierarchy Analysis 
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                     //Begin Hierarchy Analysis 
00279 
00280                     if (expr instanceof VirtualInvokeExpr || expr instanceof InterfaceInvokeExpr) {
00281                         // Same deal for the right side of the assignment statement
00282                         // Get Tuple for this InvokeExpr
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                         //End Hierarchy Analysis
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     it = res.iterator();
00362     while (it.hasNext()) {
00363     s = (Stmt) it.next();
00364     if (s instanceof GotoStmt) {
00365     GotoStmt g = (GotoStmt) s;
00366     if (body.getStmtList().contains(g.getTarget())) {
00367     List l = rs.renameStmt((Stmt) g.getTarget());
00368     if (l == null)
00369     System.out.println("Hopefully in there.");
00370     else
00371     g.setTarget((Stmt) l.toArray()[0]);
00372     }
00373     } else
00374     if (s instanceof IfStmt) {
00375     IfStmt g = (IfStmt) s;
00376     if (body.getStmtList().contains(g.getTarget())) {
00377     List l = rs.renameStmt((Stmt) g.getTarget());
00378     if (l == null)
00379     System.out.println("Hopefully in there.");
00380     else
00381     g.setTarget((Stmt) l.toArray()[0]);
00382     }
00383     }
00384     }
00385     */
00386     Inline.isMethodCompiled = isMethodCompiled;
00387     return res;
00388 }
00389 /**
00390  * This method was created in VisualAge.
00391  * @return boolean
00392  * @param s java.lang.String
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 }

Generated at Thu Feb 7 06:46:42 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001