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

StmtGraph.java

00001 package ca.mcgill.sable.soot.jimple;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Jimple, a 3-address code Java(TM) bytecode representation.        *
00005  * Copyright (C) 1997, 1998 Raja Vallee-Rai (kor@sable.mcgill.ca)    *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * Modifications by Patrick Lam (plam@sable.mcgill.ca) are           *
00009  * Copyright (C) 1999 Patrick Lam.  All rights reserved.             *
00010  *                                                                   *
00011  * This work was done as a project of the Sable Research Group,      *
00012  * School of Computer Science, McGill University, Canada             *
00013  * (http://www.sable.mcgill.ca/).  It is understood that any         *
00014  * modification not identified as such is not covered by the         *
00015  * preceding statement.                                              *
00016  *                                                                   *
00017  * This work is free software; you can redistribute it and/or        *
00018  * modify it under the terms of the GNU Library General Public       *
00019  * License as published by the Free Software Foundation; either      *
00020  * version 2 of the License, or (at your option) any later version.  *
00021  *                                                                   *
00022  * This work is distributed in the hope that it will be useful,      *
00023  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00025  * Library General Public License for more details.                  *
00026  *                                                                   *
00027  * You should have received a copy of the GNU Library General Public *
00028  * License along with this library; if not, write to the             *
00029  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00030  * Boston, MA  02111-1307, USA.                                      *
00031  *                                                                   *
00032  * Java is a trademark of Sun Microsystems, Inc.                     *
00033  *                                                                   *
00034  * To submit a bug report, send a comment, or get the latest news on *
00035  * this project and other Sable Research Group projects, please      *
00036  * visit the web site: http://www.sable.mcgill.ca/                   *
00037  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00038 
00039 /*
00040  Reference Version
00041  -----------------
00042  This is the latest official version on which this file is based.
00043  The reference version is: $SootVersion: 1.beta.4 $
00044 
00045  Change History
00046  --------------
00047  A) Notes:
00048 
00049  Please use the following template.  Most recent changes should
00050  appear at the top of the list.
00051 
00052  - Modified on [date (March 1, 1900)] by [name]. [(*) if appropriate]
00053    [description of modification].
00054 
00055  Any Modification flagged with "(*)" was done as a project of the
00056  Sable Research Group, School of Computer Science,
00057  McGill University, Canada (http://www.sable.mcgill.ca/).
00058 
00059  You should add your copyright, using the following template, at
00060  the top of this file, along with other copyrights.
00061 
00062  *                                                                   *
00063  * Modifications by [name] are                                       *
00064  * Copyright (C) [year(s)] [your name (or company)].  All rights     *
00065  * reserved.                                                         *
00066  *                                                                   *
00067 
00068  B) Changes:
00069 
00070  - Modified on March 15, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca) (*)
00071    Added a pseudo topological order iterator (and its reverse).
00072    Moved in Patrick's getPath code.
00073    
00074  - Modified on March 13, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca) (*)
00075    Re-organized the timers.
00076 
00077  - Modified on February 3, 1999 by Patrick Lam (plam@sable.mcgill.ca) (*)
00078    Added changes in support of the Grimp intermediate
00079    representation (with aggregated-expressions).
00080 
00081  - Modified on November 2, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00082    Repackaged all source files and performed extensive modifications.
00083    First initial release of Soot.
00084 
00085  - Modified on September 22, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca). (*)
00086    Added support for exception edge inclusion.
00087 
00088  - Modified on 23-Jul-1998 by Raja Vallee-Rai (kor@sable.mcgill.ca). (*)
00089    Many changes.
00090 
00091  - Modified on 15-Jun-1998 by Raja Vallee-Rai (kor@sable.mcgill.ca). (*)
00092    First internal release (Version 0.1).
00093 */
00094 
00095 import ca.mcgill.sable.soot.*;
00096 import ca.mcgill.sable.util.*;
00097 
00098 public class StmtGraph
00099 {
00100     List heads;
00101     List tails;
00102 
00103     Map stmtToSuccs;        // Stmt to List
00104     Map stmtToPreds;        // Stmt to List
00105     SootMethod method;
00106     List stmts;
00107     int size;
00108     StmtList stmtList;
00109 
00110     private boolean isPseudoTopologicalOrderReady;
00111     private List topOrder;
00112               
00113     private boolean isReversePseudoTopologicalOrderReady;
00114     private List reverseTopOrder;
00115               
00116     private Map stmtToColor;
00117     private final int WHITE = 0,
00118               GRAY = 1,
00119               BLACK = 2;
00120 
00121     private LinkedList order;
00122     private boolean isReversed;
00123     
00124     StmtGraph(StmtList stmtList, boolean addExceptionEdges)
00125     {
00126         this.stmtList = stmtList;
00127         this.method = getBody().getMethod();
00128         
00129         if(Main.isVerbose)
00130             System.out.println("[" + method.getName() + 
00131             "]     Constructing StmtGraph...");
00132       
00133         if(Main.isProfilingOptimization)
00134             Main.graphTimer.start();
00135       
00136         // Build stmts (for iterator)
00137         {
00138             stmts = new LinkedList();
00139 
00140             stmts.addAll(stmtList);
00141             stmts = Collections.unmodifiableList(stmts);
00142             size = stmtList.size();
00143         }
00144 
00145         // Build successors
00146         {
00147             Map classToHandler = new HashMap(); // list of exceptions being caught, and their handlers
00148 
00149             stmtToSuccs = new HashMap(size * 2 + 1, 0.7f);
00150             stmtToPreds = new HashMap(size * 2 + 1, 0.7f);
00151 
00152 
00153             // Add regular successors
00154             {
00155                 ListIterator stmtIt = stmtList.listIterator();
00156 
00157                 while(stmtIt.hasNext())
00158                 {
00159                     Stmt s = (Stmt) stmtIt.next();
00160 
00161                     List successors = new ArrayList();
00162                     boolean addNext = true;
00163 
00164                     if(s instanceof GotoStmt)
00165                     {
00166                         successors.add(((GotoStmt) s).getTarget());
00167                         addNext = false;
00168                     }
00169                     else if(s instanceof IfStmt)
00170                     {
00171                         successors.add(((IfStmt) s).getTarget());
00172                     }
00173                     else if(s instanceof ReturnStmt || s instanceof ReturnVoidStmt)
00174                     {
00175                         addNext = false;
00176                     }
00177                     else if(s instanceof RetStmt)
00178                     {
00179                         // Add all statements which get their address taken
00180 
00181                         ListIterator it = stmtList.listIterator();
00182 
00183                         while(it.hasNext())
00184                         {
00185                             Stmt stmt = (Stmt) it.next();
00186 
00187                             if(stmt instanceof AssignStmt)
00188                             {
00189                                 AssignStmt as = (AssignStmt) stmt;
00190 
00191                                 if(as.getRightOp() instanceof NextNextStmtRef)
00192                                 {
00193                                     Iterator succIt = stmtList.listIterator(it.nextIndex());
00194 
00195                                     if(succIt.hasNext())
00196                                     {
00197                                         succIt.next();
00198 
00199                                         if(succIt.hasNext())
00200                                             successors.add(succIt.next());
00201                                     }
00202                                 }
00203                             }
00204                         }
00205 
00206                         addNext = false;
00207                     }
00208                     else if(s instanceof ThrowStmt)
00209                     {
00210                         addNext = false;
00211                     }
00212                     else if(s instanceof LookupSwitchStmt)
00213                     {
00214                         LookupSwitchStmt l = (LookupSwitchStmt) s;
00215 
00216                         successors.add(l.getDefaultTarget());
00217 
00218                         Iterator targetIt = l.getTargets().iterator();
00219 
00220                         while(targetIt.hasNext())
00221                             successors.add(targetIt.next());
00222 
00223                         addNext = false;
00224                     }
00225                     else if(s instanceof TableSwitchStmt)
00226                     {
00227                         TableSwitchStmt t = (TableSwitchStmt) s;
00228 
00229                         successors.add(t.getDefaultTarget());
00230 
00231                         Iterator targetIt = t.getTargets().iterator();
00232 
00233                         while(targetIt.hasNext())
00234                             successors.add(targetIt.next());
00235 
00236 
00237                         addNext = false;
00238                     }
00239 
00240                     // Put the next statement as the successor
00241                         if(addNext)
00242                         {
00243                             successors.add(stmtList.get(stmtIt.nextIndex()));
00244                         }
00245 
00246 
00247                     // Store away successors
00248                         stmtToSuccs.put(s, successors);
00249                 }
00250             }
00251 
00252             // Add exception based successors
00253                 if(addExceptionEdges)
00254                 {
00255                     Iterator trapIt = getBody().getTraps().
00256                         iterator();
00257 
00258                     while(trapIt.hasNext())
00259                     {
00260                         Trap trap = (Trap) trapIt.next();
00261 
00262                         Stmt beginStmt = (Stmt) trap.getBeginUnit();
00263                         Stmt handlerStmt = (Stmt) trap.getHandlerUnit();
00264                         Stmt endStmt = (Stmt) trap.getEndUnit();
00265                         Iterator stmtIt = stmtList.listIterator(stmtList.indexOf(beginStmt));
00266 
00267                         for(;;)
00268                         {
00269                             Stmt s = (Stmt) stmtIt.next();
00270 
00271                             ((List) stmtToSuccs.get(s)).add(handlerStmt);
00272 
00273                             if(s == endStmt)
00274                                 break;
00275                         }
00276                     }
00277                 }
00278 
00279             // Make successors unmodifiable
00280             {
00281                 ListIterator stmtIt = stmtList.listIterator();
00282 
00283                 while(stmtIt.hasNext())
00284                 {
00285                     Stmt s = (Stmt) stmtIt.next();
00286                     stmtToSuccs.put(s, Collections.unmodifiableList((List) stmtToSuccs.get(s)));
00287                 }
00288             }
00289         }
00290 
00291 
00292         // Build predecessors
00293         {
00294             Map stmtToPredList = new HashMap(size * 2 + 1, 0.7f);
00295 
00296             // initialize the pred sets to empty
00297             {
00298                 Iterator stmtIt = stmtList.iterator();
00299 
00300                 while(stmtIt.hasNext())
00301                 {
00302                     stmtToPredList.put(stmtIt.next(), new ArrayList());
00303                 }
00304             }
00305 
00306             // Modify preds set for each successor for this statement
00307             {
00308                 Iterator stmtIt = stmtList.iterator();
00309 
00310                 while(stmtIt.hasNext())
00311                 {
00312                     Stmt s = (Stmt) stmtIt.next();
00313                     Iterator succIt = ((List) stmtToSuccs.get(s)).iterator();
00314 
00315                     while(succIt.hasNext())
00316                     {
00317                         List predList = (List) stmtToPredList.get(succIt.next());
00318                         predList.add(s);
00319                     }
00320                 }
00321             }
00322 
00323 
00324             // Convert pred lists to arrays
00325             {
00326                 Iterator stmtIt = stmtList.iterator();
00327 
00328                 while(stmtIt.hasNext())
00329                 {
00330                     Stmt s = (Stmt) stmtIt.next();
00331 
00332                     List predList = (List) stmtToPredList.get(s);
00333                     stmtToPreds.put(s, Collections.unmodifiableList(predList));
00334                 }
00335             }
00336 
00337         }
00338 
00339         // Build tails
00340         {
00341             List tailList = new ArrayList();
00342 
00343             // Build the set
00344             {
00345                 Iterator stmtIt = stmtList.iterator();
00346 
00347                 while(stmtIt.hasNext())
00348                 {
00349                     Stmt s = (Stmt) stmtIt.next();
00350 
00351                     List succs = (List) stmtToSuccs.get(s);
00352 
00353                     if(succs.size() == 0)
00354                         tailList.add(s);
00355                 }
00356             }
00357 
00358             tails = Collections.unmodifiableList(tailList);
00359         }
00360 
00361         // Build heads
00362         {
00363             List headList = new ArrayList();
00364 
00365             // Build the set
00366             {
00367                 Iterator stmtIt = stmtList.iterator();
00368 
00369                 while(stmtIt.hasNext())
00370                 {
00371                     Stmt s = (Stmt) stmtIt.next();
00372                     List preds = (List) stmtToPreds.get(s);
00373 
00374                     if(preds.size() == 0)
00375                         headList.add(s);
00376                 }
00377             }
00378 
00379             heads = Collections.unmodifiableList(headList);
00380         }
00381 
00382         if(Main.isProfilingOptimization)
00383             Main.graphTimer.end();
00384     }
00385     private LinkedList computeOrder(boolean isReversed)
00386     {
00387         stmtToColor = new HashMap();
00388     
00389         this.isReversed = isReversed;
00390         order = new LinkedList();
00391         
00392         // Color all statements white
00393         {
00394             Iterator stmtIt = iterator();
00395             
00396             while(stmtIt.hasNext())
00397             {
00398                 Stmt s = (Stmt) stmtIt.next();
00399                 
00400                 stmtToColor.put(s, new Integer(WHITE));
00401             }
00402         }
00403         
00404         // Visit each statement 
00405         {
00406             Iterator stmtIt = iterator();
00407             
00408             while(stmtIt.hasNext())
00409             {
00410                 Stmt s = (Stmt) stmtIt.next();
00411                
00412                 if(((Integer) stmtToColor.get(s)).intValue() == WHITE)
00413                     visitStmt(s); 
00414             }
00415         }
00416         
00417         return order;
00418     }
00419     public StmtBody getBody()
00420     {
00421         return stmtList.getBody();
00422     }
00423   /** Look for a path, in g, from def to use. 
00424    * This path has to lie inside an extended basic block 
00425    * (and this property implies uniqueness.) */
00426   /* The path returned includes from and to.
00427      returns null if there is no such path */
00428   
00429   public List getExtendedBasicBlockPathBetween(Stmt from, Stmt to)
00430     {
00431         StmtGraph g = this;
00432         
00433       // if this holds, we're doomed to failure!!!
00434       if (g.getPredsOf(to).size() > 1)
00435         return null;
00436 
00437       // pathStack := list of succs lists
00438       // pathStackIndex := last visited index in pathStack
00439       LinkedList pathStack = new LinkedList();
00440       LinkedList pathStackIndex = new LinkedList();
00441 
00442       pathStack.add(from);
00443       pathStackIndex.add(new Integer(0));
00444 
00445       int psiMax = (g.getSuccsOf((Stmt)pathStack.get(0))).size();
00446       int level = 0;
00447       while (((Integer)pathStackIndex.get(0)).intValue() != psiMax)
00448         {
00449           int p = ((Integer)(pathStackIndex.get(level))).intValue();
00450 
00451           List succs = g.getSuccsOf((Stmt)(pathStack.get(level)));
00452           if (p >= succs.size())
00453             {
00454               // no more succs - backtrack to previous level.
00455 
00456               pathStack.remove(level);
00457               pathStackIndex.remove(level);
00458 
00459               level--;
00460               int q = ((Integer)pathStackIndex.get(level)).intValue();
00461               pathStackIndex.set(level, new Integer(q+1));
00462               continue;
00463             }
00464 
00465           Stmt betweenStmt = (Stmt)(succs.get(p));
00466 
00467           // we win!
00468           if (betweenStmt == to)
00469             {
00470               pathStack.add(to);
00471               return pathStack;
00472             }
00473 
00474           // check preds of betweenStmt to see if we should visit its kids.
00475           if (g.getPredsOf(betweenStmt).size() > 1)
00476             {
00477               pathStackIndex.set(level, new Integer(p+1));
00478               continue;
00479             }
00480 
00481           // visit kids of betweenStmt.
00482           level++;
00483           pathStackIndex.add(new Integer(0));
00484           pathStack.add(betweenStmt);
00485         }
00486       return null;
00487     }
00488     public List getHeads()
00489     {
00490         return heads;
00491     }
00492     public List getPredsOf(Stmt s)
00493     {
00494         if(!stmtToPreds.containsKey(s))
00495             throw new RuntimeException("Invalid stmt" + s);
00496 
00497         return (List) stmtToPreds.get(s);
00498     }
00499     public List getSuccsOf(Stmt s)
00500     {
00501         if(!stmtToSuccs.containsKey(s))
00502             throw new RuntimeException("Invalid stmt" + s);
00503 
00504         return (List) stmtToSuccs.get(s);
00505     }
00506     public List getTails()
00507     {
00508         return tails;
00509     }
00510     public Iterator iterator()
00511     {
00512         return stmts.iterator();
00513     }
00514     public Iterator pseudoTopologicalOrderIterator()
00515     {
00516         if(!isPseudoTopologicalOrderReady)
00517         {
00518             topOrder = Collections.unmodifiableList(computeOrder(false));
00519             isPseudoTopologicalOrderReady = true;
00520         }
00521         
00522         return topOrder.iterator();
00523     }
00524     public Iterator reversePseudoTopologicalOrderIterator()
00525     {
00526         if(!isReversePseudoTopologicalOrderReady)
00527         {
00528             reverseTopOrder = Collections.unmodifiableList(computeOrder(false));
00529             isReversePseudoTopologicalOrderReady = true;
00530         }
00531                 
00532         return reverseTopOrder.iterator();
00533     }
00534     public int size()
00535     {
00536         return size;
00537     }
00538     // Unfortunately, the nice recursive solution fails
00539     // because of stack overflows
00540     /*
00541     private void visitStmt(Stmt s)
00542     {
00543         stmtToColor.put(s, new Integer(GRAY));
00544          
00545         Iterator succIt = getSuccsOf(s).iterator();
00546         
00547         while(succIt.hasNext())
00548         {
00549             Stmt succ = (Stmt) succIt.next();
00550             
00551             if(((Integer) stmtToColor.get(succ)).intValue() == WHITE)
00552                 visitStmt(succ);
00553         }
00554         
00555         stmtToColor.put(s, new Integer(BLACK));
00556          
00557         if(isReversed)
00558             order.addLast(s);
00559         else
00560             order.addFirst(s); 
00561     }*/
00562     
00563     // Fill in the 'order' list with a pseudo topological order (possibly reversed)
00564     // list of statements starting at s.  Simulates recursion with a stack.
00565     
00566     private void visitStmt(Stmt startStmt)
00567     {
00568         LinkedList stmtStack = new LinkedList();
00569         LinkedList indexStack = new LinkedList();
00570         
00571         stmtToColor.put(startStmt, new Integer(GRAY));
00572         
00573         stmtStack.addLast(startStmt);
00574         indexStack.addLast(new Integer(-1));
00575         
00576         while(!stmtStack.isEmpty())
00577         {
00578             int toVisitIndex = ((Integer) indexStack.removeLast()).intValue();
00579             Stmt toVisitStmt = (Stmt) stmtStack.getLast();
00580             
00581             toVisitIndex++;
00582             
00583             indexStack.addLast(new Integer(toVisitIndex));
00584             
00585             if(toVisitIndex >= getSuccsOf(toVisitStmt).size())
00586             {
00587                 // Visit this node now that we ran out of children 
00588                     if(isReversed)
00589                         order.addLast(toVisitStmt);
00590                     else
00591                         order.addFirst(toVisitStmt);
00592                            
00593                     stmtToColor.put(toVisitStmt, new Integer(BLACK));                
00594                 
00595                 // Pop this node off
00596                     stmtStack.removeLast();
00597                     indexStack.removeLast();
00598             }
00599             else
00600             {
00601                 Stmt childStmt = (Stmt) getSuccsOf(toVisitStmt).get(toVisitIndex);
00602                 
00603                 // Visit this child next if not already visited (or on stack)
00604                     if(((Integer) stmtToColor.get(childStmt)).intValue() == WHITE)
00605                     {
00606                         stmtToColor.put(childStmt, new Integer(GRAY));
00607                         
00608                         stmtStack.addLast(childStmt);
00609                         indexStack.addLast(new Integer(-1));
00610                     }
00611             }
00612         }
00613     }
00614 }

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