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

ClassHierarchy.java

00001 package ca.mcgill.sable.soot.jimple;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Jimple, a 3-address code Java(TM) bytecode representation.        *
00005  * Copyright (C) 1998 Etienne Gagnon (gagnon@sable.mcgill.ca).  All  *
00006  * 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 November 2, 1998 by Raja Vallee-Rai (kor@sable.mcgill.ca) (*)
00068    Repackaged all source files and performed extensive modifications.
00069    First initial release of Soot.
00070 
00071  - Modified on October 14, 1998 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00072    Changed TypeNode parents, ancestors and descendants from IntSet to BitSet.
00073 
00074  - Modified on July 29, 1998 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00075    Initial version.
00076 
00077 */
00078 
00079 import ca.mcgill.sable.soot.*;
00080 import ca.mcgill.sable.soot.jimple.*;
00081 import ca.mcgill.sable.util.*;
00082 import java.util.Hashtable;
00083 import java.util.Enumeration;
00084 import java.util.Vector;
00085 import java.util.BitSet;
00086 
00087 /**
00088  * This class encapsulate the class hierarchy, as well as non-reference types.
00089  *
00090  * <P> This class is primarily used by the TypeResolver class, to optimize its computation.
00091  **/
00092 class ClassHierarchy
00093 {
00094     /** Hashtable: SootClassManager -> ClassHierarchy **/
00095     private static Hashtable classHierarchyHashtable = new Hashtable();
00096 
00097     /** The class manager **/
00098     private SootClassManager classManager;
00099 
00100     /** All type node instances **/
00101     private Vector typeNodeInstances = new Vector();
00102 
00103     /** Hashtable: Type -> TypeNode **/
00104     private Hashtable typeNodeHashtable = new Hashtable();
00105 
00106     /** Used to transform boolean, byte, short and char to int **/
00107     private ToInt transform = new ToInt();
00108 
00109     /** Used to create TypeNode instances **/
00110     private ConstructorChooser make = new ConstructorChooser();
00111 
00112     /**
00113      * Transforms boolean, byte, short and char into int.
00114      **/
00115     private class ToInt extends TypeSwitch
00116     {
00117         private Type result;
00118         private Type intType = IntType.v();
00119 
00120         ToInt()
00121         {
00122         }
00123 
00124         /** Transform boolean, byte, short and char into int. **/
00125         Type toInt(Type type)
00126         {
00127             type.apply(this);
00128             return result;
00129         }
00130 
00131         public void caseBooleanType(BooleanType type)
00132         {
00133             result = intType;
00134         }
00135 
00136         public void caseByteType(ByteType type)
00137         {
00138             result = intType;
00139         }
00140 
00141         public void caseShortType(ShortType type)
00142         {
00143             result = intType;
00144         }
00145 
00146         public void caseCharType(CharType type)
00147         {
00148             result = intType;
00149         }
00150 
00151         public void defaultCase(Type type)
00152         {
00153             result = type;
00154         }
00155     }
00156 
00157     /**
00158      * Creates new TypeNode instances usign the appropriate constructor.
00159      **/
00160     private class ConstructorChooser extends TypeSwitch
00161     {
00162         private TypeNode result;
00163 
00164         ConstructorChooser()
00165         {
00166         }
00167 
00168         /** Create a new TypeNode instance for the type parameter. **/
00169         TypeNode typeNode(Type type)
00170         {
00171             type.apply(this);
00172             return result;
00173         }
00174 
00175         public void caseRefType(RefType type)
00176         {
00177             result = new TypeNode(type);
00178         }
00179 
00180         public void caseArrayType(ArrayType type)
00181         {
00182             result = new TypeNode(type);
00183         }
00184 
00185         public void defaultCase(Type type)
00186         {
00187             result = new TypeNode(type);
00188         }
00189     }
00190 
00191     /**
00192      * Each instance of this class represents one type in the class hierarchy (or basic types).
00193      **/
00194     class TypeNode
00195     {
00196         private int id;
00197         private Type type;
00198 
00199         private BitSet parents = new BitSet();
00200         private BitSet ancestors = new BitSet();
00201         private BitSet descendants = new BitSet();
00202 
00203         TypeNode(Type type)
00204         {
00205             this.type = type;
00206             id = typeNodeInstances.size();
00207             typeNodeInstances.addElement(this);
00208             typeNodeHashtable.put(type, this);
00209         }
00210 
00211         TypeNode(RefType type)
00212         {
00213             this((Type) type);
00214 
00215             SootClass sClass = classManager.getClass(type.className);
00216             if(sClass.hasSuperClass())
00217             {
00218                 parents.set(getTypeNode(RefType.v(sClass.getSuperClass().getName())).id);
00219             }
00220             for(Iterator i = sClass.getInterfaces().iterator(); i.hasNext(); )
00221             {
00222                 parents.set(getTypeNode(RefType.v(((SootClass) i.next()).getName())).id);
00223             }
00224 
00225             int size = parents.size();
00226             for(int i = 0; i < size; i++)
00227             {
00228                 if(parents.get(i))
00229                 {
00230                     TypeNode parent = (TypeNode) typeNodeInstances.elementAt(i);
00231                     ancestors.or(parent.ancestors);
00232                 }
00233             }
00234             ancestors.or(parents);
00235 
00236             TypeNode nullNode = getTypeNode(NullType.v());
00237             descendants.set(nullNode.id);
00238             nullNode.ancestors.set(id);
00239 
00240             for(int i = 0; i < size; i++)
00241             {
00242                 if(parents.get(i))
00243                 {
00244                     TypeNode parent = (TypeNode) typeNodeInstances.elementAt(i);
00245                     parent.fixDescendants(id);
00246                 }
00247             }
00248         }
00249 
00250         TypeNode(ArrayType type)
00251         {
00252             this((Type) type);
00253 
00254             if(type.baseType instanceof RefType)
00255             {
00256                 RefType baseType = (RefType) type.baseType;
00257 
00258                 SootClass sClass = classManager.getClass(baseType.className);
00259                 if(sClass.hasSuperClass())
00260                 {
00261                     parents.set(getTypeNode(ArrayType.v(RefType.v(
00262                         sClass.getSuperClass().getName()),
00263                         type.numDimensions)).id);
00264                 }
00265                 for(Iterator i = sClass.getInterfaces().iterator(); i.hasNext(); )
00266                 {
00267                     parents.set(getTypeNode(ArrayType.v(RefType.v(
00268                         ((SootClass) i.next()).getName()),
00269                         type.numDimensions)).id);
00270                 }
00271                 parents.set(getTypeNode(RefType.v("java.lang.Object")).id);
00272                 parents.set(getTypeNode(RefType.v("java.lang.Cloneable")).id);
00273 
00274                 int size = parents.size();
00275                 for(int i = 0; i < size; i++)
00276                 {
00277                     if(parents.get(i))
00278                     {
00279                         TypeNode parent = (TypeNode) typeNodeInstances.elementAt(i);
00280                         ancestors.or(parent.ancestors);
00281                     }
00282                 }
00283                 ancestors.or(parents);
00284 
00285                 TypeNode nullNode = getTypeNode(NullType.v());
00286                 descendants.set(nullNode.id);
00287                 nullNode.ancestors.set(id);
00288 
00289                 for(int i = 0; i < size; i++)
00290                 {
00291                     if(parents.get(i))
00292                     {
00293                         TypeNode parent = (TypeNode) typeNodeInstances.elementAt(i);
00294                         parent.fixDescendants(id);
00295                     }
00296                 }
00297             }
00298             else
00299             {
00300                 parents.set(getTypeNode(RefType.v("java.lang.Object")).id);
00301                 parents.set(getTypeNode(RefType.v("java.lang.Cloneable")).id);
00302 
00303                 int size = parents.size();
00304                 for(int i = 0; i < size; i++)
00305                 {
00306                     if(parents.get(i))
00307                     {
00308                         TypeNode parent = (TypeNode) typeNodeInstances.elementAt(i);
00309                         ancestors.or(parent.ancestors);
00310                     }
00311                 }
00312                 ancestors.or(parents);
00313 
00314                 TypeNode nullNode = getTypeNode(NullType.v());
00315                 descendants.set(nullNode.id);
00316                 nullNode.ancestors.set(id);
00317 
00318                 for(int i = 0; i < size; i++)
00319                 {
00320                     if(parents.get(i))
00321                     {
00322                         TypeNode parent = (TypeNode) typeNodeInstances.elementAt(i);
00323                         parent.fixDescendants(id);
00324                     }
00325                 }
00326             }
00327         }
00328 
00329         /** Adds the given node to the list of descendants of this node and its ancestors. **/
00330         private void fixDescendants(int id)
00331         {
00332             if(descendants.get(id))
00333             {
00334                 return;
00335             }
00336 
00337             int size = parents.size();
00338             for(int i = 0; i < size; i++)
00339             {
00340                 if(parents.get(i))
00341                 {
00342                     TypeNode parent = (TypeNode) typeNodeInstances.elementAt(i);
00343                     parent.fixDescendants(id);
00344                 }
00345             }
00346 
00347             descendants.set(id);
00348         }
00349 
00350         /** Returns the unique id of this type node. **/
00351         public int getId()
00352         {
00353             return id;
00354         }
00355 
00356         /** Returns the type represented by this type node. **/
00357         public Type getType()
00358         {
00359             return type;
00360         }
00361 
00362         /** Returns the list of parents of this type node. **/
00363 /*        public List getParents()
00364         {
00365             LinkedList result = new LinkedList();
00366             int[] elements  = parents.elements();
00367 
00368             for(int i = 0; i < elements.length; i++)
00369             {
00370                 result.add(typeNodeInstances.elementAt(elements[i]));
00371             }
00372 
00373             return result;
00374         } */
00375 
00376        public boolean hasAncestor(TypeNode typeNode)
00377        {
00378            return ancestors.get(typeNode.id);
00379        }
00380 
00381        public boolean hasDescendant(TypeNode typeNode)
00382        {
00383            return descendants.get(typeNode.id);
00384        }
00385 
00386         /** Returns the ids of the ancestors of this type node. **/
00387 /*        public BitSet getAncestors()
00388         {
00389             return (BitSet) ancestors.clone();
00390         } */
00391 
00392         /** Returns the ids of the descendants of this type node. **/
00393 /*        public BitSet getDescendants()
00394         {
00395             return (BitSet) descendants.clone();
00396         } */
00397 
00398         /** Returns a string representation of this object **/
00399 /*        public String toString ()
00400         {
00401             return type.toString();
00402         } */
00403     }
00404     private ClassHierarchy(SootClassManager classManager)
00405     {
00406         if(classManager == null)
00407         {
00408             throw new NullPointerException();
00409         }
00410 
00411         this.classManager = classManager;
00412         classHierarchyHashtable.put(classManager, this);
00413     }
00414     /** Get the class hierarchy for the given class manager. **/
00415     public static ClassHierarchy getClassHierarchy(SootClassManager classManager)
00416     {
00417         ClassHierarchy classHierarchy =
00418             (ClassHierarchy) classHierarchyHashtable.get(classManager);
00419 
00420         if(classHierarchy == null)
00421         {
00422             classHierarchy = new ClassHierarchy(classManager);
00423         }
00424 
00425         return classHierarchy;
00426     }
00427     /** Get the type node for the given type. **/
00428     public TypeNode getTypeNode(Type type)
00429     {
00430         type = transform.toInt(type);
00431         TypeNode typeNode = (TypeNode) typeNodeHashtable.get(type);
00432 
00433         if(typeNode == null)
00434         {
00435             typeNode = make.typeNode(type);
00436         }
00437 
00438         return typeNode;
00439     }
00440     /** Returns a string representation of this object **/
00441     public String toString ()
00442     {
00443         StringBuffer s = new StringBuffer();
00444         boolean colon = false;
00445 
00446         s.append("ClassHierarchy:{");
00447         for(Enumeration e = typeNodeInstances.elements(); e.hasMoreElements();)
00448         {
00449             if(colon)
00450             {
00451                 s.append(",");
00452             }
00453             else
00454             {
00455                 colon = true;
00456             }
00457 
00458             s.append(e.nextElement());
00459         }
00460         s.append("}");
00461 
00462         return s.toString();
00463     }
00464 }

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