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

ChaitinAllocator.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 2, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca). (*)
00071    Improved the interference graph builder.
00072    
00073  - Modified on January 20, 1999 by Raja Vallee-Rai (rvalleerai@sable.mcgill.ca). (*)
00074    Extracted the interference graph and local packer and put in this file for
00075    increased pluggability. 
00076 */
00077 
00078 import ca.mcgill.sable.soot.*;
00079 import ca.mcgill.sable.util.*;
00080 
00081 public class ChaitinAllocator
00082 {   
00083     public class InterferenceGraph
00084     {
00085         Map localToLocals;
00086     
00087         private InterferenceGraph()
00088         {
00089         }
00090     
00091         public Set getLocals()
00092         {
00093             return localToLocals.keySet();
00094         }
00095 
00096                 
00097         public InterferenceGraph(JimpleBody body, Type type, LiveLocals liveLocals)
00098         {
00099             StmtList stmtList = body.getStmtList();
00100     
00101             // Initialize localToLocals
00102             {
00103                 localToLocals = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00104     
00105                 Iterator localIt = body.getLocals().iterator();
00106     
00107                 while(localIt.hasNext())
00108                 {
00109                     Local local = (Local) localIt.next();
00110     
00111                     if(local.getType().equals(type))
00112                         localToLocals.put(local, new ArraySet());
00113                 }
00114             }
00115     
00116             // Go through code, noting interferences
00117             {
00118                 Iterator codeIt = stmtList.iterator();
00119     
00120                 while(codeIt.hasNext())
00121                 {
00122                     Stmt stmt = (Stmt) codeIt.next();
00123     
00124                     List liveLocalsAtStmt = liveLocals.getLiveLocalsAfter(stmt);
00125                     
00126                     // Note interferences if this statement is a definition
00127                     {
00128                         if(stmt instanceof DefinitionStmt)
00129                         {
00130                             DefinitionStmt def = (DefinitionStmt) stmt;
00131     
00132                             if(def.getLeftOp() instanceof Local)
00133                             {
00134                                 Local defLocal = (Local) def.getLeftOp();
00135                   
00136                                 if(defLocal.getType().equals(type))
00137                                 {   
00138                                     Iterator localIt = liveLocalsAtStmt.iterator();
00139                                     
00140                                     while(localIt.hasNext())
00141                                     {
00142                                         Local otherLocal = (Local) localIt.next();
00143                                         
00144                                         if(otherLocal.getType().equals(type))
00145                                             setInterference(defLocal, otherLocal);
00146                                     }
00147                                 }
00148                             }    
00149                         }
00150                     }                    
00151                 }
00152             }
00153         }
00154     
00155         public boolean localsInterfere(Local l1, Local l2)
00156         {
00157             return ((Set) localToLocals.get(l1)).contains(l2);
00158         }
00159     
00160         public void setInterference(Local l1, Local l2)
00161         {
00162             ((Set) localToLocals.get(l1)).add(l2);
00163             ((Set) localToLocals.get(l2)).add(l1);
00164         }
00165     
00166         public boolean isEmpty()
00167         {
00168             return localToLocals.isEmpty();
00169         }
00170     
00171         public void removeLocal(Local local)
00172         {
00173             Object[] locals = ((Set) localToLocals.get(local)).toArray();
00174     
00175             // Handle all inverse edges
00176                 for(int i = 0; i < locals.length; i++)
00177                     ((Set) localToLocals.get(locals[i])).remove(local);
00178     
00179             // Handle all outgoing edges
00180                 localToLocals.remove(local);
00181         }
00182     
00183         public Local removeMostInterferingLocal()
00184         {
00185             if(isEmpty())
00186                 throw new RuntimeException("graph is empty");
00187     
00188     
00189             Iterator it = localToLocals.entries().iterator();
00190             Local top = (Local) ((Map.Entry) it.next()).getKey();
00191     
00192             while(it.hasNext())
00193             {
00194                 Local other = (Local) ((Map.Entry) it.next()).getKey();
00195     
00196                 if(((Set) localToLocals.get(other)).size() > ((Set) localToLocals.get(top)).size())
00197                     top = other;
00198             }
00199     
00200     
00201             removeLocal(top);
00202     
00203             return top;
00204         }
00205     
00206         Local[] getInterferencesOf(Local l)
00207         {
00208             Object[] objects = ((Set) localToLocals.get(l)).toArray();
00209             Local[] locals = new Local[objects.length];
00210     
00211             for(int i = 0; i < objects.length; i++)
00212                 locals[i] = (Local) objects[i];
00213     
00214             return locals;
00215         }
00216     
00217         /*
00218         protected Object clone()
00219         {
00220             InterferenceGraph newGraph = InterferenceGraph();
00221     
00222             // Clone all the elements
00223             {
00224                 Iterator it = localToLocals.entries().iterator();
00225     
00226     
00227                 while(it.hasNext())
00228                 {
00229                     Local local = (Local) ((Map.Entry) it.next()).getValue();
00230     
00231                     newGraph.put(local, localToLocals.get(local).clone());
00232                 }
00233             }
00234         } */
00235     }
00236     
00237     public ChaitinAllocator(JimpleBody body)
00238     {
00239         StmtList stmtList = body.getStmtList();
00240 
00241         if(Main.isVerbose)
00242             System.out.println("[" + body.getMethod().getName() + "] Packing locals...");
00243 
00244         CompleteStmtGraph stmtGraph = new CompleteStmtGraph(stmtList);
00245 
00246         LiveLocals liveLocals = new SimpleLiveLocals(stmtGraph);
00247 
00248         Set types;
00249 
00250         // Construct different types available
00251         {
00252             Iterator localIt = body.getLocals().iterator();
00253 
00254             types = new ArraySet();
00255 
00256             while(localIt.hasNext())
00257                 types.add(((Local) localIt.next()).getType());
00258         }
00259 
00260         // Perform one packing per type
00261         {
00262             Iterator typeIt = types.iterator();
00263 
00264             while(typeIt.hasNext())
00265             {
00266                 Type type = (Type) typeIt.next();
00267 
00268                 InterferenceGraph originalGraph;
00269                 InterferenceGraph workingGraph;
00270                 LinkedList localQueue;
00271                 Map localToColor = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00272                 Set usedColors = new HashSet();
00273 
00274                 // Build graphs
00275                     originalGraph = new InterferenceGraph(body, type, liveLocals);
00276                     workingGraph = new InterferenceGraph(body, type, liveLocals);
00277                         // should really be a clone
00278 
00279                 // Color parameter locals first
00280                 {
00281                     Iterator codeIt = stmtList.iterator();
00282 
00283                     while(codeIt.hasNext())
00284                     {
00285                         Stmt s = (Stmt) codeIt.next();
00286 
00287                         if(s instanceof IdentityStmt &&
00288                             ((IdentityStmt) s).getLeftOp() instanceof Local)
00289                         {
00290 
00291                             Local l = (Local) ((IdentityStmt) s).getLeftOp();
00292 
00293                             if(l.getType().equals(type))
00294                             {
00295                                 Local color = new Local("", type);
00296 
00297                                 localToColor.put(l, color);
00298                                 usedColors.add(color);
00299 
00300                                 workingGraph.removeLocal(l);
00301                             }
00302                         }
00303                     }
00304                 }
00305 
00306                 // Construct queue
00307                     localQueue = new LinkedList();
00308 
00309                     // Put in queue in decreasing interference order
00310                     while(!workingGraph.isEmpty())
00311                         localQueue.addFirst(workingGraph.removeMostInterferingLocal());
00312 
00313                         /*                    
00314                     // Put locals in queue in any order
00315                         localQueue.addAll(workingGraph.getLocals());
00316                     */
00317                     
00318                 // Assign colors for each local in queue
00319                     while(!localQueue.isEmpty())
00320                     {
00321                         Local local = (Local) localQueue.removeFirst();
00322                         Set workingColors;
00323 
00324                         // Clone currentColors
00325                         {
00326                             workingColors = new HashSet();
00327                             Iterator colorIt = usedColors.iterator();
00328 
00329                             while(colorIt.hasNext())
00330                                 workingColors.add(colorIt.next());
00331                         }
00332 
00333                         // Remove unavailable colors for this local
00334                         {
00335                             Local[] interferences = originalGraph.getInterferencesOf(local);
00336 
00337                             for(int i = 0; i < interferences.length; i++)
00338                             {
00339                                 if(localToColor.containsKey(interferences[i]))
00340                                     workingColors.remove(localToColor.get(interferences[i]));
00341                             }
00342                         }
00343 
00344                         // Assign a color
00345                         {
00346                             Local assignedColor;
00347 
00348                             if(workingColors.isEmpty())
00349                             {
00350                                 assignedColor = new Local("", type);
00351                                 usedColors.add(assignedColor);
00352                             }
00353                             else
00354                                 assignedColor = (Local) workingColors.iterator().next();
00355 
00356                             localToColor.put(local, assignedColor);
00357                         }
00358                     }
00359 
00360                 // Perform changes on method
00361                 {
00362                     Set originalLocals = new HashSet();
00363 
00364                     // Remove all locals with this type.
00365                     {
00366                         Iterator localIt = body.getLocals().iterator();
00367 
00368                         while(localIt.hasNext())
00369                         {
00370                             Local l = (Local) localIt.next();
00371 
00372                             if(l.getType().equals(type))
00373                             {
00374                                 body.removeLocal(l);
00375                                 originalLocals.add(l);
00376                             }
00377                         }
00378                     }
00379 
00380                     // Give names to the new locals
00381                     {
00382                         Iterator itr = originalLocals.iterator();
00383 
00384                         while(itr.hasNext())
00385                         {
00386                             Local original = (Local) itr.next();
00387                             Local color = (Local) localToColor.get(original);
00388 
00389                             if(color.getName().equals(""))
00390                                 color.setName(original.getName());
00391                         }
00392                     }
00393 
00394                     // Add new locals to the method
00395                     {
00396                         Iterator itr = usedColors.iterator();
00397 
00398                         while(itr.hasNext())
00399                             body.addLocal((Local) itr.next());
00400                     }
00401 
00402                     // Go through all valueBoxes of this method and perform changes
00403                     {
00404                         Iterator codeIt = stmtList.iterator();
00405 
00406                         while(codeIt.hasNext())
00407                         {
00408                             Stmt s = (Stmt) codeIt.next();
00409 
00410                             Iterator boxIt = s.getUseAndDefBoxes().iterator();
00411 
00412                             while(boxIt.hasNext())
00413                             {
00414                                 ValueBox box = (ValueBox) boxIt.next();
00415 
00416                                 if(box.getValue() instanceof Local)
00417                                 {
00418                                     Local l = (Local) box.getValue();
00419 
00420                                     if(l.getType().equals(type))
00421                                         box.setValue((Local) localToColor.get(l));
00422                                 }
00423                             }
00424                         }
00425                     }
00426                 }
00427             }
00428         }
00429     }
00430     public static void packLocals(JimpleBody body)
00431     {
00432         new ChaitinAllocator(body);
00433     }
00434 }

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