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

FastAllocator.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  * This work was done as a project of the Sable Research Group,      *
00009  * School of Computer Science, McGill University, Canada             *
00010  * (http://www.sable.mcgill.ca/).  It is understood that any         *
00011  * modification not identified as such is not covered by the         *
00012  * preceding statement.                                              *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this library; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * Java is a trademark of Sun Microsystems, Inc.                     *
00030  *                                                                   *
00031  * To submit a bug report, send a comment, or get the latest news on *
00032  * this project and other Sable Research Group projects, please      *
00033  * visit the web site: http://www.sable.mcgill.ca/                   *
00034  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00035 
00036 /*
00037  Reference Version
00038  -----------------
00039  This is the latest official version on which this file is based.
00040  The reference version is: $SootVersion: 1.beta.4 $
00041 
00042  Change History
00043  --------------
00044  A) Notes:
00045 
00046  Please use the following template.  Most recent changes should
00047  appear at the top of the list.
00048 
00049  - Modified on [date (March 1, 1900)] by [name]. [(*) if appropriate]
00050    [description of modification].
00051 
00052  Any Modification flagged with "(*)" was done as a project of the
00053  Sable Research Group, School of Computer Science,
00054  McGill University, Canada (http://www.sable.mcgill.ca/).
00055 
00056  You should add your copyright, using the following template, at
00057  the top of this file, along with other copyrights.
00058 
00059  *                                                                   *
00060  * Modifications by [name] are                                       *
00061  * Copyright (C) [year(s)] [your name (or company)].  All rights     *
00062  * reserved.                                                         *
00063  *                                                                   *
00064 
00065  B) Changes:
00066 
00067  - Modified on March 13, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca) (*)
00068    Re-organized the timers.
00069 
00070  - Modified on February 28, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca). (*)
00071    Made the packer work on StmtBody's.
00072    
00073  - Modified on February 2, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca). (*)
00074    Improved the interference graph builder.
00075 
00076  - Modified on January 20, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca). (*)
00077    Extracted the interference graph and local packer and put in this file for
00078    increased pluggability. 
00079 */
00080 
00081 import ca.mcgill.sable.soot.*;
00082 import ca.mcgill.sable.util.*;
00083 
00084 public class FastAllocator
00085 {   
00086     public class InterferenceGraph
00087     {
00088         Map localToLocals;
00089     
00090         private InterferenceGraph()
00091         {
00092         }
00093     
00094         public Set getLocals()
00095         {
00096             return localToLocals.keySet();
00097         }
00098         
00099         public InterferenceGraph(StmtBody body, Type type, LiveLocals liveLocals)
00100         {
00101             StmtList stmtList = body.getStmtList();
00102     
00103             // Initialize localToLocals
00104             {
00105                 localToLocals = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00106     
00107                 Iterator localIt = body.getLocals().iterator();
00108     
00109                 while(localIt.hasNext())
00110                 {
00111                     Local local = (Local) localIt.next();
00112     
00113                     if(local.getType().equals(type))
00114                         localToLocals.put(local, new ArraySet());
00115                 }
00116             }
00117     
00118             // Go through code, noting interferences
00119             {
00120                 Iterator codeIt = stmtList.iterator();
00121     
00122                 while(codeIt.hasNext())
00123                 {
00124                     Stmt stmt = (Stmt) codeIt.next();
00125     
00126                     List liveLocalsAtStmt = liveLocals.getLiveLocalsAfter(stmt);
00127                     
00128                     // Note interferences if this statement is a definition
00129                     {
00130                         if(stmt instanceof DefinitionStmt)
00131                         {
00132                             DefinitionStmt def = (DefinitionStmt) stmt;
00133     
00134                             if(def.getLeftOp() instanceof Local)
00135                             {
00136                                 Local defLocal = (Local) def.getLeftOp();
00137                   
00138                                 if(defLocal.getType().equals(type))
00139                                 {   
00140                                     Iterator localIt = liveLocalsAtStmt.iterator();
00141                                     
00142                                     while(localIt.hasNext())
00143                                     {
00144                                         Local otherLocal = (Local) localIt.next();
00145                                         
00146                                         if(otherLocal.getType().equals(type))
00147                                             setInterference(defLocal, otherLocal);
00148                                     }
00149                                 }
00150                             }    
00151                         }
00152                     }                    
00153                 }
00154             }
00155         }
00156     
00157         public boolean localsInterfere(Local l1, Local l2)
00158         {
00159             return ((Set) localToLocals.get(l1)).contains(l2);
00160         }
00161     
00162         public void setInterference(Local l1, Local l2)
00163         {
00164             ((Set) localToLocals.get(l1)).add(l2);
00165             ((Set) localToLocals.get(l2)).add(l1);
00166         }
00167     
00168         public boolean isEmpty()
00169         {
00170             return localToLocals.isEmpty();
00171         }
00172     
00173         /*
00174         public void removeLocal(Local local)
00175         {
00176             Object[] locals = ((Set) localToLocals.get(local)).toArray();
00177     
00178             // Handle all inverse edges
00179                 for(int i = 0; i < locals.length; i++)
00180                     ((Set) localToLocals.get(locals[i])).remove(local);
00181     
00182             // Handle all outgoing edges
00183                 localToLocals.remove(local);
00184         }
00185     
00186         public Local removeMostInterferingLocal()
00187         {
00188             if(isEmpty())
00189                 throw new RuntimeException("graph is empty");
00190     
00191     
00192             Iterator it = localToLocals.entries().iterator();
00193             Local top = (Local) ((Map.Entry) it.next()).getKey();
00194     
00195             while(it.hasNext())
00196             {
00197                 Local other = (Local) ((Map.Entry) it.next()).getKey();
00198     
00199                 if(((Set) localToLocals.get(other)).size() > ((Set) localToLocals.get(top)).size())
00200                     top = other;
00201             }
00202     
00203     
00204             removeLocal(top);
00205     
00206             return top;
00207         }
00208     */
00209     /*
00210         Set getInterferencesOf(Local l)
00211         {
00212             return localToLocals.get(l);
00213         }
00214       */
00215         
00216         Local[] getInterferencesOf(Local l)
00217         {
00218             Object[] objects = ((Set) localToLocals.get(l)).toArray();
00219             Local[] locals = new Local[objects.length];
00220     
00221             for(int i = 0; i < objects.length; i++)
00222                 locals[i] = (Local) objects[i];
00223     
00224             return locals; 
00225         }
00226     
00227         /*
00228         protected Object clone()
00229         {
00230             InterferenceGraph newGraph = InterferenceGraph();
00231     
00232             // Clone all the elements
00233             {
00234                 Iterator it = localToLocals.entries().iterator();
00235     
00236     
00237                 while(it.hasNext())
00238                 {
00239                     Local local = (Local) ((Map.Entry) it.next()).getValue();
00240     
00241                     newGraph.put(local, localToLocals.get(local).clone());
00242                 }
00243             }
00244         } */
00245     }
00246     
00247     public FastAllocator(StmtBody body)
00248     {
00249         StmtList stmtList = body.getStmtList();
00250 
00251         if(Main.isVerbose)
00252             System.out.println("[" + body.getMethod().getName() + "] Packing locals...");
00253 
00254         // Jimple.printStmtListBody_debug(body, new java.io.PrintWriter(System.out));
00255 
00256         CompleteStmtGraph stmtGraph = new CompleteStmtGraph(stmtList);
00257 
00258             
00259         LiveLocals liveLocals;
00260 
00261         if(Main.usePackedLive)
00262             liveLocals = new SimpleLiveLocals(stmtGraph);
00263         else 
00264             liveLocals = new SparseLiveLocals(stmtGraph);
00265 
00266         Set types;
00267 
00268         // Construct different types available
00269         {
00270             Iterator localIt = body.getLocals().iterator();
00271 
00272             types = new ArraySet();
00273 
00274             while(localIt.hasNext())
00275                 types.add(((Local) localIt.next()).getType());
00276         }
00277 
00278         // Perform one packing per type
00279         {
00280             Iterator typeIt = types.iterator();
00281 
00282             while(typeIt.hasNext())
00283             {
00284                 Type type = (Type) typeIt.next();
00285 
00286                 if(Main.isVerbose)
00287                     System.out.println("[" + body.getMethod().getName() + "](Packing locals)    Packing type " +
00288                         type.toString() + "...");
00289 
00290                 InterferenceGraph originalGraph;
00291                 InterferenceGraph workingGraph;
00292                 LinkedList localQueue;
00293                 Map localToColor = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00294                 Set usedColors = new HashSet();
00295 
00296                 // Build graphs
00297                     if(Main.isVerbose)
00298                         System.out.println("[" + body.getMethod().getName() + "](Packing locals)    " + 
00299                             "Building interference graph...");
00300 
00301                     originalGraph = new InterferenceGraph(body, type, liveLocals);
00302                     // workingGraph = new InterferenceGraph(body, type, liveLocals);
00303                         // should really be a clone
00304 
00305                 // Color parameter locals first
00306                 {
00307                     Iterator codeIt = stmtList.iterator();
00308 
00309                     while(codeIt.hasNext())
00310                     {
00311                         Stmt s = (Stmt) codeIt.next();
00312 
00313                         if(s instanceof IdentityStmt &&
00314                             ((IdentityStmt) s).getLeftOp() instanceof Local)
00315                         {
00316 
00317                             Local l = (Local) ((IdentityStmt) s).getLeftOp();
00318 
00319                             if(l.getType().equals(type))
00320                             {
00321                                 Local color = new Local("", type);
00322 
00323                                 localToColor.put(l, color);
00324                                 usedColors.add(color);
00325 
00326                                 //workingGraph.removeLocal(l);
00327                             }
00328                         }
00329                         else {
00330                             // At the end of the IdentityStmt's
00331                             break;
00332                         }
00333                     }
00334                 }
00335 
00336                 // Construct queue
00337                     localQueue = new LinkedList();
00338 
00339                     // Put locals in queue in any order
00340                         localQueue.addAll(originalGraph.getLocals());
00341                     
00342                 // Assign colors for each local in queue
00343                 {
00344                     if(Main.isVerbose) 
00345                     {
00346                         System.out.println("[" + body.getMethod().getName() + "](Packing locals)    " +
00347                             "Coloring each local...");
00348                     }
00349                     
00350                     while(!localQueue.isEmpty())
00351                     {
00352                         Local local = (Local) localQueue.removeFirst();
00353                         Set workingColors;
00354 
00355                         if(localToColor.containsKey(local))
00356                         {
00357                             // Already assigned, probably a parameter
00358                             continue;
00359                         }
00360                         
00361                         // Clone currentColors
00362                         {
00363                             workingColors = new HashSet();
00364                             Iterator colorIt = usedColors.iterator();
00365 
00366                             while(colorIt.hasNext())
00367                                 workingColors.add(colorIt.next());
00368                         }
00369 
00370                         // Remove unavailable colors for this local
00371                         {
00372                             Local[] interferences = originalGraph.getInterferencesOf(local);
00373 
00374                             for(int i = 0; i < interferences.length; i++)
00375                             {
00376                                 if(localToColor.containsKey(interferences[i]))
00377                                     workingColors.remove(localToColor.get(interferences[i]));
00378                             }
00379                         }
00380 
00381                         /*
00382                         // Remove unavailable colors for this local
00383                         {
00384                             Iterator interferences = originalGraph.getInterferencesOf(local).iterator();
00385 
00386                             while(interferences.hasNext())
00387                             {
00388                                 Local l = (Local) interferences.next();
00389                             
00390                                 if(localToColor.containsKey(l));
00391                                     workingColors.remove(localToColor.get(l));
00392                             }
00393                         }
00394 */
00395 
00396                         // Assign a color
00397                         {
00398                             Local assignedColor;
00399 
00400                             if(workingColors.isEmpty())
00401                             {
00402                                 assignedColor = new Local("", type);
00403                                 usedColors.add(assignedColor);
00404                             }
00405                             else
00406                                 assignedColor = (Local) workingColors.iterator().next();
00407 
00408                             localToColor.put(local, assignedColor);
00409                         }
00410                     }
00411                 }
00412                 
00413                 // Perform changes on method
00414                 {
00415                     Set originalLocals = new HashSet();
00416 
00417                     // Remove all locals with this type.
00418                     {
00419                         Iterator localIt = body.getLocals().iterator();
00420                         List locals = body.getLocals();
00421                         
00422                         while(localIt.hasNext())
00423                         {
00424                             Local l = (Local) localIt.next();
00425 
00426                             if(l.getType().equals(type))
00427                             {
00428                                 locals.remove(l);
00429                                 originalLocals.add(l);
00430                             }
00431                         }
00432                     }
00433 
00434                     // Give names to the new locals
00435                     {
00436                         Iterator itr = originalLocals.iterator();
00437 
00438                         while(itr.hasNext())
00439                         {
00440                             Local original = (Local) itr.next();
00441                             Local color = (Local) localToColor.get(original);
00442 
00443                             if(color.getName().equals(""))
00444                                 color.setName(original.getName());
00445                         }
00446                     }
00447 
00448                     // Add new locals to the method
00449                     {
00450                         Iterator itr = usedColors.iterator();
00451                         List locals = body.getLocals();
00452                         
00453                         while(itr.hasNext())
00454                             locals.add((Local) itr.next());
00455                     }
00456 
00457                     // Go through all valueBoxes of this method and perform changes
00458                     {
00459                         Iterator codeIt = stmtList.iterator();
00460 
00461                         while(codeIt.hasNext())
00462                         {
00463                             Stmt s = (Stmt) codeIt.next();
00464 
00465                             Iterator boxIt = s.getUseAndDefBoxes().iterator();
00466 
00467                             while(boxIt.hasNext())
00468                             {
00469                                 ValueBox box = (ValueBox) boxIt.next();
00470 
00471                                 if(box.getValue() instanceof Local)
00472                                 {
00473                                     Local l = (Local) box.getValue();
00474 
00475                                     if(l.getType().equals(type))
00476                                         box.setValue((Local) localToColor.get(l));
00477                                 }
00478                             }
00479                         }
00480                     }
00481                 }
00482             }
00483         }
00484     }
00485     public static void packLocals(StmtBody body)
00486     {
00487         new FastAllocator(body);
00488     }
00489 }

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