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

Builder.java

00001 package edu.ksu.cis.bandera.birc;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * Bandera, a Java(TM) analysis and transformation toolkit           *
00005  * Copyright (C) 1998, 1999   James Corbett (corbett@hawaii.edu)     *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project in the SAnToS Laboratory,         *
00009  * Department of Computing and Information Sciences, Kansas State    *
00010  * University, USA (http://www.cis.ksu.edu/santos).                  *
00011  * It is understood that any modification not identified as such is  *
00012  * not covered by the 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 toolkit; 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 SAnToS projects, please visit the web-site *
00033  *                http://www.cis.ksu.edu/santos                      *
00034  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00035 import java.io.*;
00036 import java.util.Vector;
00037 import java.util.Hashtable;
00038 
00039 import edu.ksu.cis.bandera.bir.TransSystem;
00040 import edu.ksu.cis.bandera.bir.BirThread;
00041 import edu.ksu.cis.bandera.bir.BirConstants;
00042 import edu.ksu.cis.bandera.bir.LockAction;
00043 import edu.ksu.cis.bandera.bir.LockTest;
00044 import edu.ksu.cis.bandera.bir.ThreadLocTest;
00045 import edu.ksu.cis.bandera.bir.Location;
00046 import edu.ksu.cis.bandera.bir.LocVector;
00047 import edu.ksu.cis.bandera.bir.StateVar;
00048 import edu.ksu.cis.bandera.bir.Transformation;
00049 import edu.ksu.cis.bandera.bir.ActionVector;
00050 import edu.ksu.cis.bandera.bir.TransVector;
00051 import edu.ksu.cis.bandera.bir.BirTrace;
00052 import edu.ksu.cis.bandera.util.DefaultValues;
00053 import edu.ksu.cis.bandera.prog.HierarchyQuery;
00054 
00055 import ca.mcgill.sable.util.*;
00056 import ca.mcgill.sable.soot.*;
00057 import ca.mcgill.sable.soot.jimple.*;
00058 
00059 /**
00060  * Builder is the main class of BIRC, which extracts a transition
00061  * system from a restricted Jimple representation of a Java program.
00062  * <p>
00063  * See the <a href="http://null.ics.hawaii.edu/~corbett/birc.html"> BIRC
00064  * Release Notes</a> for information on what subset of Jimple is
00065  * currently supported by BIRC.
00066  * <p>
00067  * BIRC is invoked on an array of Soot classes as follows:
00068  * <pre>
00069  *  // Parameters
00070  *  SootClass [] staticClasses = ...; // An array of SootClass objects
00071  *  String name = ...;                // Name of system (used for filenames)
00072  *  PredicateSet preds = ...;         // Predicates to embed
00073  * 
00074  *  // Invoke BIRC to build the transition system (BIR)
00075  *  TransSystem system = Builder.createTransSystem(staticClasses, name, preds);
00076  *  // An alternate version of this call allows for setting of default resource
00077  *  // constraints in the transition system
00078  * 
00079  *  // Print the BIR
00080  *  PrintWriter writerOut = new PrintWriter(System.out, true);
00081  *  BirPrinter.print(system, writerOut);
00082  * </pre>
00083  */
00084 
00085 public class Builder implements BirConstants {
00086 
00087     /**
00088      * These are the default sizes of collections and arrays.
00089      * In the future, these should come from the front end.
00090      */
00091     public static int COLLECTION_SIZE = DefaultValues.birMaxInstances;
00092     public static int MAX_ARRAY_LENGTH = DefaultValues.birMaxArrayLen;
00093 
00094     BirThread thread;     // Current thread being built
00095     StmtGraph stmtGraph;  // Statement graph of current thread
00096     SootMethod method;    // Method whose body is current thread
00097     int mark;             // Mark value for depth-first search of Stmt graph
00098     Vector reachableStmts; // Set of reachable Stmts in Stmt graph
00099 
00100     static TransSystem system;        // Transition system being built
00101     static TypeExtractor typeExtract; // Type extractor we're using
00102     static DynamicMap dynamicMap;     // Dynamic map we're using
00103     static HashSet lockedClasses;     // Set of classes that are locked
00104     static HashSet parentClasses;     // Set of classes that all supertypes
00105 
00106     private Builder(BirThread thread, StmtGraph stmtGraph, SootMethod method) {
00107     this.thread = thread;
00108     this.stmtGraph = stmtGraph;
00109     this.method = method;
00110     }
00111     /**
00112      * Build a BIR thread from the run() method of a Jimple class.
00113      * <p>
00114      * Note: all threads have already been declared (this allows
00115      * cross references).
00116      */
00117 
00118     static void buildThread(SootClass sClass, boolean mainClass,
00119                 PredicateSet predSet) {
00120     // Retrieve thread
00121     String methodName = (mainClass) ? "main" : "run";
00122     SootMethod method = sClass.getMethod(methodName);
00123     BirThread thread = system.threadOfKey(method);
00124 
00125     // Get statement graph for method body
00126     JimpleBody body = (JimpleBody) 
00127         new StoredBody(Jimple.v()).resolveFor(method);
00128     StmtList stmtList = body.getStmtList();
00129     if (stmtList.size() == 0)
00130         return;
00131     CompleteStmtGraph cStmtGraph = new CompleteStmtGraph(stmtList);
00132     LocalDefs localDefs = new SimpleLocalDefs(cStmtGraph);
00133     LiveLocals liveLocals = new SparseLiveLocals(cStmtGraph);
00134     BriefStmtGraph stmtGraph = new BriefStmtGraph(stmtList);
00135 
00136     // Set start location and main
00137     Stmt head = (Stmt) stmtList.get(0);
00138     Location startLoc = system.locationOfKey(head, thread);
00139     thread.setStartLoc(startLoc);
00140     thread.setMain(mainClass);
00141 
00142     // Make state vars for locals
00143     Iterator localIt = body.getLocals().iterator();
00144     while (localIt.hasNext()) {
00145         Local local = (Local) localIt.next();
00146         String key = ExprExtractor.localKey(method, local);
00147         declareVar(key, local.getName(), local.getType(), thread);
00148     }
00149     
00150     // Collect reachable statements by walking stmtGraph
00151     Builder builder = new Builder(thread, stmtGraph, method);
00152     Vector reachableStmts = builder.reachableFrom(head);
00153 
00154     // Extract BIR from each reachable statement
00155     TransExtractor extractor = 
00156         new TransExtractor(system, thread, stmtGraph, localDefs, 
00157                    liveLocals, method, typeExtract, predSet);
00158     for (int i = 0; i < reachableStmts.size(); i++) 
00159         ((Stmt)reachableStmts.elementAt(i)).apply(extractor);
00160     }
00161     /**
00162      * Check for statics on the left and right side of a definition Stmt.
00163      * If found, and the class of the static has not already been processed,
00164      * declare a new BIR global variable for the static fields of the class.
00165      */
00166 
00167     static void checkForStatics(DefinitionStmt defStmt, Hashtable done) {
00168     if (defStmt.getRightOp() instanceof StaticFieldRef) {
00169         StaticFieldRef fieldRef = (StaticFieldRef)defStmt.getRightOp();
00170         SootClass sClass = fieldRef.getField().getDeclaringClass();
00171         if (done.get(sClass) == null) {
00172         declareClassGlobals(sClass);
00173         done.put(sClass,sClass);
00174         }
00175     }
00176     if (defStmt.getLeftOp() instanceof StaticFieldRef) {
00177         StaticFieldRef fieldRef = (StaticFieldRef)defStmt.getLeftOp();
00178         SootClass sClass = fieldRef.getField().getDeclaringClass();
00179         if (done.get(sClass) == null) {
00180         declareClassGlobals(sClass);
00181         done.put(sClass,sClass);
00182         }
00183     }
00184     }
00185     /**
00186      * Given the dynamic map, create a collection for each collection key
00187      * that was declared in the map.  The size of a collection is the
00188      * sum of the sizes of all map entries stored in that collection.
00189      */
00190 
00191     static void createCollections() {
00192     // For each collection key K of class C, 
00193     // create K_col = collection [N] of C, where N is the sum
00194     // of the sizes of all allocators with key K.
00195     // Also, add K_col to C_ref.  
00196     Vector keys = dynamicMap.getCollections();
00197     for (int i = 0; i < keys.size(); i++) {
00198         String name;
00199         edu.ksu.cis.bandera.bir.Type elementType;
00200         edu.ksu.cis.bandera.bir.Type collectType;
00201 
00202         // First, create the collection type and variable
00203         Object key = keys.elementAt(i);
00204         int size = dynamicMap.getCollectionSize(key);
00205         SootClass sootClass = dynamicMap.getCollectionClass(key);
00206         ArrayType arrayType = dynamicMap.getCollectionArray(key);
00207         // key is either class collection or array collection
00208         if (sootClass != null) {
00209         elementType = typeExtract.getRecordType(sootClass);
00210         name = sootClass.getName();
00211         } else {
00212         elementType = typeExtract.getArrayType(arrayType);
00213         name = typeExtract.arrayName(arrayType);
00214         }
00215         collectType = typeExtract.createCollectionType(elementType,size);
00216         StateVar col = 
00217         system.declareVar(key,name + "_col",null,collectType,null);
00218 
00219         // Now add the collection to the ref types that could refer to it
00220         if (sootClass != null) {
00221         // A class collection can be referenced by the ref type
00222         // for that class, all superclasses, and any 
00223         // implemented interfaces
00224         typeExtract.getRefType(sootClass).addTarget(col, sootClass, typeExtract);
00225         Vector superClasses = typeExtract.getSuperClasses(sootClass);
00226         for (int j = 0; j < superClasses.size(); j++) {
00227             SootClass supClass = (SootClass) superClasses.elementAt(j);
00228             typeExtract.getRefType(supClass).addTarget(col, sootClass, typeExtract);
00229         }
00230         Vector intClasses = typeExtract.getInterfaceClasses(sootClass);
00231         for (int j = 0; j < intClasses.size(); j++) {
00232             SootClass intClass = (SootClass) intClasses.elementAt(j);
00233             typeExtract.getRefType(intClass).addTarget(col, sootClass, typeExtract);
00234         }
00235         } else
00236         // An array collection can be referenced only by the
00237         // ref type of the array
00238         typeExtract.getRefType(arrayType).addTarget(col);
00239     }   
00240     }
00241     /**
00242      * For each Jimple class and array type, create a corresponding
00243      * BIR record/array type using the type extractor.
00244      */
00245 
00246     static void createRecordAndArrayTypes() {
00247     // Record the supertypes of dynamically allocated classes
00248     // also determine which of those are locked
00249     Vector sootClasses = dynamicMap.getClasses();
00250     for (int i = 0; i < sootClasses.size(); i++) {
00251         SootClass sootClass = (SootClass) sootClasses.elementAt(i);
00252             SootClass ancestor = sootClass;
00253             while (ancestor.hasSuperClass()) {
00254               ancestor = ancestor.getSuperClass();
00255               if (lockedClasses.contains(ancestor)) 
00256          lockedClasses.add(sootClass);
00257         }
00258         }
00259 
00260     // For each class C, create C_rec = record { ... }
00261     // 
00262     // There are two cases:
00263     //   1) the dynamically allocated classes which should be
00264     //      created with an indication of wether instances may be locked
00265     //   2) the unallocated classes that are locked, i.e., that
00266     //      may be supertypes of dynamically allocated classes
00267     //
00268        
00269     // First handle all the dynamically allocated classes
00270     sootClasses = dynamicMap.getClasses();
00271     for (int i = 0; i < sootClasses.size(); i++) {
00272         SootClass sootClass = (SootClass) sootClasses.elementAt(i);
00273         typeExtract.createRecordType(sootClass, 
00274                      lockedClasses.contains(sootClass));
00275     }
00276 
00277     // Second handle all the unallocated locked classes
00278     for (Iterator pIt = parentClasses.iterator(); pIt.hasNext(); ) {
00279         SootClass sootClass = (SootClass) pIt.next();
00280         typeExtract.createRecordType(sootClass, 
00281                      lockedClasses.contains(sootClass));
00282     }
00283 
00284     // For each array type T, create T_arr = array [K] of T
00285     Vector arrayTypes = dynamicMap.getArrays();
00286     for (int i = 0; i < arrayTypes.size(); i++) {
00287         ArrayType arrayType = (ArrayType) arrayTypes.elementAt(i);
00288         typeExtract.createArrayType(arrayType,MAX_ARRAY_LENGTH);
00289     }
00290     }
00291     /**
00292      * Once the dynamic map has been constructed, create a reference
00293      * type for each class, array type, and interface.  These types
00294      * will be used to represent the Java reference types of the Jimple.
00295      * <p>
00296      * Note that, at this point, we have not yet created the collections,
00297      * the the reference types are unresolved.
00298      */
00299 
00300     static void createRefTypes() {
00301     // For each class C, create C_ref = ref {} (unresolved)
00302     Vector sootClasses = dynamicMap.getClasses();
00303     for (int i = 0; i < sootClasses.size(); i++) {
00304         SootClass sootClass = (SootClass) sootClasses.elementAt(i);
00305         typeExtract.createRefType(sootClass);
00306     }
00307 
00308     // For each parent of an allocated class create a ref
00309         for (Iterator pIt = parentClasses.iterator(); pIt.hasNext(); ) {
00310             SootClass sootClass = (SootClass) pIt.next();
00311             typeExtract.createRefType(sootClass);
00312         }
00313 
00314     // For each array type T, create T_ref = ref {} (unresolved)
00315     Vector arrayTypes = dynamicMap.getArrays();
00316     for (int i = 0; i < arrayTypes.size(); i++) {
00317         ArrayType arrayType = (ArrayType) arrayTypes.elementAt(i);
00318         typeExtract.createRefType(arrayType);
00319     }
00320     // For each interface I, create I_ref = ref {} (unresolved)
00321     Vector interfaces = dynamicMap.getInterfaces();
00322     for (int i = 0; i < interfaces.size(); i++) {
00323         SootClass sootClass = (SootClass) interfaces.elementAt(i);
00324         typeExtract.createRefType(sootClass);
00325     }
00326     }
00327     /**
00328      * Creates a transition system from a set of Soot classes.
00329      *
00330      * @param sootClasses an array of SootClass objects containing
00331      *  methods that represent the code executed by threads.
00332      *  The first class must have a static method <tt>main()</tt>
00333      *  and the remaining classes must each have a static method
00334      *  <tt>run()</tt>.
00335      * @param name name of transition system (used to generate filenames)
00336      * @param predSet set of predicates to embed (can be null)
00337      * @param maxArrayLength maximum length of an array
00338      * @param maxCollectSize maximum size of a heap collection
00339      * @param minInt minimum value for integer
00340      * @param maxInt maximum value for integer
00341      * @return a transition system representing the Soot classes
00342      */
00343 
00344     public static TransSystem createTransSystem(SootClass [] sootClasses,
00345                         String name, 
00346                         int maxArrayLength, 
00347                         int maxCollectSize, 
00348                         int minInt, 
00349                         int maxInt, 
00350                         PredicateSet predSet) {
00351     MAX_ARRAY_LENGTH = maxArrayLength;
00352     COLLECTION_SIZE = maxCollectSize;
00353     edu.ksu.cis.bandera.bir.Type.defaultRangeType = new edu.ksu.cis.bandera.bir.Range(minInt, maxInt);
00354         return createTransSystem(sootClasses, name, predSet);
00355     }
00356     /**
00357      * Creates a transition system from a set of Soot classes.
00358      *
00359      * @param threadClasses an array of SootClass objects containing
00360      *  methods that represent the code executed by threads.
00361      *  The first class must have a static method <tt>main()</tt>
00362      *  and the remaining classes must each have a method
00363      *  <tt>run()</tt>.
00364      * @param allClasses an array of SootClass objects referenced
00365      * @param name name of transition system (used to generate filenames)
00366      * @param predSet set of predicates to embed (can be null)
00367      * @return a transition system representing the Soot classes
00368      */
00369 
00370     public static TransSystem createTransSystem(SootClass [] sootClasses,
00371                         String name, 
00372                         PredicateSet predSet) {
00373     if (predSet == null)
00374         predSet = new PredicateSet();   // Create empty set so non-null
00375     system = new TransSystem(name);
00376     typeExtract = new TypeExtractor(system, sootClasses[0].getManager());
00377 
00378     // Declare classes, threads, and global variables
00379     declareClasses(sootClasses);
00380     for (int i = 0; i < sootClasses.length; i++) 
00381         declareThread(sootClasses[i], (i == 0));
00382     declareGlobals(sootClasses);
00383 
00384     // Build all threads
00385     for (int i = 0; i < sootClasses.length; i++) 
00386         buildThread(sootClasses[i], (i == 0), predSet);
00387 
00388     // Reduce the transition system and number the locations
00389     (new Reducer(system)).run();
00390     system.numberLocations();
00391 
00392     // Declare the predicates
00393     declarePredicates(predSet);
00394     return system;
00395     }
00396     static void declareClasses(SootClass [] sootClasses) {
00397     identifyAllocatorsLocks(sootClasses);
00398     createRefTypes();
00399     createRecordAndArrayTypes();
00400     createCollections();
00401     }
00402     /**
00403      * Declare a BIR variable for each static field of a class.
00404      * <p>
00405      * Note: we ignore the built-in classes in any subpackage of java.*
00406      */
00407 
00408 
00409     static void declareClassGlobals(SootClass sClass) {
00410     // Ignore built-in classes
00411     if (sClass.getName().startsWith("java."))
00412         return;
00413 
00414     // Declare state variable for each static field
00415     Iterator fieldIt = sClass.getFields().iterator();        
00416     while(fieldIt.hasNext()) {
00417         SootField field = (SootField) fieldIt.next();
00418         if (Modifier.isStatic(field.getModifiers())) 
00419         declareVar(field, field.getName(), field.getType(), null);
00420     }
00421 
00422     // Scan the <clinit> method for initializations to static fields
00423     if (sClass.declaresMethod("<clinit>")) {
00424         SootMethod method = sClass.getMethod("<clinit>");
00425         JimpleBody body = (JimpleBody) 
00426         new StoredBody(Jimple.v()).resolveFor(method);
00427         StmtList stmtList = body.getStmtList();
00428         for (int i = 0; i < stmtList.size(); i++) {
00429         if (stmtList.get(i) instanceof AssignStmt) {
00430             AssignStmt stmt = (AssignStmt) stmtList.get(i);
00431             if (stmt.getLeftOp() instanceof StaticFieldRef) {
00432             StaticFieldRef lhs = (StaticFieldRef)stmt.getLeftOp();
00433             if (lhs.getType() instanceof RefType)
00434                 warn("ignoring initialization of " + lhs);
00435             else
00436                 initializeGlobal(lhs, stmt.getRightOp());
00437             }
00438         }
00439         }
00440     }
00441     }
00442     /**
00443      * Declare global BIR variables for all Jimple static variables
00444      * referenced in the body of some thread.
00445      * <p>
00446      * Also declare a 'this' variable for each thread except the main
00447      * thread to hold the reference to the Runnable or Thread object 
00448      * that owns the thread's run() method.
00449      */
00450 
00451     static void declareGlobals(SootClass [] sootClasses) {
00452     Hashtable done = new Hashtable();  // Classes we've already processed
00453     for (int i = 0; i < sootClasses.length; i++) {
00454         SootClass sClass = sootClasses[i];
00455         List methods = sootClasses[i].getMethods();
00456         Iterator methodIt = methods.iterator();
00457         while (methodIt.hasNext()) {
00458         SootMethod method = (SootMethod) methodIt.next();
00459         JimpleBody body = (JimpleBody) 
00460             new StoredBody(Jimple.v()).resolveFor(method);
00461         StmtList stmtList = body.getStmtList();
00462         for (int j = 0; j < stmtList.size(); j++) {
00463             Stmt stmt = (Stmt) stmtList.get(j);
00464             if (stmt instanceof DefinitionStmt) 
00465             checkForStatics((DefinitionStmt)stmt,done);
00466         }
00467         }
00468         if (i > 0) {  // Declare 'this' variable (except for main thread)
00469         String name = sClass.getName() + "__this";
00470         Type type = RefType.v(sClass.getName());
00471         StateVar var = declareVar(sClass,name,type,null);
00472         var.setConstant(true);
00473         }
00474     }
00475     }
00476     /**
00477      * For each predicate declared, use an expression extractor 
00478      * to translate the Jimple Expr for the predicate into a BIR Expr,
00479      * then declare that as the BIR predciate.
00480      */
00481 
00482     static void declarePredicates(PredicateSet predSet) {
00483     Vector valPreds = predSet.getValuePredicates();
00484     for (int i = 0; i < valPreds.size(); i++) {
00485         Expr valPred = (Expr) valPreds.elementAt(i);
00486         ExprExtractor extractor = 
00487         new ExprExtractor(system,null,null,null,typeExtract,predSet);
00488         valPred.apply(extractor);
00489         edu.ksu.cis.bandera.bir.Expr predExpr = 
00490         (edu.ksu.cis.bandera.bir.Expr) extractor.getResult();
00491         system.declarePredicate(predSet.predicateName(valPred),predExpr);
00492     }
00493     }
00494     static void declareThread(SootClass sClass, boolean mainClass) {
00495     // Create thread for run() or main() method
00496     String methodName = (mainClass) ? "main" : "run";
00497     SootMethod method = sClass.getMethod(methodName);
00498     system.createThread(sClass.getName(), method);
00499     }
00500     /**
00501      * Declare a BIR variable in the transition system.
00502      * <p>
00503      * The type extractor is used to convert the SootType into a BIR type.
00504      * If the SootType is not representable (type extractor returns null),
00505      * then we ignore this variable (with a warning).
00506      */
00507 
00508     static StateVar declareVar(Object key, String name, Type sootType, 
00509                BirThread thread) {
00510     sootType.apply(typeExtract);
00511     edu.ksu.cis.bandera.bir.Type type = 
00512         (edu.ksu.cis.bandera.bir.Type) typeExtract.getResult();
00513     if (type == null) {
00514         warn("ignoring object of type " + sootType);
00515         return null;
00516     }
00517     // if ((thread == null) || type.isKind(RANGE | BOOL | ENUMERATED))
00518     return system.declareVar(key, name, thread, type, null);
00519     }
00520     void findReachableFrom(Stmt stmt) {
00521     Location loc = system.locationOfKey(stmt, thread);
00522     if (loc.getMark() != mark) {
00523         loc.setMark(mark);
00524         Iterator stmtIt = stmtGraph.getSuccsOf(stmt).iterator();
00525         // Don't include the 'return' statement at the end
00526         if (stmtIt.hasNext())
00527         reachableStmts.addElement(stmt);
00528         while (stmtIt.hasNext()) {
00529         Stmt nextStmt = (Stmt) stmtIt.next();
00530         findReachableFrom(nextStmt);
00531         }
00532     }
00533     }
00534     /**
00535      * Heap objects are stored in BIR collections, which must be declared.
00536      * We build a "dynamic map" that defines, for each allocator site
00537      * (NewExpr or NewArrayExpr), which collection will hold the elements 
00538      * of that site.
00539      * <p>
00540      * Currently, we simply create a collection for each allocator site.
00541      * <p>
00542      * This method accepts the soot classes that define the bodies of the
00543      * threads, and it looks for allocator expressions in the code for
00544      * these threads, defining a dynamic map entry for each.
00545      * <p>
00546      * In addition this code determines the set of types that are
00547      * explicitly locked in statements that are reachable from the
00548      * threads.  These will be used to determine which classes need
00549      * to have locks allocated in the model.
00550      */
00551 
00552     static void identifyAllocatorsLocks(SootClass [] sootClasses) {
00553     dynamicMap = new DynamicMap(sootClasses[0].getManager());
00554     lockedClasses = new HashSet();  
00555     HashSet dynamicClasses = new HashSet();
00556     // Look through all Stmts of all methods of all classes
00557     for (int i = 0; i < sootClasses.length; i++) {
00558         List methods = sootClasses[i].getMethods();
00559         Iterator methodIt = methods.iterator();
00560         while (methodIt.hasNext()) {
00561         SootMethod method = (SootMethod) methodIt.next();
00562         JimpleBody body = (JimpleBody) 
00563             new StoredBody(Jimple.v()).resolveFor(method);
00564         StmtList stmtList = body.getStmtList();
00565         for (int j = 0; j < stmtList.size(); j++) {
00566             Stmt stmt = (Stmt) stmtList.get(j);
00567             // Look for Definition statements with a NewExpr on the RHS
00568             if (stmt instanceof DefinitionStmt) {
00569             DefinitionStmt defStmt = (DefinitionStmt)stmt;
00570             if (defStmt.getRightOp() instanceof NewExpr) {
00571                 NewExpr newExpr = (NewExpr) defStmt.getRightOp();
00572                 // Filter out exception classes
00573                         SootClass newClass = sootClasses[0].getManager().getClass(newExpr.getBaseType().className);
00574 
00575                 boolean throwableClass = false;
00576                         SootClass ancestor = newClass;
00577                             while (ancestor.hasSuperClass()) {
00578                               ancestor = ancestor.getSuperClass();
00579                           if (ancestor.getName().equals("java.lang.Throwable")) {
00580                      throwableClass = true;
00581                   }
00582                 }
00583                 if (!throwableClass) {
00584                    dynamicMap.addEntry(newExpr, newExpr, 
00585                         COLLECTION_SIZE);
00586                            dynamicClasses.add(sootClasses[0].getManager().getClass(newExpr.getBaseType().className));
00587                 }
00588             }
00589             if (defStmt.getRightOp() instanceof NewArrayExpr) {
00590                 NewArrayExpr newExpr = 
00591                 (NewArrayExpr) defStmt.getRightOp();
00592                 dynamicMap.addEntry(newExpr, newExpr, 
00593                         COLLECTION_SIZE,
00594                         MAX_ARRAY_LENGTH);
00595             }           
00596             if (defStmt.getRightOp() instanceof NewMultiArrayExpr) 
00597                 warn("multi-dimensional arrays not supported");
00598             }
00599 
00600             // Look for enter monitor statements and record type of arg
00601                 if (stmt instanceof EnterMonitorStmt) {
00602                     EnterMonitorStmt enterStmt = (EnterMonitorStmt)stmt;
00603                         Type type = enterStmt.getOp().getType();
00604                         if (type instanceof RefType) {  
00605                           lockedClasses.add(sootClasses[0].getManager().getClass(((RefType)type).className));
00606                         }
00607                 }
00608         }       
00609         }
00610     }
00611     parentClasses = new HashSet();
00612     for (Iterator dcIt = dynamicClasses.iterator(); dcIt.hasNext(); ) {
00613         SootClass sootClass = (SootClass) dcIt.next();
00614         // Build the Ancestor map for use in resolving reference typing
00615         HierarchyQuery.buildAncestors(sootClass);
00616 
00617         // Generate the parents
00618             SootClass ancestor = sootClass;
00619             while (ancestor.hasSuperClass()) {
00620               ancestor = ancestor.getSuperClass();
00621           if (!dynamicClasses.contains(ancestor)) {
00622          parentClasses.add(ancestor);
00623              HierarchyQuery.buildAncestors(ancestor);
00624           }
00625         }
00626         }
00627     dynamicMap.print();
00628     }
00629     /**
00630      * Set initial value of static field.
00631      * <p>
00632      * Currently, this only works if the assigned value is static.
00633      */
00634 
00635 
00636     static void initializeGlobal(StaticFieldRef lhs, Value rhs) {
00637     StateVar var = system.getVarOfKey(lhs.getField());
00638     ExprExtractor extractor = new ExprExtractor(system, null, null, null,
00639                             typeExtract, 
00640                             new PredicateSet());
00641     rhs.apply(extractor);
00642     if (extractor.getResult() != null)
00643         var.setInitVal((edu.ksu.cis.bandera.bir.Expr)
00644                extractor.getResult());
00645     }
00646     /**
00647      * Interpret a BIR trace in terms of the Jimple code from which
00648      * it was created.
00649      * 
00650      * @param trace - a BIR trace of a transition system created by BIRC
00651      * @return the corresponding Jimple trace 
00652      */
00653     public static JimpleTrace interpretTrace(BirTrace trace) {
00654     return new JimpleTrace(trace);
00655     }
00656     /**
00657      * Do a depth first search of the statement graph and return
00658      * a vector of all statements reachable from a given statement.
00659      * <p>
00660      * We do this to eliminate exception handlers, which are not
00661      * reachable in the BriefStmtGraph (the CompleteStmtGraph
00662      * contains arcs representing possible exception raising,
00663      * so the exception handlers are reachable in that graph).
00664      */
00665 
00666 
00667     Vector reachableFrom(Stmt stmt) {
00668     reachableStmts = new Vector();
00669     mark = Location.getNewMark();
00670     findReachableFrom(stmt);
00671     return reachableStmts;
00672     }
00673     static void warn(String s) {
00674     System.out.println("Warning: " + s);
00675     }
00676 }

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