1 vivien   1.1.2.1 // ODPointerAnalysis.java, created Sat Jan  8 23:22:24 2000 by salcianu
   2 cananian 1.1.2.3 // Copyright (C) 2000 Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
   3 vivien   1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
   4 vivien   1.1.2.1 package harpoon.Analysis.PointerAnalysis;
   5 vivien   1.1.2.1 
   6 vivien   1.1.2.1 import java.util.HashMap;
   7 vivien   1.1.2.1 import java.util.Map;
   8 vivien   1.1.2.1 import java.util.Iterator;
   9 vivien   1.1.2.1 import java.util.Enumeration;
  10 vivien   1.1.2.1 import java.util.Set;
  11 vivien   1.1.2.1 import java.util.HashSet;
  12 vivien   1.1.2.1 import java.util.Date;
  13 vivien   1.1.2.1 import java.util.Collections;
  14 vivien   1.1.2.1 import java.util.Arrays;
  15 vivien   1.1.2.1 import java.util.Comparator;
  16 vivien   1.1.2.1 
  17 vivien   1.1.2.1 import java.lang.reflect.Modifier;
  18 vivien   1.1.2.1 
  19 vivien   1.1.2.1 import harpoon.ClassFile.HCodeFactory;
  20 vivien   1.1.2.1 import harpoon.ClassFile.HCodeElement;
  21 vivien   1.1.2.1 import harpoon.ClassFile.HClass;
  22 vivien   1.1.2.1 import harpoon.ClassFile.HMethod;
  23 vivien   1.1.2.1 import harpoon.ClassFile.HField;
  24 vivien   1.1.2.1 import harpoon.ClassFile.HCode;
  25 vivien   1.1.2.1 import harpoon.ClassFile.Linker;
  26 vivien   1.1.2.1 import harpoon.ClassFile.Loader;
  27 vivien   1.1.2.1 
  28 vivien   1.1.2.1 import harpoon.Analysis.Quads.CallGraph;
  29 vivien   1.1.2.1 import harpoon.Analysis.AllCallers;
  30 vivien   1.1.2.1 import harpoon.Analysis.ClassHierarchy;
  31 vivien   1.1.2.1 import harpoon.Util.LightBasicBlocks.LightBasicBlock;
  32 vivien   1.1.2.1 
  33 vivien   1.1.2.1 import harpoon.Temp.Temp;
  34 vivien   1.1.2.1 
  35 vivien   1.1.2.1 import harpoon.IR.Quads.Quad;
  36 vivien   1.1.2.1 import harpoon.IR.Quads.QuadKind;
  37 vivien   1.1.2.1 import harpoon.IR.Quads.QuadVisitor;
  38 vivien   1.1.2.1 import harpoon.IR.Quads.HEADER;
  39 vivien   1.1.2.1 import harpoon.IR.Quads.METHOD;
  40 vivien   1.1.2.1 import harpoon.IR.Quads.AGET;
  41 vivien   1.1.2.1 import harpoon.IR.Quads.ALENGTH;
  42 vivien   1.1.2.1 import harpoon.IR.Quads.ANEW;
  43 vivien   1.1.2.1 import harpoon.IR.Quads.ASET;
  44 vivien   1.1.2.1 import harpoon.IR.Quads.GET;
  45 vivien   1.1.2.1 import harpoon.IR.Quads.MOVE;
  46 vivien   1.1.2.1 import harpoon.IR.Quads.NEW;
  47 vivien   1.1.2.1 import harpoon.IR.Quads.RETURN;
  48 vivien   1.1.2.1 import harpoon.IR.Quads.THROW;
  49 vivien   1.1.2.1 import harpoon.IR.Quads.SET;
  50 vivien   1.1.2.1 import harpoon.IR.Quads.CALL;
  51 vivien   1.1.2.1 import harpoon.IR.Quads.MONITORENTER;
  52 vivien   1.1.2.1 import harpoon.IR.Quads.MONITOREXIT;
  53 vivien   1.1.2.1 import harpoon.IR.Quads.FOOTER;
  54 vivien   1.1.2.1 import harpoon.IR.Quads.TYPECAST;
  55 vivien   1.1.2.1 
  56 vivien   1.1.2.1 import harpoon.Analysis.MetaMethods.MetaMethod;
  57 vivien   1.1.2.1 import harpoon.Analysis.MetaMethods.MetaCallGraph;
  58 vivien   1.1.2.1 import harpoon.Analysis.MetaMethods.MetaAllCallers;
  59 vivien   1.1.2.1 import harpoon.Analysis.MetaMethods.GenType;
  60 vivien   1.1.2.1 
  61 vivien   1.1.2.1 import harpoon.Util.TypeInference.CachingArrayInfo;
  62 vivien   1.1.2.1 
  63 vivien   1.1.2.1 import harpoon.Util.LightBasicBlocks.LBBConverter;
  64 vivien   1.1.2.1 import harpoon.Util.LightBasicBlocks.CachingSCCLBBFactory;
  65 vivien   1.1.2.1 import harpoon.Util.Graphs.SCComponent;
  66 salcianu 1.5     import harpoon.Util.Graphs.Navigator;
  67 salcianu 1.8     import harpoon.Util.Graphs.TopSortedCompDiGraph;
  68 vivien   1.1.2.1 import harpoon.Util.UComp;
  69 vivien   1.1.2.1 
  70 vivien   1.1.2.1 import harpoon.Util.Util;
  71 vivien   1.1.2.1 
  72 vivien   1.1.2.1 import harpoon.Util.DataStructs.Relation;
  73 vivien   1.1.2.1 import harpoon.Util.DataStructs.LightRelation;
  74 vivien   1.1.2.1 import harpoon.Util.DataStructs.LightMap;
  75 vivien   1.1.2.1 
  76 vivien   1.1.2.1 
  77 vivien   1.1.2.1 
  78 vivien   1.1.2.1 
  79 vivien   1.1.2.1 /**
  80 vivien   1.1.2.1  * <code>ODPointerAnalysis</code> is the main class of the Pointer Analysis
  81 vivien   1.1.2.1  package. It is designed to act as a <i>query-object</i>: after being
  82 vivien   1.1.2.1  initialized, it can be asked to provide the Parallel Interaction Graph
  83 vivien   1.1.2.1  valid at the end of a specific method.
  84 vivien   1.1.2.1  * 
  85 cananian 1.1.2.3  * @author  Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
  86 salcianu 1.11     * @version $Id: ODPointerAnalysis.java,v 1.11 2004/03/06 21:52:24 salcianu Exp $
  87 vivien   1.1.2.1  */
  88 vivien   1.1.2.1 public class ODPointerAnalysis {
  89 vivien   1.1.2.1     public static final boolean DEBUG     = false;
  90 vivien   1.1.2.1     public static final boolean DEBUG2    = false;
  91 vivien   1.1.2.1     public static final boolean DEBUG_SCC = false;
  92 vivien   1.1.2.1 
  93 vivien   1.1.2.1     /** Turns on the save memory mode. In this mode, some of the speed is
  94 vivien   1.1.2.1         sacrified for the sake of the memory consumption. More specifically,
  95 vivien   1.1.2.1         the <i>Interior</i>, large version of the Parallel Interaction Graph
  96 vivien   1.1.2.1         at the end of a method is no longer cached. */
  97 vivien   1.1.2.1     public static final boolean SAVE_MEMORY = false;
  98 vivien   1.1.2.1 
  99 vivien   1.1.2.1     /** Makes the pointer analysis deterministic to make the debug easier.
 100 vivien   1.1.2.1         The main source of undeterminism in our code is the intensive use of
 101 vivien   1.1.2.1         <code>Set</code>s which doesn't offer any guarantee about the order
 102 vivien   1.1.2.1         in which they iterate over their elements. */
 103 vivien   1.1.2.1     public static final boolean DETERMINISTIC = true;
 104 vivien   1.1.2.1 
 105 vivien   1.1.2.1     /** Turns on the priniting of some timing info. */
 106 vivien   1.1.2.1     public static boolean TIMING = true;
 107 vivien   1.1.2.1     public static final boolean STATS = true;
 108 vivien   1.1.2.1     public static boolean SHOW_NODES = true;
 109 vivien   1.1.2.1     public static final boolean DETAILS2 = false;
 110 vivien   1.1.2.1 
 111 vivien   1.1.2.1 
 112 vivien   1.1.2.1     /** Hack to speed it up: it appears to me that the edge ordering
 113 vivien   1.1.2.1         relation is not extremely important: in recursive methods or in
 114 vivien   1.1.2.1         methods with loops, it tends to be just a cartesian product between
 115 vivien   1.1.2.1         I and O. */
 116 vivien   1.1.2.1     public static final boolean IGNORE_EO = true;
 117 vivien   1.1.2.1 
 118 vivien   1.1.2.1     /** Controls the recording of data about the thread nodes that are
 119 vivien   1.1.2.1         touched after being started. */
 120 vivien   1.1.2.1     public static final boolean TOUCHED_THREAD_SUPPORT= false;
 121 vivien   1.1.2.1 
 122 vivien   1.1.2.1     // TODO: Most of the following flags should be final (which will
 123 vivien   1.1.2.1     // help somehow the compiler to perform some dead code elimination
 124 vivien   1.1.2.1     // etc. and maybe gain some speed). For the moment, they are non-final
 125 vivien   1.1.2.1     // so that the main modeule can modify them (according to the command
 126 vivien   1.1.2.1     // line options).
 127 vivien   1.1.2.1 
 128 vivien   1.1.2.1     /** Activates the calling context sensitivity. When this flag is
 129 vivien   1.1.2.1         on, the nodes from the graph of the callee are specialized for each
 130 vivien   1.1.2.1         call site (up to <code>MAX_SPEC_DEPTH</code> times). This increases
 131 vivien   1.1.2.1         the precision of the analysis but requires more time and memory. */
 132 vivien   1.1.2.1     public static boolean CALL_CONTEXT_SENSITIVE = false;
 133 vivien   1.1.2.1 
 134 vivien   1.1.2.1     /** The specialization limit. This puts a limit to the otherwise
 135 vivien   1.1.2.1         exponential growth of the number of nodes in the analysis. */
 136 vivien   1.1.2.1     public static int MAX_SPEC_DEPTH = 1;
 137 vivien   1.1.2.1 
 138 vivien   1.1.2.1     /** Activates the full thread sensitivity. When this flag is on, 
 139 vivien   1.1.2.1         the analysis makes the distinction not only between the nodes
 140 vivien   1.1.2.1         allocated by the current thread and those allocated by all the
 141 vivien   1.1.2.1         others but also between the nodes allocated by threads with
 142 vivien   1.1.2.1         different run methods (for the time being, we cannot make the
 143 vivien   1.1.2.1         distinction between two threads with the same thread node). */
 144 vivien   1.1.2.1     public static boolean THREAD_SENSITIVE = false;
 145 vivien   1.1.2.1 
 146 vivien   1.1.2.1     /** Activates the weak thread sensitivity. When this flag is
 147 vivien   1.1.2.1         on, the precision of the interthread analysis is increased:
 148 vivien   1.1.2.1         the nodes from the graph of the run method of the thread whose
 149 vivien   1.1.2.1         interactions with the current thread are analyzed are specialized
 150 vivien   1.1.2.1         to differenciate between the nodes created by that thread and
 151 vivien   1.1.2.1         the nodes created by the current one. This increases
 152 vivien   1.1.2.1         the precision of the analysis but requires more time and memory. */
 153 vivien   1.1.2.1     public static boolean WEAKLY_THREAD_SENSITIVE = false;
 154 vivien   1.1.2.1 
 155 vivien   1.1.2.1     /** Activates the loop sensitivity. When this flag is on, the precision
 156 vivien   1.1.2.1         of the intra-method analysis is increased by making the difference
 157 vivien   1.1.2.1         between the last object allocated at a specific object creation
 158 vivien   1.1.2.1         site inside a loop and the objects allocated at the same object
 159 vivien   1.1.2.1         creation site but in the previous iterations. This enambles
 160 vivien   1.1.2.1         some strong optimizations but requires more time and memory. */
 161 vivien   1.1.2.1     public static boolean LOOP_SENSITIVE = false;
 162 vivien   1.1.2.1 
 163 vivien   1.1.2.1     /** Array elements are modeled as fields of the array object, all of them
 164 vivien   1.1.2.1         with the same name since the analysis is not able to make the
 165 vivien   1.1.2.1         distinction between the fields. 
 166 vivien   1.1.2.1         this name is supposed to be "as impossible as possible", so that we
 167 vivien   1.1.2.1         don't have any conflict with real fields. */
 168 vivien   1.1.2.1     public static final String ARRAY_CONTENT = "+ae+";
 169 vivien   1.1.2.1 
 170 vivien   1.1.2.1     // FV
 171 vivien   1.1.2.1     public static boolean BOUNDED_ANALYSIS_DEPTH = false;
 172 vivien   1.1.2.1     public static boolean ON_DEMAND_ANALYSIS = false;
 173 vivien   1.1.2.1     public static boolean ODA_precise = false;
 174 vivien   1.1.2.1     public static boolean NODES_DRIVEN = false;
 175 vivien   1.1.2.1     public static boolean FIRST_ANALYSIS = false;
 176 vivien   1.1.2.1     public static int     MAX_ANALYSIS_DEPTH = 0;
 177 vivien   1.1.2.1     public static int     MAX_ANALYSIS_ABOVE_SPEC = 0;
 178 vivien   1.1.2.1     public static int     current_analysis_depth = 0;
 179 vivien   1.1.2.1     public static int     number_of_mapups = 0;
 180 vivien   1.1.2.1     public static int     number_of_mm_analyzed = 0;
 181 vivien   1.1.2.1 
 182 vivien   1.1.2.1     public static Map Quad2Node = new LightMap();
 183 vivien   1.1.2.1 
 184 vivien   1.1.2.1     public static boolean MartinTheWildHacker=false;
 185 vivien   1.1.2.1 
 186 vivien   1.1.2.1     public static HashMap [] hash_proc_int_d = null; 
 187 vivien   1.1.2.1     public static HashMap [] hash_proc_ext_d = null; 
 188 vivien   1.1.2.1 
 189 vivien   1.1.2.1     public static Set interestingQuads = null;
 190 vivien   1.1.2.1     public static Set interestingNodes = null;
 191 vivien   1.1.2.1     public static Relation Quad2Nodes  = null;
 192 vivien   1.1.2.1 
 193 vivien   1.1.2.1     // The HCodeFactory providing the actual code of the analyzed methods
 194 vivien   1.1.2.1     private final MetaCallGraph  mcg;
 195 vivien   1.1.2.1     public final MetaCallGraph getMetaCallGraph() { return mcg; }
 196 vivien   1.1.2.1     private final MetaAllCallers mac;
 197 vivien   1.1.2.1     public final MetaAllCallers getMetaAllCallers() { return mac; }
 198 vivien   1.1.2.1     public final CachingSCCLBBFactory scc_lbb_factory;
 199 vivien   1.1.2.1 
 200 vivien   1.1.2.1     private Map hash_proc_interact_int = new HashMap();
 201 vivien   1.1.2.1 
 202 vivien   1.1.2.1     private Map hash_proc_interact_ext = new HashMap();
 203 vivien   1.1.2.1 
 204 vivien   1.1.2.1 
 205 vivien   1.1.2.1 
 206 vivien   1.1.2.1     // Maintains the partial points-to and escape information for the
 207 vivien   1.1.2.1     // analyzed methods. This info is successively refined by the fixed
 208 vivien   1.1.2.1     // point algorithm until no further change is possible
 209 vivien   1.1.2.1     // mapping MetaMethod -> ODParIntGraph.
 210 vivien   1.1.2.1     private Map hash_proc_int = new HashMap();
 211 vivien   1.1.2.1 
 212 vivien   1.1.2.1     // Maintains the external view of the parallel interaction graphs
 213 vivien   1.1.2.1     // attached with the analyzed methods. These "bricks" are used
 214 vivien   1.1.2.1     // for the processing of the CALL nodes.
 215 vivien   1.1.2.1     // Mapping MetaMethod -> ODParIntGraph.
 216 vivien   1.1.2.1     private Map hash_proc_ext = new HashMap();
 217 vivien   1.1.2.1 
 218 vivien   1.1.2.1 
 219 vivien   1.1.2.1     // Maintains the method holes information needed for a later
 220 vivien   1.1.2.1     // precision enhancement.
 221 vivien   1.1.2.1     // mapping MetaMethod -> HashSet of MethodHole.
 222 vivien   1.1.2.1 //     public static Map hash_method_holes    = new HashMap();
 223 vivien   1.1.2.1 //     public static Map hash_holes_history   = new HashMap();
 224 vivien   1.1.2.1 //     public static Map hash_in_edge_always  = new HashMap();
 225 vivien   1.1.2.1 //     public static Map hash_out_edge_always = new HashMap();
 226 vivien   1.1.2.1 //     public static Map hash_out_edge_maybe  = new HashMap();
 227 vivien   1.1.2.1 //     public static Map hash_locks = new HashMap();
 228 vivien   1.1.2.1 
 229 vivien   1.1.2.1     public static int mh_number = 0;
 230 vivien   1.1.2.1 
 231 vivien   1.1.2.1     public static MethodHole BottomHole = 
 232 vivien   1.1.2.1         new MethodHole(null,
 233 vivien   1.1.2.1                        new HashSet(),
 234 vivien   1.1.2.1                        new MetaMethod[0],
 235 vivien   1.1.2.1                        new Set[0],
 236 vivien   1.1.2.1                        new PANode(PANode.INSIDE),
 237 vivien   1.1.2.1                        new PANode(PANode.INSIDE),
 238 vivien   1.1.2.1                        -1789,-1);
 239 vivien   1.1.2.1 
 240 vivien   1.1.2.1     /** Creates a <code>ODPointerAnalysis</code>.
 241 vivien   1.1.2.1      *
 242 vivien   1.1.2.1      *  @param _mcg The (meta) Call Graph that models the caller-callee
 243 vivien   1.1.2.1      *  relation between methods.
 244 vivien   1.1.2.1      *  @param _mac The dual of <code>_mcg</code> (<i>ie</i> the
 245 vivien   1.1.2.1      *  callee-caller relation.
 246 vivien   1.1.2.1      *  @param lbbconv The producer of the (Light) Basic Block representation
 247 vivien   1.1.2.1      *  of a method body. 
 248 vivien   1.1.2.1      *
 249 vivien   1.1.2.1      *</ul> */
 250 vivien   1.1.2.1     public ODPointerAnalysis(MetaCallGraph _mcg, MetaAllCallers _mac,
 251 salcianu 1.5                                  LBBConverter lbbconv, Linker linker) {
 252 vivien   1.1.2.1         mcg  = _mcg;
 253 vivien   1.1.2.1         mac  = _mac;
 254 vivien   1.1.2.1         scc_lbb_factory = new CachingSCCLBBFactory(lbbconv);
 255 salcianu 1.5             this.nodes = new NodeRepository(linker);
 256 vivien   1.1.2.1         if(SAVE_MEMORY)
 257 vivien   1.1.2.1             aamm = new HashSet();
 258 vivien   1.1.2.1     }
 259 vivien   1.1.2.1 
 260 vivien   1.1.2.1     // the set of already analyzed meta-methods
 261 vivien   1.1.2.1     private Set aamm = null;
 262 vivien   1.1.2.1 
 263 vivien   1.1.2.1     /** Returns the full (internal) <code>ODParIntGraph</code> attached to
 264 vivien   1.1.2.1      * the method <code>hm</code> i.e. the graph at the end of the method.
 265 vivien   1.1.2.1      * Returns <code>null</code> if no such graph is available. */
 266 vivien   1.1.2.1     public ODParIntGraph getIntParIntGraph(MetaMethod mm){
 267 vivien   1.1.2.1         // FV Caution...
 268 vivien   1.1.2.1         if(BOUNDED_ANALYSIS_DEPTH==true) {
 269 vivien   1.1.2.1             ODParIntGraph pig = 
 270 vivien   1.1.2.1                 (ODParIntGraph) hash_proc_int_d[current_analysis_depth].get(mm);
 271 vivien   1.1.2.1             if (pig==null){
 272 vivien   1.1.2.1                 System.out.println("ERROR: getIntParIntGraph " + 
 273 vivien   1.1.2.1                                    "called in bounded analysis " + 
 274 vivien   1.1.2.1                                    "and return null pig");
 275 vivien   1.1.2.1                 System.out.println("current_analysis_depth= " +
 276 vivien   1.1.2.1                                    current_analysis_depth);
 277 vivien   1.1.2.1             }
 278 vivien   1.1.2.1             return pig;
 279 vivien   1.1.2.1         }
 280 vivien   1.1.2.1         else
 281 vivien   1.1.2.1             if(SAVE_MEMORY){
 282 vivien   1.1.2.1                 if(!aamm.contains(mm))
 283 vivien   1.1.2.1                     analyze(mm);
 284 vivien   1.1.2.1                 analyze_intra_proc(mm);
 285 vivien   1.1.2.1                 ODParIntGraph pig = (ODParIntGraph)hash_proc_int.get(mm);
 286 vivien   1.1.2.1                 hash_proc_int.clear();
 287 vivien   1.1.2.1                 return pig;
 288 vivien   1.1.2.1             }
 289 vivien   1.1.2.1             else{
 290 vivien   1.1.2.1                 ODParIntGraph pig = (ODParIntGraph)hash_proc_int.get(mm);
 291 vivien   1.1.2.1                 // FV test to be modified ? In fact, do we need any
 292 vivien   1.1.2.1                 // bufferization at all by hash_proc_int ?
 293 vivien   1.1.2.1                 if(pig == null){
 294 vivien   1.1.2.1                     analyze(mm);
 295 vivien   1.1.2.1                     pig = (ODParIntGraph)hash_proc_int.get(mm);
 296 vivien   1.1.2.1                 }
 297 vivien   1.1.2.1                 return pig;
 298 vivien   1.1.2.1             }
 299 vivien   1.1.2.1     }
 300 vivien   1.1.2.1 
 301 vivien   1.1.2.1     public boolean isAnalyzed(MetaMethod mm){
 302 vivien   1.1.2.1         ODParIntGraph pig = (ODParIntGraph) hash_proc_int.get(mm);
 303 vivien   1.1.2.1         if (pig==null)
 304 vivien   1.1.2.1             return false;
 305 vivien   1.1.2.1         else
 306 vivien   1.1.2.1             return true;
 307 vivien   1.1.2.1     }
 308 vivien   1.1.2.1 
 309 vivien   1.1.2.1 
 310 vivien   1.1.2.1     public ODParIntGraph getIntParIntGraph(MetaMethod mm, boolean compute_it){
 311 vivien   1.1.2.1         ODParIntGraph pig = null;
 312 vivien   1.1.2.1         // FV Caution...
 313 vivien   1.1.2.1         if(BOUNDED_ANALYSIS_DEPTH==true) {
 314 vivien   1.1.2.1             pig = (ODParIntGraph) hash_proc_int_d[current_analysis_depth].get(mm);
 315 vivien   1.1.2.1             if ((pig==null)&&(compute_it)){
 316 vivien   1.1.2.1                 analyze_intra_proc(mm);
 317 vivien   1.1.2.1                 pig = (ODParIntGraph) hash_proc_int_d[current_analysis_depth].get(mm);
 318 vivien   1.1.2.1             }
 319 vivien   1.1.2.1             else{
 320 vivien   1.1.2.1                 if (pig==null)
 321 vivien   1.1.2.1                     System.out.println("ERROR: getIntParIntGraph " + 
 322 vivien   1.1.2.1                                        "called in bounded analysis " + 
 323 vivien   1.1.2.1                                        "and return null pig");
 324 vivien   1.1.2.1             }
 325 vivien   1.1.2.1         }
 326 vivien   1.1.2.1         else pig = (ODParIntGraph) hash_proc_int.get(mm);
 327 vivien   1.1.2.1         if((pig == null) && compute_it){
 328 vivien   1.1.2.1             analyze(mm);
 329 vivien   1.1.2.1             pig = (ODParIntGraph)hash_proc_int.get(mm);
 330 vivien   1.1.2.1         }
 331 vivien   1.1.2.1         return pig;
 332 vivien   1.1.2.1     }
 333 vivien   1.1.2.1 
 334 vivien   1.1.2.1 
 335 vivien   1.1.2.1 
 336 vivien   1.1.2.1     
 337 vivien   1.1.2.1     /** Returns the simplified (external) <code>ODParIntGraph</code> attached to
 338 vivien   1.1.2.1      * the method <code>hm</code> i.e. the graph at the end of the method.
 339 vivien   1.1.2.1      * of which only the parts reachable from the exterior (via parameters,
 340 vivien   1.1.2.1      * returned objects or static classes) have been preserved. The escape
 341 vivien   1.1.2.1      * function do not consider the parameters of the function (anyway, this
 342 vivien   1.1.2.1      * graph is supposed to be inlined into the graph of the caller, so the 
 343 vivien   1.1.2.1      * parameters will disappear anyway).
 344 vivien   1.1.2.1      * Returns <code>null</code> if no such graph is available. */
 345 vivien   1.1.2.1     public ODParIntGraph getExtParIntGraph(MetaMethod mm){
 346 vivien   1.1.2.1         return getExtParIntGraph(mm,true);
 347 vivien   1.1.2.1     }
 348 vivien   1.1.2.1 
 349 vivien   1.1.2.1     // internal method doing the job
 350 vivien   1.1.2.1     public ODParIntGraph getExtParIntGraph(MetaMethod mm, boolean compute_it){
 351 vivien   1.1.2.1         ODParIntGraph pig = null;
 352 vivien   1.1.2.1         // FV Caution...
 353 vivien   1.1.2.1         if(BOUNDED_ANALYSIS_DEPTH==true) {
 354 vivien   1.1.2.1             pig = (ODParIntGraph) hash_proc_ext_d[current_analysis_depth].get(mm);
 355 vivien   1.1.2.1             if ((pig==null)&&(compute_it)){
 356 vivien   1.1.2.1                 analyze_intra_proc(mm);
 357 vivien   1.1.2.1                 pig = (ODParIntGraph) hash_proc_ext_d[current_analysis_depth].get(mm);
 358 vivien   1.1.2.1             }
 359 vivien   1.1.2.1             else{
 360 vivien   1.1.2.1                 if (pig==null)
 361 vivien   1.1.2.1                     System.out.println("ERROR: getExtParIntGraph " + 
 362 vivien   1.1.2.1                                        "called in bounded analysis " + 
 363 vivien   1.1.2.1                                        "and return null pig");
 364 vivien   1.1.2.1             }
 365 vivien   1.1.2.1         }
 366 vivien   1.1.2.1         else pig = (ODParIntGraph) hash_proc_ext.get(mm);
 367 vivien   1.1.2.1         if((pig == null) && compute_it){
 368 vivien   1.1.2.1             analyze(mm);
 369 vivien   1.1.2.1             pig = (ODParIntGraph)hash_proc_ext.get(mm);
 370 vivien   1.1.2.1         }
 371 vivien   1.1.2.1         return pig;
 372 vivien   1.1.2.1     }
 373 vivien   1.1.2.1 
 374 vivien   1.1.2.1     // Returns a version of the external graph for meta-method hm that is
 375 vivien   1.1.2.1     // specialized for the call site q
 376 vivien   1.1.2.1     ODParIntGraph getSpecializedExtParIntGraph(MetaMethod mm, CALL q){
 377 vivien   1.1.2.1         // first, search in the cache
 378 vivien   1.1.2.1         Map map_mm = (Map) cs_specs.get(mm);
 379 vivien   1.1.2.1         if(map_mm == null){
 380 vivien   1.1.2.1             map_mm = new HashMap();
 381 vivien   1.1.2.1             cs_specs.put(mm,map_mm);
 382 vivien   1.1.2.1         }
 383 vivien   1.1.2.1 
 384 vivien   1.1.2.1         ODParIntGraph pig = null;
 385 vivien   1.1.2.1         if (!ODPointerAnalysis.ON_DEMAND_ANALYSIS)
 386 vivien   1.1.2.1             pig = (ODParIntGraph) map_mm.get(q);
 387 vivien   1.1.2.1         if(pig != null){
 388 vivien   1.1.2.1 //          if (pig.isCoherent())
 389 vivien   1.1.2.1 //              System.out.println("PIG coherent in mem of getSpecializedExtParIntGraph");
 390 vivien   1.1.2.1 //          else{
 391 vivien   1.1.2.1 //              System.err.println("PIG incoherent in mem of getSpecializedExtParIntGraph");
 392 vivien   1.1.2.1 //              System.out.println("PIG incoherent in mem of getSpecializedExtParIntGraph");
 393 vivien   1.1.2.1 //              System.out.println(pig);
 394 vivien   1.1.2.1 //          }
 395 vivien   1.1.2.1             return pig;
 396 vivien   1.1.2.1         }
 397 vivien   1.1.2.1 
 398 vivien   1.1.2.1         // if the specialization was not already in the cache,
 399 vivien   1.1.2.1         // try to recover the original ParIntGraph (if it exists) and
 400 vivien   1.1.2.1         // specialize it
 401 vivien   1.1.2.1 
 402 vivien   1.1.2.1         ODParIntGraph original_pig = getExtParIntGraph(mm);
 403 vivien   1.1.2.1         if(original_pig == null) return null;
 404 vivien   1.1.2.1 
 405 vivien   1.1.2.1         
 406 vivien   1.1.2.1         ODParIntGraph new_pig = original_pig.csSpecialize(q);
 407 vivien   1.1.2.1 
 408 vivien   1.1.2.1 //      if (new_pig.isCoherent())
 409 vivien   1.1.2.1 //              System.out.println("PIG coherent in end of getSpecializedExtParIntGraph");
 410 vivien   1.1.2.1 //          else{
 411 vivien   1.1.2.1 //              System.err.println("PIG incoherent in end of getSpecializedExtParIntGraph");
 412 vivien   1.1.2.1 //              System.out.println("PIG incoherent in end of getSpecializedExtParIntGraph");
 413 vivien   1.1.2.1 //              System.out.println(new_pig);
 414 vivien   1.1.2.1 //          }
 415 vivien   1.1.2.1 
 416 vivien   1.1.2.1         if(!SAVE_MEMORY)
 417 vivien   1.1.2.1             map_mm.put(q,new_pig);
 418 vivien   1.1.2.1 
 419 vivien   1.1.2.1         return new_pig; 
 420 vivien   1.1.2.1     }
 421 vivien   1.1.2.1     // cache for call site sensitivity: Map<MetaMethod, Map<CALL,ODParIntGraph>>
 422 vivien   1.1.2.1     private Map cs_specs = new HashMap();
 423 vivien   1.1.2.1 
 424 vivien   1.1.2.1 
 425 vivien   1.1.2.1     // Returns a specialized version of the external graph for meta-method mm;
 426 vivien   1.1.2.1     // mm is supposed to be the run method (the body) of a thread.
 427 vivien   1.1.2.1     ODParIntGraph getSpecializedExtParIntGraph(MetaMethod mm){
 428 vivien   1.1.2.1 
 429 vivien   1.1.2.1         ODParIntGraph pig = (ODParIntGraph) t_specs.get(mm);
 430 vivien   1.1.2.1         if(pig != null) return pig;
 431 vivien   1.1.2.1 
 432 vivien   1.1.2.1         // if the specialization was not already in the cache,
 433 vivien   1.1.2.1         // try to recover the original ODParIntGraph (if it exists) and
 434 vivien   1.1.2.1         // specialize it
 435 vivien   1.1.2.1 
 436 vivien   1.1.2.1         ODParIntGraph original_pig = getExtParIntGraph(mm);
 437 vivien   1.1.2.1         if(original_pig == null) return null;
 438 vivien   1.1.2.1 
 439 vivien   1.1.2.1         ODParIntGraph new_pig = null;
 440 vivien   1.1.2.1         if(THREAD_SENSITIVE)
 441 vivien   1.1.2.1             new_pig = original_pig.tSpecialize(mm);
 442 vivien   1.1.2.1         else
 443 vivien   1.1.2.1             if(WEAKLY_THREAD_SENSITIVE)
 444 vivien   1.1.2.1                 new_pig = original_pig.wtSpecialize(mm);
 445 cananian 1.3.2.1             else assert false : "The thread specialization is off!";
 446 vivien   1.1.2.1 
 447 vivien   1.1.2.1         t_specs.put(mm,new_pig);
 448 vivien   1.1.2.1 
 449 vivien   1.1.2.1         return new_pig; 
 450 vivien   1.1.2.1     }
 451 vivien   1.1.2.1     // cache for thread sensitivity: Map<MetaMethod, ODParIntGraph>
 452 vivien   1.1.2.1     private Map t_specs = new HashMap();
 453 vivien   1.1.2.1 
 454 vivien   1.1.2.1 
 455 vivien   1.1.2.1     /** Returns the parameter nodes of the method <code>hm</code>. This is
 456 vivien   1.1.2.1      * useful for the understanding of the <code>ODParIntGraph</code> attached
 457 vivien   1.1.2.1      * to <code>hm</code> */
 458 vivien   1.1.2.1     public PANode[] getParamNodes(MetaMethod mm){
 459 vivien   1.1.2.1         return nodes.getAllParams(mm);
 460 vivien   1.1.2.1     }
 461 vivien   1.1.2.1 
 462 vivien   1.1.2.1     /** Returns the parallel interaction graph for the end of the method 
 463 vivien   1.1.2.1         <code>hm</code>. The interactions between <code>hm</code> and the
 464 vivien   1.1.2.1         threads it (transitively) starts are analyzed in order to 
 465 vivien   1.1.2.1         &quot;recover&quot; some of the escaped nodes.<br>
 466 vivien   1.1.2.1         See Section 10 <i>Inter-thread Analysis</i> in the original paper of
 467 vivien   1.1.2.1         Martin and John Whaley for more details. */
 468 vivien   1.1.2.1     public ODParIntGraph threadInteraction(MetaMethod mm){
 469 vivien   1.1.2.1         System.out.println("threadInteraction for " + mm);
 470 vivien   1.1.2.1         ODParIntGraph pig = (ODParIntGraph) getIntParIntGraph(mm);
 471 vivien   1.1.2.1         // TBU
 472 vivien   1.1.2.1         //      return InterThreadPA.resolve_threads(this, pig);
 473 vivien   1.1.2.1         return null;
 474 vivien   1.1.2.1     }
 475 vivien   1.1.2.1 
 476 vivien   1.1.2.1     private ODParIntGraph threadIntInteraction(MetaMethod mm){
 477 vivien   1.1.2.1         System.out.println("threadIntInteraction for " + mm);
 478 vivien   1.1.2.1         ODParIntGraph pig = (ODParIntGraph) getIntParIntGraph(mm);
 479 vivien   1.1.2.1 
 480 vivien   1.1.2.1         //TBU   return InterThreadPA.resolve_threads(this, pig);
 481 vivien   1.1.2.1         return null;
 482 vivien   1.1.2.1     }
 483 vivien   1.1.2.1 
 484 vivien   1.1.2.1     private ODParIntGraph threadExtInteraction(MetaMethod mm){
 485 vivien   1.1.2.1         System.out.println("threadExtInteraction for " + mm);
 486 vivien   1.1.2.1 
 487 vivien   1.1.2.1         ODParIntGraph pig = (ODParIntGraph) getIntThreadInteraction(mm);
 488 vivien   1.1.2.1             PANode[] nodes = getParamNodes(mm);
 489 vivien   1.1.2.1             boolean is_main =
 490 vivien   1.1.2.1                 mm.getHMethod().getName().equals("main");
 491 vivien   1.1.2.1 
 492 vivien   1.1.2.1             ODParIntGraph shrinked_graph = pig.keepTheEssential(nodes,is_main);
 493 vivien   1.1.2.1 
 494 vivien   1.1.2.1             // We try to correct some imprecisions in the analysis:
 495 vivien   1.1.2.1             //  1. if the meta-method is not returning an Object, clear
 496 vivien   1.1.2.1             // the return set of the shrinked_graph
 497 vivien   1.1.2.1             HMethod hm = mm.getHMethod();
 498 vivien   1.1.2.1             if(hm.getReturnType().isPrimitive())
 499 vivien   1.1.2.1                 shrinked_graph.G.r.clear();
 500 vivien   1.1.2.1             //  2. if the meta-method doesn't throw any exception,
 501 vivien   1.1.2.1             // clear the exception set of the shrinked_graph.
 502 vivien   1.1.2.1             if(hm.getExceptionTypes().length == 0)
 503 vivien   1.1.2.1                 shrinked_graph.G.excp.clear();
 504 vivien   1.1.2.1       return(shrinked_graph);
 505 vivien   1.1.2.1     }
 506 vivien   1.1.2.1 
 507 vivien   1.1.2.1     public ODParIntGraph getExtThreadInteraction(MetaMethod mm){
 508 vivien   1.1.2.1             ODParIntGraph pig = (ODParIntGraph)hash_proc_interact_ext.get(mm);
 509 vivien   1.1.2.1             if(pig == null){
 510 vivien   1.1.2.1                 pig = threadExtInteraction(mm);
 511 vivien   1.1.2.1                 hash_proc_interact_ext.put(mm, pig);
 512 vivien   1.1.2.1             }
 513 vivien   1.1.2.1             return pig;
 514 vivien   1.1.2.1     }
 515 vivien   1.1.2.1 
 516 vivien   1.1.2.1     public ODParIntGraph getIntThreadInteraction(MetaMethod mm){
 517 vivien   1.1.2.1             ODParIntGraph pig = (ODParIntGraph)hash_proc_interact_int.get(mm);
 518 vivien   1.1.2.1             if(pig == null){
 519 vivien   1.1.2.1                 pig = threadIntInteraction(mm);
 520 vivien   1.1.2.1                 hash_proc_interact_int.put(mm, pig);
 521 vivien   1.1.2.1             }
 522 vivien   1.1.2.1             return pig;
 523 vivien   1.1.2.1     }
 524 vivien   1.1.2.1 
 525 vivien   1.1.2.1 
 526 vivien   1.1.2.1 
 527 vivien   1.1.2.1 
 528 vivien   1.1.2.1 
 529 vivien   1.1.2.1     // Worklist of <code>MetaMethod</code>s for the inter-procedural analysis
 530 vivien   1.1.2.1     private PAWorkStack W_inter_proc = new PAWorkStack();
 531 vivien   1.1.2.1 
 532 vivien   1.1.2.1     // Worklist for the intra-procedural analysis; at any moment, it
 533 vivien   1.1.2.1     // contains only basic blocks from the same method.
 534 vivien   1.1.2.1     private PAWorkList  W_intra_proc = new PAWorkList();
 535 vivien   1.1.2.1 
 536 vivien   1.1.2.1     // Repository for node management.
 537 salcianu 1.5         final NodeRepository nodes;
 538 vivien   1.1.2.1     final NodeRepository getNodeRepository() { return nodes; }
 539 vivien   1.1.2.1 
 540 vivien   1.1.2.1 
 541 vivien   1.1.2.1     // Navigator for the mmethod SCC building phase. The code is complicated
 542 vivien   1.1.2.1     // by the fact that we are interested only in yet unexplored methods
 543 vivien   1.1.2.1     // (i.e. whose parallel interaction graphs are not yet in the cache).
 544 salcianu 1.5         private Navigator mm_navigator =
 545 salcianu 1.5             new Navigator() {
 546 vivien   1.1.2.1                 public Object[] next(Object node){
 547 vivien   1.1.2.1                     MetaMethod[] mms  = mcg.getCallees((MetaMethod)node);
 548 vivien   1.1.2.1                     MetaMethod[] mms2 = get_new_mmethods(mms);
 549 vivien   1.1.2.1                     
 550 vivien   1.1.2.1                     if(DETERMINISTIC)
 551 vivien   1.1.2.1                         Arrays.sort(mms2, UComp.uc);
 552 vivien   1.1.2.1                     
 553 vivien   1.1.2.1                     return mms2;
 554 vivien   1.1.2.1                 }
 555 vivien   1.1.2.1                 
 556 vivien   1.1.2.1                 public Object[] prev(Object node){
 557 vivien   1.1.2.1                     MetaMethod[] mms  = mac.getCallers((MetaMethod)node);
 558 vivien   1.1.2.1                     MetaMethod[] mms2 = get_new_mmethods(mms);
 559 vivien   1.1.2.1                     
 560 vivien   1.1.2.1                     if(DETERMINISTIC)
 561 vivien   1.1.2.1                         Arrays.sort(mms2, UComp.uc);
 562 vivien   1.1.2.1                     return mms2;
 563 vivien   1.1.2.1                 }
 564 vivien   1.1.2.1                 
 565 vivien   1.1.2.1                 // selects only the (yet) unanalyzed methods
 566 vivien   1.1.2.1                 private MetaMethod[] get_new_mmethods(MetaMethod[] mms){
 567 vivien   1.1.2.1                     int count = 0;
 568 vivien   1.1.2.1                     boolean good[] = new boolean[mms.length];
 569 vivien   1.1.2.1                     for(int i = 0 ; i < mms.length ; i++)
 570 vivien   1.1.2.1                         if(!hash_proc_ext.containsKey(mms[i])){
 571 vivien   1.1.2.1                             good[i] = true;
 572 vivien   1.1.2.1                             count++;
 573 vivien   1.1.2.1                         }
 574 vivien   1.1.2.1                         else
 575 vivien   1.1.2.1                             good[i] = false;
 576 vivien   1.1.2.1                     
 577 vivien   1.1.2.1                     MetaMethod[] new_mms = new MetaMethod[count];
 578 vivien   1.1.2.1                     int j = 0;
 579 vivien   1.1.2.1                     for(int i = 0 ; i < mms.length ; i++)
 580 vivien   1.1.2.1                         if(good[i])
 581 vivien   1.1.2.1                             new_mms[j++] = mms[i];
 582 vivien   1.1.2.1                     return new_mms;
 583 vivien   1.1.2.1                 }
 584 vivien   1.1.2.1             };
 585 vivien   1.1.2.1     
 586 vivien   1.1.2.1 
 587 vivien   1.1.2.1     // Top-level procedure for the analysis. Receives the main method as
 588 vivien   1.1.2.1     // parameter. For the moment, it is not doing the inter-thread analysis
 589 vivien   1.1.2.1     private void analyze(MetaMethod mm){
 590 vivien   1.1.2.1         if(DEBUG)
 591 vivien   1.1.2.1             System.out.println("ANALYZE: " + mm);
 592 vivien   1.1.2.1 
 593 vivien   1.1.2.1         long begin_time = TIMING ? System.currentTimeMillis() : 0;
 594 vivien   1.1.2.1 
 595 vivien   1.1.2.1         if(DEBUG)
 596 vivien   1.1.2.1           System.out.println("Creating the strongly connected components " +
 597 vivien   1.1.2.1                              "of methods ...");
 598 vivien   1.1.2.1 
 599 vivien   1.1.2.1         // SCComponent.DETERMINISTIC = DETERMINISTIC;
 600 vivien   1.1.2.1 
 601 vivien   1.1.2.1         // the topologically sorted graph of strongly connected components
 602 vivien   1.1.2.1         // composed of mutually recursive methods (the edges model the
 603 vivien   1.1.2.1         // caller-callee interaction).
 604 salcianu 1.9             TopSortedCompDiGraph<MetaMethod> mmethod_sccs = 
 605 salcianu 1.8                 new TopSortedCompDiGraph(Collections.singleton(mm),
 606 salcianu 1.8                                          mm_navigator);
 607 vivien   1.1.2.1 
 608 vivien   1.1.2.1         if(DEBUG_SCC || TIMING)
 609 salcianu 1.8                 Debug.display_mm_sccs(mmethod_sccs, mcg,
 610 salcianu 1.8                                       System.currentTimeMillis() - begin_time);
 611 vivien   1.1.2.1 
 612 salcianu 1.9             for(SCComponent scc : mmethod_sccs.incrOrder()) {
 613 vivien   1.1.2.1             analyze_inter_proc_scc(scc);
 614 vivien   1.1.2.1 
 615 salcianu 1.1.2.2             if(SAVE_MEMORY) {
 616 salcianu 1.11                    for(Object mm0 : scc.nodes())
 617 salcianu 1.11                        aamm.add((MetaMethod) mm0);
 618 salcianu 1.1.2.2             }
 619 vivien   1.1.2.1         }
 620 vivien   1.1.2.1 
 621 vivien   1.1.2.1         if(TIMING)
 622 vivien   1.1.2.1             System.out.println("analyze(" + mm + ") finished in " +
 623 vivien   1.1.2.1                           (System.currentTimeMillis() - begin_time) + "ms");
 624 vivien   1.1.2.1     }
 625 vivien   1.1.2.1 
 626 vivien   1.1.2.1 
 627 vivien   1.1.2.1     // information about the interesting AGET quads
 628 vivien   1.1.2.1     CachingArrayInfo cai = new CachingArrayInfo();
 629 vivien   1.1.2.1 
 630 vivien   1.1.2.1     // inter-procedural analysis of a group of mutually recursive methods
 631 vivien   1.1.2.1     private void analyze_inter_proc_scc(SCComponent scc){
 632 vivien   1.1.2.1         if(TIMING || DEBUG){
 633 vivien   1.1.2.1             System.out.print("SCC" + scc.getId() + 
 634 vivien   1.1.2.1                              "\t (" + scc.size() + " meta-method(s)){");
 635 salcianu 1.11                for(Iterator it = scc.nodes().iterator(); it.hasNext(); )
 636 vivien   1.1.2.1                 System.out.print("\n " + it.next());
 637 vivien   1.1.2.1             System.out.print("} ... ");
 638 vivien   1.1.2.1         }
 639 vivien   1.1.2.1 
 640 vivien   1.1.2.1         long b_time = TIMING ? System.currentTimeMillis() : 0;
 641 vivien   1.1.2.1 
 642 salcianu 1.11            MetaMethod mmethod = (MetaMethod) scc.nodes().iterator().next();
 643 vivien   1.1.2.1 
 644 vivien   1.1.2.1         // if SCC composed of a native or abstract method, return immediately!
 645 vivien   1.1.2.1         if(!analyzable(mmethod.getHMethod())){
 646 vivien   1.1.2.1             if(TIMING)
 647 vivien   1.1.2.1                 System.out.println(System.currentTimeMillis() - b_time + "ms");
 648 vivien   1.1.2.1             if(DEBUG)
 649 salcianu 1.8                     System.out.println(scc.toString() + " is unanalyzable");
 650 vivien   1.1.2.1             return;
 651 vivien   1.1.2.1         }
 652 vivien   1.1.2.1 
 653 vivien   1.1.2.1         // Initially, the worklist (actually a workstack) contains only one
 654 vivien   1.1.2.1         // of the methods from the actual group of mutually recursive
 655 vivien   1.1.2.1         // methods. The others will be added later (because they are reachable
 656 vivien   1.1.2.1         // in the AllCaller graph from this initial node). 
 657 vivien   1.1.2.1         W_inter_proc.add(mmethod);
 658 vivien   1.1.2.1 
 659 vivien   1.1.2.1         boolean must_check = scc.isLoop();
 660 vivien   1.1.2.1 
 661 vivien   1.1.2.1         while(!W_inter_proc.isEmpty()){
 662 vivien   1.1.2.1             // grab a method from the worklist
 663 vivien   1.1.2.1             MetaMethod mm_work = (MetaMethod) W_inter_proc.remove();
 664 vivien   1.1.2.1 
 665 vivien   1.1.2.1             ODParIntGraph old_info = (ODParIntGraph) hash_proc_ext.get(mm_work);
 666 vivien   1.1.2.1 
 667 vivien   1.1.2.1             analyze_intra_proc(mm_work);
 668 vivien   1.1.2.1             // clear the LightBasicBlock -> ODParIntGraph data generated by
 669 vivien   1.1.2.1             // analyze_intra_proc
 670 vivien   1.1.2.1             //lbb2pig.clear(); // annotation
 671 vivien   1.1.2.1             LBBConverter lbbconv = scc_lbb_factory.getLBBConverter();
 672 vivien   1.1.2.1             LightBasicBlock.Factory lbbf = 
 673 vivien   1.1.2.1                 lbbconv.convert2lbb(mm_work.getHMethod());
 674 vivien   1.1.2.1             clear_lbb2pig(lbbf);
 675 vivien   1.1.2.1             //end annotation
 676 vivien   1.1.2.1 
 677 vivien   1.1.2.1             ODParIntGraph new_info = (ODParIntGraph) hash_proc_ext.get(mm_work);
 678 vivien   1.1.2.1 
 679 vivien   1.1.2.1             if(must_check && !new_info.equals(old_info)) { // new info?
 680 vivien   1.1.2.1                 // since the original graph associated with hm_work changed,
 681 vivien   1.1.2.1                 // the old specializations for it are no longer actual;
 682 vivien   1.1.2.1                 if(CALL_CONTEXT_SENSITIVE)
 683 vivien   1.1.2.1                     cs_specs.remove(mm_work);
 684 vivien   1.1.2.1 
 685 vivien   1.1.2.1                 Object[] mms = mac.getCallers(mm_work);    
 686 vivien   1.1.2.1 
 687 vivien   1.1.2.1                 if(DETERMINISTIC){
 688 vivien   1.1.2.1                     Arrays.sort(mms,UComp.uc);
 689 vivien   1.1.2.1                 }
 690 vivien   1.1.2.1                 for(int i = 0; i < mms.length ; i++){
 691 vivien   1.1.2.1                     MetaMethod mm_caller = (MetaMethod) mms[i];
 692 vivien   1.1.2.1                     if(scc.contains(mm_caller))
 693 vivien   1.1.2.1                         W_inter_proc.add(mm_caller);
 694 vivien   1.1.2.1                 }
 695 vivien   1.1.2.1             }
 696 vivien   1.1.2.1         }
 697 vivien   1.1.2.1 
 698 vivien   1.1.2.1         // enable some GC:
 699 vivien   1.1.2.1         // 1. get rid of the cache from the scc_lbb factory; anyway, it is
 700 vivien   1.1.2.1         // unsuseful, since the methods from scc are never reanalyzed. 
 701 vivien   1.1.2.1         // 1b. the info attached to the LBBs will be collected by the GCC too
 702 vivien   1.1.2.1         scc_lbb_factory.clear();
 703 vivien   1.1.2.1         // 2. the meta methods of this SCC will never be revisited, so the
 704 vivien   1.1.2.1         // specializations generated for the call sites inside them are not
 705 vivien   1.1.2.1         // usefull any more
 706 vivien   1.1.2.1         if(CALL_CONTEXT_SENSITIVE)
 707 vivien   1.1.2.1             cs_specs.clear();
 708 vivien   1.1.2.1         // 3. clear the array info
 709 vivien   1.1.2.1         cai.clear();
 710 vivien   1.1.2.1         // 4. to save memory, the cache of "internal" graphs can be flushed
 711 vivien   1.1.2.1         if(SAVE_MEMORY){
 712 vivien   1.1.2.1             System.out.println("hash_proc_int cleared!");
 713 vivien   1.1.2.1             hash_proc_int.clear();
 714 vivien   1.1.2.1         }
 715 vivien   1.1.2.1 
 716 vivien   1.1.2.1         if(TIMING)
 717 vivien   1.1.2.1             System.out.println((System.currentTimeMillis() - b_time) + "ms");
 718 vivien   1.1.2.1     }
 719 vivien   1.1.2.1 
 720 vivien   1.1.2.1     private MetaMethod current_intra_mmethod = null;
 721 vivien   1.1.2.1     private ODParIntGraph initial_pig = null;
 722 vivien   1.1.2.1 
 723 vivien   1.1.2.1     // the set of the AGETs from arrays of non-primitive types.
 724 vivien   1.1.2.1     private Set good_agets = null;
 725 vivien   1.1.2.1 
 726 vivien   1.1.2.1     // Performs the intra-procedural pointer analysis.
 727 vivien   1.1.2.1     //FV changed from private to public
 728 vivien   1.1.2.1     public void analyze_intra_proc(MetaMethod mm){
 729 vivien   1.1.2.1         //if(DEBUG)
 730 vivien   1.1.2.1         System.out.println("META METHOD: " + mm);
 731 vivien   1.1.2.1         long start_time = System.currentTimeMillis();
 732 vivien   1.1.2.1 
 733 vivien   1.1.2.1         ODPointerAnalysis.number_of_mm_analyzed++;
 734 vivien   1.1.2.1 
 735 vivien   1.1.2.1         LBBConverter lbbconv = scc_lbb_factory.getLBBConverter();
 736 vivien   1.1.2.1         LightBasicBlock.Factory lbbf = lbbconv.convert2lbb(mm.getHMethod());
 737 vivien   1.1.2.1         HCode hcode = lbbf.getHCode();
 738 vivien   1.1.2.1         good_agets = cai.getInterestingAGETs(mm.getHMethod(), hcode);
 739 vivien   1.1.2.1 
 740 vivien   1.1.2.1         current_intra_mmethod = mm;
 741 vivien   1.1.2.1 
 742 vivien   1.1.2.1         // cut the method into SCCs of basic blocks
 743 salcianu 1.9             TopSortedCompDiGraph<LightBasicBlock> ts_lbbs = 
 744 salcianu 1.8                 scc_lbb_factory.computeSCCLBB(mm.getHMethod());
 745 vivien   1.1.2.1 
 746 salcianu 1.10            if(DEBUG2)
 747 salcianu 1.10                Debug.show_lbb_scc(mm, ts_lbbs);
 748 vivien   1.1.2.1 
 749 salcianu 1.10            if(STATS) Stats.record_mmethod_pass(mm, ts_lbbs);
 750 vivien   1.1.2.1 
 751 vivien   1.1.2.1         // construct the ODParIntGraph at the beginning of the method 
 752 salcianu 1.11            LightBasicBlock first_bb = (LightBasicBlock)
 753 salcianu 1.11                ts_lbbs.decrOrder().get(0).nodes().iterator().next();
 754 vivien   1.1.2.1         HEADER first_hce = (HEADER) first_bb.getElements()[0];
 755 vivien   1.1.2.1         METHOD m  = (METHOD) first_hce.next(1);
 756 vivien   1.1.2.1         initial_pig = get_mmethod_initial_pig(mm,m);
 757 vivien   1.1.2.1 //      if (ODPointerAnalysis.ON_DEMAND_ANALYSIS)
 758 vivien   1.1.2.1 //          initialize_OD_fields(mm);
 759 vivien   1.1.2.1 
 760 salcianu 1.8             
 761 vivien   1.1.2.1         // analyze the SCCs in decreasing topological order
 762 salcianu 1.9             for(SCComponent scc : ts_lbbs.decrOrder())
 763 salcianu 1.9                 analyze_intra_proc_scc(scc);
 764 vivien   1.1.2.1 
 765 vivien   1.1.2.1         good_agets = null;
 766 vivien   1.1.2.1         long end_time = System.currentTimeMillis();
 767 vivien   1.1.2.1         System.out.println("Analysis time= " + (end_time - start_time) + 
 768 vivien   1.1.2.1                            "ms for " + mm);
 769 vivien   1.1.2.1     }
 770 vivien   1.1.2.1 
 771 vivien   1.1.2.1 
 772 vivien   1.1.2.1 //     private HashSet    mm_with_inside_node = new HashSet();
 773 vivien   1.1.2.1 
 774 vivien   1.1.2.1     public boolean create_inside_nodes(MetaMethod mm){
 775 vivien   1.1.2.1         //if(DEBUG)
 776 vivien   1.1.2.1             System.out.println("META METHOD: " + mm);
 777 vivien   1.1.2.1 //      if(STATS) Stats.record_mmethod_pass(mm);
 778 vivien   1.1.2.1 
 779 vivien   1.1.2.1         LBBConverter lbbconv = scc_lbb_factory.getLBBConverter();
 780 vivien   1.1.2.1         LightBasicBlock.Factory lbbf = lbbconv.convert2lbb(mm.getHMethod());
 781 vivien   1.1.2.1         LightBasicBlock[] lbbs = lbbf.getAllBBs();
 782 vivien   1.1.2.1         Linker linker = mm.getHMethod().getDeclaringClass().getLinker();
 783 vivien   1.1.2.1         HClass excp_class = linker.forName("java.lang.Exception");
 784 vivien   1.1.2.1 
 785 vivien   1.1.2.1         for(int i=0; (i<lbbs.length); i++){
 786 vivien   1.1.2.1             HCodeElement[] instrs = lbbs[i].getElements();
 787 vivien   1.1.2.1             int len = instrs.length;
 788 vivien   1.1.2.1             for(int j = 0; (j < len); j++){
 789 vivien   1.1.2.1                 Quad q = (Quad) instrs[j];
 790 vivien   1.1.2.1                 int qk = q.kind();
 791 vivien   1.1.2.1                 if ((qk==QuadKind.ANEW)||(qk==QuadKind.NEW)){
 792 vivien   1.1.2.1                     GenType type = null;
 793 vivien   1.1.2.1                     if (qk==QuadKind.ANEW)
 794 vivien   1.1.2.1                         type = new GenType(((ANEW) q).hclass(), GenType.MONO);
 795 vivien   1.1.2.1                     else
 796 vivien   1.1.2.1                         type = new GenType(((NEW) q).hclass(), GenType.MONO);
 797 vivien   1.1.2.1 
 798 vivien   1.1.2.1                     if (!excp_class.isSuperclassOf(type.getHClass()))
 799 vivien   1.1.2.1                         return true;
 800 vivien   1.1.2.1                 }
 801 vivien   1.1.2.1             }
 802 vivien   1.1.2.1         }
 803 vivien   1.1.2.1         return false;
 804 vivien   1.1.2.1     }
 805 vivien   1.1.2.1 
 806 vivien   1.1.2.1     public void make_thread_heap(MetaMethod mm, ODMAInfo mainfo){
 807 vivien   1.1.2.1         if(DEBUG)
 808 vivien   1.1.2.1             System.out.println("META METHOD: " + mm);
 809 vivien   1.1.2.1 //      if(STATS) Stats.record_mmethod_pass(mm);
 810 vivien   1.1.2.1 
 811 vivien   1.1.2.1         LBBConverter lbbconv = scc_lbb_factory.getLBBConverter();
 812 vivien   1.1.2.1         LightBasicBlock.Factory lbbf = lbbconv.convert2lbb(mm.getHMethod());
 813 vivien   1.1.2.1         LightBasicBlock[] lbbs = lbbf.getAllBBs();
 814 vivien   1.1.2.1         Linker linker = mm.getHMethod().getDeclaringClass().getLinker();
 815 vivien   1.1.2.1         HClass thread_class = linker.forName("java.lang.Thread");
 816 vivien   1.1.2.1 
 817 vivien   1.1.2.1         for(int i=0; (i<lbbs.length); i++){
 818 vivien   1.1.2.1             HCodeElement[] instrs = lbbs[i].getElements();
 819 vivien   1.1.2.1             int len = instrs.length;
 820 vivien   1.1.2.1             for(int j = 0; (j < len); j++){
 821 vivien   1.1.2.1                 Quad q = (Quad) instrs[j];
 822 vivien   1.1.2.1                 int qk = q.kind();
 823 vivien   1.1.2.1                 if (qk==QuadKind.NEW){
 824 vivien   1.1.2.1                     GenType type = new GenType(((NEW) q).hclass(), GenType.MONO);
 825 vivien   1.1.2.1                     if (thread_class.isSuperclassOf(type.getHClass()))
 826 vivien   1.1.2.1                         {
 827 vivien   1.1.2.1                             System.err.println("!!!! One thread node found !!! " + mm);
 828 vivien   1.1.2.1                             MyAP ap = mainfo.getAPObj((NEW) q);
 829 vivien   1.1.2.1                             ap.mh = true;
 830 vivien   1.1.2.1                         }
 831 vivien   1.1.2.1                 }
 832 vivien   1.1.2.1             }
 833 vivien   1.1.2.1         }
 834 vivien   1.1.2.1     }
 835 vivien   1.1.2.1 
 836 vivien   1.1.2.1     public int count_creation_sites(MetaMethod mm){
 837 vivien   1.1.2.1         if(DEBUG)
 838 vivien   1.1.2.1             System.out.println("META METHOD: " + mm);
 839 vivien   1.1.2.1         
 840 vivien   1.1.2.1         int count = 0;
 841 vivien   1.1.2.1 
 842 vivien   1.1.2.1         LBBConverter lbbconv = scc_lbb_factory.getLBBConverter();
 843 vivien   1.1.2.1         LightBasicBlock.Factory lbbf = lbbconv.convert2lbb(mm.getHMethod());
 844 vivien   1.1.2.1         LightBasicBlock[] lbbs = lbbf.getAllBBs();
 845 vivien   1.1.2.1         
 846 vivien   1.1.2.1         for(int i=0; (i<lbbs.length); i++){
 847 vivien   1.1.2.1             HCodeElement[] instrs = lbbs[i].getElements();
 848 vivien   1.1.2.1             int len = instrs.length;
 849 vivien   1.1.2.1             for(int j = 0; (j < len); j++){
 850 vivien   1.1.2.1                 Quad q = (Quad) instrs[j];
 851 vivien   1.1.2.1                 int qk = q.kind();
 852 vivien   1.1.2.1                 if ((qk==QuadKind.ANEW)||(qk==QuadKind.NEW))
 853 vivien   1.1.2.1                     count++;
 854 vivien   1.1.2.1             }
 855 vivien   1.1.2.1         }
 856 vivien   1.1.2.1         return count;
 857 vivien   1.1.2.1     }
 858 vivien   1.1.2.1 
 859 vivien   1.1.2.1 
 860 vivien   1.1.2.1     // Intra-procedural analysis of a strongly connected component of
 861 vivien   1.1.2.1     // basic blocks.
 862 vivien   1.1.2.1     private void analyze_intra_proc_scc(SCComponent scc){
 863 vivien   1.1.2.1 
 864 vivien   1.1.2.1         if(DEBUG2)
 865 vivien   1.1.2.1             System.out.println("\nSCC" + scc.getId());
 866 vivien   1.1.2.1 
 867 vivien   1.1.2.1         // add ALL the BBs from this SCC to the worklist.
 868 vivien   1.1.2.1         if(DETERMINISTIC) {
 869 salcianu 1.11                Object[] objs = Debug.sortedSet(scc.nodes());
 870 vivien   1.1.2.1             for(int i = 0; i < objs.length; i++)
 871 vivien   1.1.2.1                 W_intra_proc.add(objs[i]);
 872 vivien   1.1.2.1         }
 873 vivien   1.1.2.1         else
 874 salcianu 1.11                W_intra_proc.addAll(scc.nodes());
 875 vivien   1.1.2.1 
 876 vivien   1.1.2.1         boolean must_check = scc.isLoop();
 877 vivien   1.1.2.1 
 878 vivien   1.1.2.1         while(!W_intra_proc.isEmpty()){
 879 vivien   1.1.2.1             // grab a Basic Block from the worklist
 880 vivien   1.1.2.1             LightBasicBlock lbb_work = (LightBasicBlock) W_intra_proc.remove();
 881 vivien   1.1.2.1 
 882 vivien   1.1.2.1             //ODParIntGraph old_info = (ODParIntGraph) lbb2pig.get(lbb_work);
 883 vivien   1.1.2.1             // annotation
 884 vivien   1.1.2.1             ODParIntGraphPair old_info = (ODParIntGraphPair) lbb_work.user_info;
 885 vivien   1.1.2.1             analyze_basic_block(lbb_work);
 886 vivien   1.1.2.1             ODParIntGraphPair new_info = (ODParIntGraphPair) lbb_work.user_info;
 887 vivien   1.1.2.1 
 888 vivien   1.1.2.1             if(must_check && !ODParIntGraphPair.identical(old_info, new_info)){
 889 vivien   1.1.2.1                 // yes! The succesors of the analyzed basic block
 890 vivien   1.1.2.1                 // are potentially "interesting", so they should be added
 891 vivien   1.1.2.1                 // to the intra-procedural worklist
 892 vivien   1.1.2.1 
 893 vivien   1.1.2.1                 LightBasicBlock[] next_lbbs = lbb_work.getNextLBBs();
 894 vivien   1.1.2.1                 int len = next_lbbs.length;
 895 vivien   1.1.2.1                 for(int i = 0; i < len; i++){
 896 vivien   1.1.2.1                     LightBasicBlock lbb_next = next_lbbs[i];
 897 vivien   1.1.2.1                     if(scc.contains(lbb_next))
 898 vivien   1.1.2.1                         W_intra_proc.add(lbb_next);
 899 vivien   1.1.2.1                 }
 900 vivien   1.1.2.1             }
 901 vivien   1.1.2.1         }
 902 vivien   1.1.2.1 
 903 vivien   1.1.2.1     }
 904 vivien   1.1.2.1 
 905 vivien   1.1.2.1 
 906 vivien   1.1.2.1     /** The Parallel Interaction Graph which is updated by the
 907 vivien   1.1.2.1      *  <code>analyze_basic_block</code>. This should normally be a
 908 vivien   1.1.2.1      *  local variable of that function but it must be also accessible
 909 vivien   1.1.2.1      *  to the <code>PAVisitor</code> class */
 910 vivien   1.1.2.1     private ODParIntGraph lbbpig = null;
 911 vivien   1.1.2.1 
 912 vivien   1.1.2.1     // The pair of ODParIntGraphs computed by the inter-procedural analysis
 913 vivien   1.1.2.1     // will be put here. 
 914 vivien   1.1.2.1     private ODParIntGraphPair call_pp = null;
 915 vivien   1.1.2.1 
 916 vivien   1.1.2.1 
 917 vivien   1.1.2.1 //     public static Map  in_edge_always    = null;
 918 vivien   1.1.2.1 //     public static Map  out_edge_always   = null;
 919 vivien   1.1.2.1 //     public static Map  out_edge_maybe    = null;
 920 vivien   1.1.2.1 //     public static Set  method_holes      = null;
 921 vivien   1.1.2.1 //     public static Relation holes_history = null;
 922 vivien   1.1.2.1 //     public static Relation locks         = null;
 923 vivien   1.1.2.1 
 924 vivien   1.1.2.1 
 925 vivien   1.1.2.1     /** QuadVisitor for the <code>analyze_basic_block</code> */
 926 vivien   1.1.2.1     private class PAVisitor extends QuadVisitor{
 927 vivien   1.1.2.1 
 928 vivien   1.1.2.1         /** Visit a general quad, other than those explicitly
 929 vivien   1.1.2.1          processed by the other <code>visit</code> methods. */
 930 vivien   1.1.2.1         public void visit(Quad q){
 931 vivien   1.1.2.1             // remove all the edges from the temps that are defined
 932 vivien   1.1.2.1             // by this quad.
 933 vivien   1.1.2.1             Temp[] defs = q.def();
 934 vivien   1.1.2.1             for(int i = 0; i < defs.length; i++)
 935 vivien   1.1.2.1                 lbbpig.G.I.removeEdges(defs[i]);
 936 vivien   1.1.2.1             //System.out.println(lbbpig);
 937 vivien   1.1.2.1         }
 938 vivien   1.1.2.1                 
 939 vivien   1.1.2.1 
 940 vivien   1.1.2.1         public void visit(HEADER q){
 941 vivien   1.1.2.1             // do nothing
 942 vivien   1.1.2.1             //System.out.println(lbbpig);
 943 vivien   1.1.2.1         }
 944 vivien   1.1.2.1 
 945 vivien   1.1.2.1         public void visit(METHOD q){
 946 vivien   1.1.2.1             // do nothing
 947 vivien   1.1.2.1             //System.out.println(lbbpig);
 948 vivien   1.1.2.1         }
 949 vivien   1.1.2.1 
 950 vivien   1.1.2.1         public void visit(TYPECAST q){
 951 vivien   1.1.2.1             // do nothing
 952 vivien   1.1.2.1             //System.out.println(lbbpig);
 953 vivien   1.1.2.1         }
 954 vivien   1.1.2.1 
 955 vivien   1.1.2.1         /** Copy statements **/
 956 vivien   1.1.2.1         public void visit(MOVE q){
 957 vivien   1.1.2.1             lbbpig.G.I.removeEdges(q.dst());
 958 vivien   1.1.2.1             Set set = lbbpig.G.I.pointedNodes(q.src());
 959 vivien   1.1.2.1             //System.out.println("Move " + set);
 960 vivien   1.1.2.1             lbbpig.G.I.addEdges(q.dst(),set);
 961 vivien   1.1.2.1             // q.dst() is a variable, do nothing more for ODA.
 962 vivien   1.1.2.1             //tbu
 963 vivien   1.1.2.1             //System.out.println(lbbpig);
 964 vivien   1.1.2.1         }
 965 vivien   1.1.2.1         
 966 vivien   1.1.2.1         
 967 vivien   1.1.2.1         // LOAD STATEMENTS
 968 vivien   1.1.2.1         /** Load statement; normal case */
 969 vivien   1.1.2.1         public void visit(GET q){
 970 vivien   1.1.2.1             Temp l2 = q.objectref();
 971 vivien   1.1.2.1             HField hf = q.field();
 972 vivien   1.1.2.1 
 973 vivien   1.1.2.1             //System.out.println("GET ");
 974 vivien   1.1.2.1 
 975 vivien   1.1.2.1             // do not analyze loads from non-pointer fields
 976 vivien   1.1.2.1             if(hf.getType().isPrimitive()) return;
 977 vivien   1.1.2.1 
 978 salcianu 1.6                 if(l2 == null) {
 979 vivien   1.1.2.1                 // special treatement of the static fields
 980 vivien   1.1.2.1                 PANode static_node =
 981 vivien   1.1.2.1                     nodes.getStaticNode(hf.getDeclaringClass().getName());
 982 vivien   1.1.2.1                 // l2 is a variable, do nothing more for ODA.
 983 salcianu 1.6                     lbbpig.G.e.addNodeHole(static_node, static_node);
 984 salcianu 1.6                     process_load(q, q.dst(), Collections.singleton(static_node),
 985 salcianu 1.6                                  hf.getName());
 986 salcianu 1.6                     return;
 987 vivien   1.1.2.1             }
 988 salcianu 1.6                 process_load(q, q.dst(), lbbpig.G.I.pointedNodes(l2),
 989 salcianu 1.6                              hf.getName());
 990 vivien   1.1.2.1             //System.out.println(lbbpig);
 991 vivien   1.1.2.1         }
 992 vivien   1.1.2.1         
 993 vivien   1.1.2.1         /** Load statement; special case - arrays. */
 994 salcianu 1.6             public void visit(AGET q) {
 995 vivien   1.1.2.1             if(DEBUG2){
 996 vivien   1.1.2.1                 System.out.println("AGET: " + q);
 997 vivien   1.1.2.1                 System.out.println("good_agets: " + good_agets);
 998 vivien   1.1.2.1             }
 999 vivien   1.1.2.1             //System.out.println("AGET " + q);
1000 vivien   1.1.2.1 
1001 vivien   1.1.2.1 
1002 vivien   1.1.2.1             // AGET from an array of primitive objects (int, float, ...)
1003 vivien   1.1.2.1             if(!good_agets.contains(q)){
1004 vivien   1.1.2.1                 if(DEBUG)
1005 vivien   1.1.2.1                     System.out.println("NOT-PA RELEVANT AGET: " + 
1006 vivien   1.1.2.1                                        q.getSourceFile() + ":" + 
1007 vivien   1.1.2.1                                        q.getLineNumber() + " " + q);
1008 vivien   1.1.2.1                 // not interesting for the pointer analysis
1009 vivien   1.1.2.1                 lbbpig.G.I.removeEdges(q.dst());
1010 vivien   1.1.2.1                 // q.dst() is a variable, do nothing more for ODA.
1011 vivien   1.1.2.1                 return;
1012 vivien   1.1.2.1             }
1013 vivien   1.1.2.1             // All the elements of an array are collapsed in a single
1014 vivien   1.1.2.1             // node, referenced through a conventional named field
1015 salcianu 1.6     
1016 salcianu 1.6                 process_load(q, q.dst(), lbbpig.G.I.pointedNodes(q.objectref()),
1017 salcianu 1.6                              ARRAY_CONTENT);
1018 vivien   1.1.2.1             //System.out.println(lbbpig);
1019 vivien   1.1.2.1         }
1020 vivien   1.1.2.1         
1021 vivien   1.1.2.1         /** Does the real processing of a load statement. */
1022 salcianu 1.6             public void process_load(Quad q, Temp l1, Set loadFrom, String f) {
1023 salcianu 1.6                 Set set_aux = loadFrom;
1024 vivien   1.1.2.1             Set set_S   = lbbpig.G.I.pointedNodes(set_aux,f);
1025 vivien   1.1.2.1             HashSet set_E = new HashSet();
1026 vivien   1.1.2.1             
1027 vivien   1.1.2.1 
1028 vivien   1.1.2.1             //System.out.println("PROCESS_LOAD ");
1029 vivien   1.1.2.1 
1030 cananian 1.7                 for (Object nodeO : set_aux){
1031 cananian 1.7                     PANode node = (PANode) nodeO;
1032 vivien   1.1.2.1                 // hasEscaped instead of escaped (there is no problem
1033 vivien   1.1.2.1                 // with the nodes that *will* escape - the future cannot
1034 vivien   1.1.2.1                 // affect us).
1035 vivien   1.1.2.1                 if(lbbpig.G.e.hasEscaped(node))
1036 vivien   1.1.2.1                     set_E.add(node);
1037 vivien   1.1.2.1             }
1038 vivien   1.1.2.1             
1039 vivien   1.1.2.1             lbbpig.G.I.removeEdges(l1);
1040 vivien   1.1.2.1 
1041 vivien   1.1.2.1 
1042 vivien   1.1.2.1             // create/use the load node corresponding to reading the field
1043 vivien   1.1.2.1             // f from node, forall node in set_E (the escaped nodes pointed to by l2)
1044 vivien   1.1.2.1             if(!set_E.isEmpty()) {
1045 vivien   1.1.2.1                 if (ODPointerAnalysis.MartinTheWildHacker){
1046 vivien   1.1.2.1                     // update the action repository
1047 vivien   1.1.2.1                     Set active_threads = lbbpig.tau.activeThreadSet();
1048 vivien   1.1.2.1                     PANode load_node = null;            
1049 cananian 1.7                         for(Object nodeO : set_E) {
1050 cananian 1.7                             PANode node = (PANode) nodeO;
1051 vivien   1.1.2.1                         Set a = lbbpig.G.O.pointedNodes(node, f);
1052 vivien   1.1.2.1                         if(a.isEmpty()) {
1053 vivien   1.1.2.1                             if(load_node == null) {
1054 vivien   1.1.2.1                                 load_node = nodes.getCodeNode(q,PANode.LOAD);
1055 vivien   1.1.2.1                                 set_S.add(load_node);
1056 vivien   1.1.2.1                             }
1057 vivien   1.1.2.1                             lbbpig.G.O.addEdge(node, f, load_node);
1058 vivien   1.1.2.1                             if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1059 vivien   1.1.2.1                                 lbbpig.odi.addOutsideEdges(node, f, load_node);
1060 vivien   1.1.2.1                             }
1061 vivien   1.1.2.1                             lbbpig.ar.add_ld(node, f, load_node,
1062 vivien   1.1.2.1                                              ActionRepository.THIS_THREAD,
1063 vivien   1.1.2.1                                              active_threads);
1064 vivien   1.1.2.1                         }
1065 vivien   1.1.2.1                         else {
1066 vivien   1.1.2.1                             PANode node2 = (PANode) a.iterator().next();
1067 vivien   1.1.2.1                             lbbpig.G.O.addEdge(node, f, node2);
1068 vivien   1.1.2.1                             if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1069 vivien   1.1.2.1                                 lbbpig.odi.addOutsideEdges(node, f, node2);
1070 vivien   1.1.2.1                             }
1071 vivien   1.1.2.1                             set_S.add(node2);
1072 vivien   1.1.2.1                             lbbpig.ar.add_ld(node, f, node2,
1073 vivien   1.1.2.1                                              ActionRepository.THIS_THREAD,
1074 vivien   1.1.2.1                                              active_threads);
1075 vivien   1.1.2.1                         }
1076 vivien   1.1.2.1                     }
1077 vivien   1.1.2.1                 
1078 vivien   1.1.2.1                     if(!ODPointerAnalysis.IGNORE_EO)
1079 cananian 1.3.2.1                         assert false : "Not implemented";
1080 vivien   1.1.2.1                     //lbbpig.eo.add(set_E, f, load_node, lbbpig.G.I);
1081 vivien   1.1.2.1                     
1082 vivien   1.1.2.1                     lbbpig.G.propagate(set_E);
1083 vivien   1.1.2.1                 }
1084 vivien   1.1.2.1                 else{
1085 vivien   1.1.2.1                     PANode load_node = nodes.getCodeNode(q,PANode.LOAD); 
1086 vivien   1.1.2.1                     set_S.add(load_node);
1087 vivien   1.1.2.1                     lbbpig.G.O.addEdges(set_E,f,load_node);
1088 vivien   1.1.2.1 
1089 vivien   1.1.2.1                     if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1090 vivien   1.1.2.1                         lbbpig.odi.addOutsideEdges(set_E, f, load_node);
1091 vivien   1.1.2.1                     }
1092 vivien   1.1.2.1 
1093 vivien   1.1.2.1                     if(!PointerAnalysis.IGNORE_EO)
1094 vivien   1.1.2.1                         lbbpig.eo.add(set_E, f, load_node, lbbpig.G.I);
1095 vivien   1.1.2.1 
1096 vivien   1.1.2.1                     lbbpig.G.propagate(set_E);
1097 vivien   1.1.2.1                     
1098 vivien   1.1.2.1                     // update the action repository
1099 vivien   1.1.2.1                     Set active_threads = lbbpig.tau.activeThreadSet();
1100 cananian 1.7                         for (Object neO : set_E){
1101 cananian 1.7                             PANode ne = (PANode) neO;
1102 vivien   1.1.2.1                         lbbpig.ar.add_ld(ne, f, load_node,
1103 vivien   1.1.2.1                                          ActionRepository.THIS_THREAD,
1104 vivien   1.1.2.1                                          active_threads);
1105 vivien   1.1.2.1                     }
1106 vivien   1.1.2.1                 }
1107 vivien   1.1.2.1             }
1108 vivien   1.1.2.1 
1109 vivien   1.1.2.1             lbbpig.G.I.addEdges(l1,set_S);
1110 vivien   1.1.2.1             // l1 is a variable : do nothing more for ODA
1111 vivien   1.1.2.1 
1112 vivien   1.1.2.1             if(TOUCHED_THREAD_SUPPORT) touch_threads(set_aux);
1113 vivien   1.1.2.1         }
1114 vivien   1.1.2.1 
1115 vivien   1.1.2.1 
1116 vivien   1.1.2.1         // OBJECT CREATION SITES
1117 vivien   1.1.2.1         /** Object creation sites; normal case */
1118 vivien   1.1.2.1         public void visit(NEW q){
1119 vivien   1.1.2.1             //System.out.println("NEW " + q);       
1120 vivien   1.1.2.1             process_new(q,q.dst());
1121 vivien   1.1.2.1             //System.out.println(lbbpig);
1122 vivien   1.1.2.1         }
1123 vivien   1.1.2.1         
1124 vivien   1.1.2.1         /** Object creation sites; special case - arrays */
1125 vivien   1.1.2.1         public void visit(ANEW q){
1126 vivien   1.1.2.1             //System.out.println("ANEW " + q);      
1127 vivien   1.1.2.1             process_new(q,q.dst());
1128 vivien   1.1.2.1             //System.out.println(lbbpig);
1129 vivien   1.1.2.1         }
1130 vivien   1.1.2.1         
1131 vivien   1.1.2.1         private void process_new(Quad q,Temp tmp){
1132 vivien   1.1.2.1 //          System.out.println("PROCESS_NEW " + q);
1133 vivien   1.1.2.1             // Kill_I = edges(I,l)
1134 vivien   1.1.2.1             PANode node = nodes.getCodeNode(q,PANode.INSIDE);
1135 vivien   1.1.2.1             if ((ODPointerAnalysis.ON_DEMAND_ANALYSIS)&&
1136 vivien   1.1.2.1                 (ODPointerAnalysis.NODES_DRIVEN)){
1137 vivien   1.1.2.1 //              System.out.println("storing...");
1138 vivien   1.1.2.1                 PANode n = (PANode) Quad2Node.get(q);
1139 vivien   1.1.2.1                 if(n==null){
1140 vivien   1.1.2.1                     Quad2Node.put(q,node);
1141 vivien   1.1.2.1                 }
1142 vivien   1.1.2.1                 else if (n.equals(node)){
1143 vivien   1.1.2.1                     //everything is OK
1144 vivien   1.1.2.1                 }
1145 vivien   1.1.2.1                 else {
1146 vivien   1.1.2.1                     System.err.println("**ERROR** : Quad with at leat to nodes " +
1147 vivien   1.1.2.1                                        q + " " + node + " " + n);
1148 vivien   1.1.2.1                 }
1149 vivien   1.1.2.1 //              if(Quad2Node==null){
1150 vivien   1.1.2.1 //                  Quad2Node = new LightMap();
1151 vivien   1.1.2.1 //                  mm2quadsNnodes.put(mm,Quad2Node);
1152 vivien   1.1.2.1 //              }
1153 vivien   1.1.2.1 
1154 vivien   1.1.2.1 
1155 vivien   1.1.2.1 //              System.err.println("New with all flags set...");
1156 vivien   1.1.2.1 //              System.err.println("Quad " + q + "(" + q.getID() + ")");
1157 vivien   1.1.2.1 //              if(ODPointerAnalysis.interestingQuads.contains(q)){
1158 vivien   1.1.2.1 // //               System.err.println("... IN !!!");
1159 vivien   1.1.2.1 //                  ODPointerAnalysis.interestingNodes.add(node);
1160 vivien   1.1.2.1 //                  ODPointerAnalysis.Quad2Nodes.add(q,node);
1161 vivien   1.1.2.1 //              }
1162 vivien   1.1.2.1 //              else{
1163 vivien   1.1.2.1 //                  ODPointerAnalysis.interestingNodes.add(node);
1164 vivien   1.1.2.1 //                  System.err.println("... notin :-(");
1165 vivien   1.1.2.1 //                  for(Iterator it_qq=ODPointerAnalysis.interestingQuads.iterator();
1166 vivien   1.1.2.1 //                      it_qq.hasNext(); ){
1167 vivien   1.1.2.1 //                      Quad qq = (Quad) it_qq.next();
1168 vivien   1.1.2.1 //                      if (qq.equals(q)){
1169 vivien   1.1.2.1 //                          System.err.println("... EQUALITY !!!");
1170 vivien   1.1.2.1 //                      }
1171 vivien   1.1.2.1 //                      else{
1172 vivien   1.1.2.1 //                          System.err.println("nothing new");
1173 vivien   1.1.2.1 //                          System.err.println("Quad " + q + "(" + q.getID() + ")");
1174 vivien   1.1.2.1 //                          System.err.println("Quad " + qq + "(" + qq.getID() + ")");
1175 vivien   1.1.2.1 //                          if (q.getID()==qq.getID()){
1176 vivien   1.1.2.1 //                              System.err.println(q.getFactory());
1177 vivien   1.1.2.1 //                              System.err.println(qq.getFactory());
1178 vivien   1.1.2.1                             
1179 vivien   1.1.2.1 //                          if (q.hashCode()==qq.hashCode()) 
1180 vivien   1.1.2.1 //                              System.err.println("hashCode()");
1181 vivien   1.1.2.1 //                          if (q.getFactory().equals(qq.getFactory())) 
1182 vivien   1.1.2.1 //                              System.err.println("getFactory()()");
1183 vivien   1.1.2.1 //                          if (q.getSourceFile().equals(qq.getSourceFile())) 
1184 vivien   1.1.2.1 //                              System.err.println("getSourceFile()");
1185 vivien   1.1.2.1 //                          else{
1186 vivien   1.1.2.1 //                              System.err.println("getSourceFile= " + q.getSourceFile() + qq.getSourceFile());
1187 vivien   1.1.2.1 //                          }
1188 vivien   1.1.2.1 //                          if (q.getLineNumber()==qq.getLineNumber()) 
1189 vivien   1.1.2.1 //                              System.err.println("getLineNumber()");
1190 vivien   1.1.2.1 // //                       if (q.()==qq.()) System.err.println("()");
1191 vivien   1.1.2.1 //                          }
1192 vivien   1.1.2.1 //                      }
1193 vivien   1.1.2.1 //              }
1194 vivien   1.1.2.1 //              }
1195 vivien   1.1.2.1             }
1196 vivien   1.1.2.1             lbbpig.G.I.removeEdges(tmp);
1197 vivien   1.1.2.1             // Gen_I = {<l,n>}
1198 vivien   1.1.2.1             lbbpig.G.I.addEdge(tmp,node);
1199 vivien   1.1.2.1             // tmp is a variable : do nothing more for ODA
1200 vivien   1.1.2.1             //System.out.println(lbbpig);
1201 vivien   1.1.2.1         }
1202 vivien   1.1.2.1         
1203 vivien   1.1.2.1         
1204 vivien   1.1.2.1         /** Return statement: r' = I(l) */
1205 vivien   1.1.2.1         public void visit(RETURN q){
1206 vivien   1.1.2.1             //System.out.println("RETURN " + q);            
1207 vivien   1.1.2.1             Temp tmp = q.retval();
1208 vivien   1.1.2.1             // return without value; nothing to be done
1209 vivien   1.1.2.1             if(tmp == null) return;
1210 vivien   1.1.2.1             Set set = lbbpig.G.I.pointedNodes(tmp);
1211 vivien   1.1.2.1             // TAKE CARE: r is assumed to be empty before!
1212 vivien   1.1.2.1             lbbpig.G.r.addAll(set);
1213 vivien   1.1.2.1             //System.out.println(lbbpig);
1214 vivien   1.1.2.1         }
1215 vivien   1.1.2.1 
1216 vivien   1.1.2.1         /** Return statement: r' = I(l) */
1217 vivien   1.1.2.1         public void visit(THROW q){
1218 vivien   1.1.2.1             //System.out.println("THROW " + q);     
1219 vivien   1.1.2.1             Temp tmp = q.throwable();
1220 vivien   1.1.2.1             Set set = lbbpig.G.I.pointedNodes(tmp);
1221 vivien   1.1.2.1             // TAKE CARE: excp is assumed to be empty before!
1222 vivien   1.1.2.1             lbbpig.G.excp.addAll(set);
1223 vivien   1.1.2.1             //System.out.println(lbbpig);
1224 vivien   1.1.2.1         }
1225 vivien   1.1.2.1         
1226 vivien   1.1.2.1         
1227 vivien   1.1.2.1         // STORE STATEMENTS
1228 salcianu 1.6     
1229 salcianu 1.6             // [AS] changed the code to remove the infamous
1230 salcianu 1.6             // ArtificialTempFactory.  process_store takes as arguments
1231 salcianu 1.6             // the sets of source / destination nodes, instead of l1/l2.
1232 salcianu 1.6             // This way, we can treat the static field assignment without
1233 salcianu 1.6             // introducing a bogus artificial temp.
1234 vivien   1.1.2.1         /** Store statements; normal case */
1235 salcianu 1.6             public void visit(SET q) {
1236 vivien   1.1.2.1             //System.out.println("SET " + q);       
1237 vivien   1.1.2.1             Temp   l1 = q.objectref();
1238 salcianu 1.6                 Temp   l2 = q.src();
1239 vivien   1.1.2.1             HField hf = q.field();
1240 vivien   1.1.2.1             // do not analyze stores into non-pointer fields
1241 vivien   1.1.2.1             if(hf.getType().isPrimitive()) return;
1242 vivien   1.1.2.1             // static field -> get the corresponding artificial node
1243 salcianu 1.6                 if(l1 == null) {
1244 vivien   1.1.2.1                 PANode static_node =
1245 vivien   1.1.2.1                     nodes.getStaticNode(hf.getDeclaringClass().getName());
1246 vivien   1.1.2.1                 // l1 is a variable : do nothing more for ODA
1247 vivien   1.1.2.1                 lbbpig.G.e.addNodeHole(static_node,static_node);
1248 salcianu 1.6     
1249 salcianu 1.6                     process_store(Collections.singleton(static_node),
1250 salcianu 1.6                                   hf.getName(),
1251 salcianu 1.6                                   lbbpig.G.I.pointedNodes(l2));
1252 salcianu 1.6                     return;
1253 vivien   1.1.2.1             }
1254 salcianu 1.6                 process_store(lbbpig.G.I.pointedNodes(l1),
1255 salcianu 1.6                               hf.getName(),
1256 salcianu 1.6                               lbbpig.G.I.pointedNodes(l2));
1257 vivien   1.1.2.1             //System.out.println(lbbpig);
1258 vivien   1.1.2.1         }
1259 vivien   1.1.2.1         
1260 vivien   1.1.2.1         /** Store statement; special case - array */
1261 salcianu 1.6             public void visit(ASET q) {
1262 vivien   1.1.2.1             //System.out.println("ASET " + q);      
1263 vivien   1.1.2.1             // All the elements of an array are collapsed in a single
1264 vivien   1.1.2.1             // node
1265 salcianu 1.6                 process_store(lbbpig.G.I.pointedNodes(q.objectref()),
1266 salcianu 1.6                               ARRAY_CONTENT,
1267 salcianu 1.6                               lbbpig.G.I.pointedNodes(q.src()));
1268 vivien   1.1.2.1             //System.out.println(lbbpig);
1269 vivien   1.1.2.1         }
1270 vivien   1.1.2.1         
1271 salcianu 1.6             /** Does the real processing of a store statement: edges from
1272 salcianu 1.6                 any node in set1 toward any node in set2, labeled with
1273 salcianu 1.6                 field f. */
1274 salcianu 1.6             public void process_store(Set set1, String f, Set set2) {
1275 salcianu 1.6                 lbbpig.G.I.addEdges(set1, f, set2);
1276 vivien   1.1.2.1             if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1277 vivien   1.1.2.1                 //System.out.println("in_edge_always");
1278 vivien   1.1.2.1                 lbbpig.odi.addInsideEdges(set1, f, set2);
1279 vivien   1.1.2.1             }
1280 vivien   1.1.2.1             lbbpig.G.propagate(set1);
1281 vivien   1.1.2.1 
1282 vivien   1.1.2.1             if(TOUCHED_THREAD_SUPPORT) touch_threads(set1);
1283 vivien   1.1.2.1             //System.out.println(lbbpig);
1284 vivien   1.1.2.1         }
1285 vivien   1.1.2.1         
1286 vivien   1.1.2.1         public void process_thread_start_site(CALL q){
1287 vivien   1.1.2.1             if(DEBUG2)
1288 vivien   1.1.2.1                 System.out.println("THREAD START SITE: " + 
1289 vivien   1.1.2.1                                    q.getSourceFile() + ":" +
1290 vivien   1.1.2.1                                    q.getLineNumber());
1291 vivien   1.1.2.1 
1292 vivien   1.1.2.1             //System.out.println("PROCESS_THREAD_START_SITE " + q);         
1293 vivien   1.1.2.1 
1294 vivien   1.1.2.1             // the parallel interaction graph in the case no thread
1295 vivien   1.1.2.1             // is started due to some error and an exception is returned
1296 vivien   1.1.2.1             // back from the "start()"
1297 vivien   1.1.2.1             ODParIntGraph lbbpig_no_thread = (ODParIntGraph) (lbbpig.clone());
1298 vivien   1.1.2.1 
1299 vivien   1.1.2.1             Temp l = q.params(0);
1300 vivien   1.1.2.1             Set set = lbbpig.G.I.pointedNodes(l);
1301 vivien   1.1.2.1             lbbpig.tau.incAll(set);
1302 vivien   1.1.2.1             
1303 cananian 1.7                 for (Object ntO : set){
1304 cananian 1.7                     PANode nt = (PANode) ntO;
1305 vivien   1.1.2.1                 lbbpig.G.e.addNodeHole(nt,nt);
1306 vivien   1.1.2.1                 lbbpig.G.propagate(Collections.singleton(nt));
1307 vivien   1.1.2.1             }
1308 vivien   1.1.2.1 
1309 vivien   1.1.2.1             call_pp = new ODParIntGraphPair(lbbpig, lbbpig_no_thread);      
1310 vivien   1.1.2.1             //System.out.println(lbbpig);
1311 vivien   1.1.2.1         }
1312 vivien   1.1.2.1 
1313 vivien   1.1.2.1         public void visit(CALL q){
1314 vivien   1.1.2.1             //System.out.println("CALL " + q);      
1315 vivien   1.1.2.1             // treat the thread start sites specially
1316 vivien   1.1.2.1             if(thread_start_site(q)){
1317 vivien   1.1.2.1                 process_thread_start_site(q);
1318 vivien   1.1.2.1                 return;
1319 vivien   1.1.2.1             }
1320 vivien   1.1.2.1 
1321 vivien   1.1.2.1             call_pp = 
1322 vivien   1.1.2.1                 ODInterProcPA.analyze_call(ODPointerAnalysis.this,
1323 vivien   1.1.2.1                                            current_intra_mmethod,
1324 vivien   1.1.2.1                                            q,       // the CALL site
1325 vivien   1.1.2.1                                            lbbpig); // the graph before the call
1326 vivien   1.1.2.1             //System.out.println(lbbpig);
1327 vivien   1.1.2.1         }
1328 vivien   1.1.2.1 
1329 vivien   1.1.2.1         // We are sure that the call site q corresponds to a thread start
1330 vivien   1.1.2.1         // site if only java.lang.Thread.start can be called there. (If
1331 vivien   1.1.2.1         // some other methods can be called, it is possible that some of
1332 vivien   1.1.2.1         // them do not start a thread.)
1333 vivien   1.1.2.1         private boolean thread_start_site(CALL q){
1334 vivien   1.1.2.1             //System.out.println("THREAD_START_SITE " + q);         
1335 vivien   1.1.2.1             MetaMethod mms[] = mcg.getCallees(current_intra_mmethod,q);
1336 vivien   1.1.2.1             if(mms.length!=1) return false;
1337 vivien   1.1.2.1 
1338 vivien   1.1.2.1             HMethod hm = mms[0].getHMethod();
1339 vivien   1.1.2.1             String name = hm.getName();
1340 vivien   1.1.2.1             if((name==null) || !name.equals("start")) return false;
1341 vivien   1.1.2.1 
1342 vivien   1.1.2.1             if(hm.isStatic()) return false;
1343 vivien   1.1.2.1             HClass hclass = hm.getDeclaringClass();
1344 vivien   1.1.2.1             return hclass.getName().equals("java.lang.Thread");
1345 vivien   1.1.2.1         }
1346 vivien   1.1.2.1 
1347 vivien   1.1.2.1         /** Process an acquire statement. */
1348 vivien   1.1.2.1         public void visit(MONITORENTER q){
1349 vivien   1.1.2.1             //System.out.println("MONITORENTER " + q);      
1350 vivien   1.1.2.1             process_acquire_release(q, q.lock());
1351 vivien   1.1.2.1             //System.out.println(lbbpig);
1352 vivien   1.1.2.1         }
1353 vivien   1.1.2.1 
1354 vivien   1.1.2.1         /** Process a release statement. */
1355 vivien   1.1.2.1         public void visit(MONITOREXIT q){
1356 vivien   1.1.2.1             //System.out.println("MONITOREXIT " + q);       
1357 vivien   1.1.2.1             process_acquire_release(q, q.lock());
1358 vivien   1.1.2.1             //System.out.println(lbbpig);
1359 vivien   1.1.2.1         }
1360 vivien   1.1.2.1 
1361 vivien   1.1.2.1         // Does the real processing for acquire/release statements.
1362 vivien   1.1.2.1         private void process_acquire_release(Quad q, Temp l){
1363 vivien   1.1.2.1             //System.out.println("PROCESS_ACQUIRE_RELEASE " + q);           
1364 vivien   1.1.2.1             Set active_threads = lbbpig.tau.activeThreadSet();
1365 cananian 1.7                 for (Object nodeO : lbbpig.G.I.pointedNodes(l)){
1366 cananian 1.7                     PANode node = (PANode) nodeO;
1367 vivien   1.1.2.1                 PASync sync = new PASync(node,ActionRepository.THIS_THREAD, q);
1368 vivien   1.1.2.1                 lbbpig.ar.add_sync(sync, active_threads);
1369 vivien   1.1.2.1                 if (ODPointerAnalysis.ON_DEMAND_ANALYSIS)
1370 vivien   1.1.2.1                     lbbpig.odi.addLock(sync);
1371 vivien   1.1.2.1             }
1372 vivien   1.1.2.1             
1373 vivien   1.1.2.1             if(TOUCHED_THREAD_SUPPORT)
1374 vivien   1.1.2.1                 touch_threads(lbbpig.G.I.pointedNodes(l));
1375 vivien   1.1.2.1             //System.out.println(lbbpig);
1376 vivien   1.1.2.1         }
1377 vivien   1.1.2.1 
1378 vivien   1.1.2.1         // Records the fact that the started thread from the set 
1379 vivien   1.1.2.1         // "set_touched_nodes" have been touched.
1380 vivien   1.1.2.1         private void touch_threads(Set set_touched_nodes){
1381 vivien   1.1.2.1             //System.out.println("TOUCH_THREADS");          
1382 cananian 1.7                 for(Object touched_nodeO : set_touched_nodes){
1383 cananian 1.7                     PANode touched_node = (PANode) touched_nodeO;
1384 vivien   1.1.2.1                 if((touched_node.type == PANode.INSIDE) &&
1385 vivien   1.1.2.1                    lbbpig.tau.isStarted(touched_node))
1386 vivien   1.1.2.1                     lbbpig.touch_thread(touched_node);
1387 vivien   1.1.2.1             }
1388 vivien   1.1.2.1             //System.out.println(lbbpig);
1389 vivien   1.1.2.1         }
1390 vivien   1.1.2.1 
1391 vivien   1.1.2.1 
1392 vivien   1.1.2.1         /** End of the currently analyzed method; store the graph
1393 vivien   1.1.2.1             in the hash table. */
1394 vivien   1.1.2.1         public void visit(FOOTER q){
1395 vivien   1.1.2.1             // The full graph is stored in the hash_proc_int hashtable;
1396 vivien   1.1.2.1             HMethod hm = current_intra_mmethod.getHMethod();
1397 vivien   1.1.2.1             System.out.println(" Footer: int: " + lbbpig);
1398 vivien   1.1.2.1             if(ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1399 vivien   1.1.2.1                 if (lbbpig==null){
1400 vivien   1.1.2.1 //                  for(int i=0; i<MAX_ANALYSIS_DEPTH; i++){
1401 vivien   1.1.2.1                     for(int i=0; i<2; i++){
1402 vivien   1.1.2.1                         hash_proc_int_d[i].put(current_intra_mmethod,null);
1403 vivien   1.1.2.1                         hash_proc_ext_d[i].put(current_intra_mmethod,null);
1404 vivien   1.1.2.1                     }
1405 vivien   1.1.2.1                 }
1406 vivien   1.1.2.1                 else {
1407 vivien   1.1.2.1 //                  ODParIntGraph new_pig = (ODParIntGraph) lbbpig.clone();
1408 vivien   1.1.2.1                     ODParIntGraph new_pig = lbbpig;
1409 vivien   1.1.2.1                     Linker linker =  hm.getDeclaringClass().getLinker();
1410 vivien   1.1.2.1                     HClass excp_class = 
1411 vivien   1.1.2.1                         linker.forName("java.lang.RuntimeException");
1412 vivien   1.1.2.1                     if(hm.getReturnType().isPrimitive()){
1413 vivien   1.1.2.1                         new_pig.G.r.clear();
1414 vivien   1.1.2.1                     }
1415 vivien   1.1.2.1                     if(hm.getExceptionTypes().length == 0){
1416 vivien   1.1.2.1                         HashSet faulty = new HashSet();
1417 cananian 1.7                             for(Object nO : new_pig.G.excp){
1418 cananian 1.7                                 PANode n = (PANode) nO;
1419 vivien   1.1.2.1                             GenType[] types = n.getPossibleClasses();
1420 vivien   1.1.2.1                             if ((types!=null)&&(types.length!=0)){
1421 vivien   1.1.2.1                                 boolean false_excp = true;
1422 vivien   1.1.2.1                                 for(int i=0; (i<types.length)&&(false_excp); i++){
1423 vivien   1.1.2.1                                     if (excp_class.isSuperclassOf(types[i].getHClass()))
1424 vivien   1.1.2.1                                         false_excp = false;
1425 vivien   1.1.2.1                                 }
1426 vivien   1.1.2.1                                 if(false_excp){
1427 vivien   1.1.2.1 //                                  System.err.println("Type length: " + types.length);
1428 vivien   1.1.2.1 //                                  for(int i=0; (i<types.length)&&(false_excp); i++){
1429 vivien   1.1.2.1 //                                      System.err.println("Type : " + 
1430 vivien   1.1.2.1 //                                                         types[i].getHClass());
1431 vivien   1.1.2.1 //                                      System.err.println("Remove " + n);
1432 vivien   1.1.2.1 //                                  }
1433 vivien   1.1.2.1                                     faulty.add(n);
1434 vivien   1.1.2.1                                 }
1435 vivien   1.1.2.1                             }
1436 vivien   1.1.2.1                         }
1437 vivien   1.1.2.1                         new_pig.G.excp.removeAll(faulty);
1438 vivien   1.1.2.1                     }
1439 vivien   1.1.2.1 //                  for(int i=0; i<MAX_ANALYSIS_DEPTH; i++){
1440 vivien   1.1.2.1                     for(int i=0; i<2; i++){
1441 vivien   1.1.2.1                         hash_proc_int_d[i].put(current_intra_mmethod,new_pig.clone());
1442 vivien   1.1.2.1                         hash_proc_ext_d[i].put(current_intra_mmethod,new_pig.clone());
1443 vivien   1.1.2.1                     }
1444 vivien   1.1.2.1                 }
1445 vivien   1.1.2.1             }
1446 vivien   1.1.2.1             hash_proc_int.put(current_intra_mmethod,lbbpig);
1447 vivien   1.1.2.1 
1448 vivien   1.1.2.1             // To obtain the external view of the method, the graph must be
1449 vivien   1.1.2.1             // shrinked to the really necessary parts: only the stuff
1450 vivien   1.1.2.1             // that is accessible from the "root" nodes (i.e. the nodes
1451 vivien   1.1.2.1             // that can be accessed by the rest of the program - e.g.
1452 vivien   1.1.2.1             // the caller).
1453 vivien   1.1.2.1             // The set of root nodes consists of the param and return
1454 vivien   1.1.2.1             // nodes, and (for the non-"main" methods) the static nodes.
1455 vivien   1.1.2.1             // TODO: think about the static nodes vs. "main"
1456 vivien   1.1.2.1             PANode[] nodes = getParamNodes(current_intra_mmethod);
1457 vivien   1.1.2.1             boolean is_main = 
1458 vivien   1.1.2.1                 current_intra_mmethod.getHMethod().getName().equals("main");
1459 vivien   1.1.2.1             ODParIntGraph shrinked_graph =lbbpig.keepTheEssential(nodes,is_main);
1460 vivien   1.1.2.1 
1461 vivien   1.1.2.1             // We try to correct some imprecisions in the analysis:
1462 vivien   1.1.2.1             //  1. if the meta-method is not returning an Object, clear
1463 vivien   1.1.2.1             // the return set of the shrinked_graph
1464 vivien   1.1.2.1             if(hm.getReturnType().isPrimitive())
1465 vivien   1.1.2.1                 shrinked_graph.G.r.clear();
1466 vivien   1.1.2.1             //  2. if the meta-method doesn't throw any exception,
1467 vivien   1.1.2.1             // clear the exception set of the shrinked_graph.
1468 vivien   1.1.2.1             if(hm.getExceptionTypes().length == 0)
1469 vivien   1.1.2.1                 shrinked_graph.G.excp.clear();
1470 vivien   1.1.2.1 
1471 vivien   1.1.2.1             // The external view of the graph is stored in the
1472 vivien   1.1.2.1             // hash_proc_ext hashtable;
1473 vivien   1.1.2.1             hash_proc_ext.put(current_intra_mmethod,shrinked_graph);
1474 vivien   1.1.2.1 //          System.out.println(" Footer: ext: " + shrinked_graph);
1475 vivien   1.1.2.1 //          if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1476 vivien   1.1.2.1 //              ODParIntGraph new_pig = (ODParIntGraph) lbbpig.clone();
1477 vivien   1.1.2.1 //              if(hm.getReturnType().isPrimitive()){
1478 vivien   1.1.2.1 //                  new_pig.G.r.clear();
1479 vivien   1.1.2.1 //              }
1480 vivien   1.1.2.1 //              if(hm.getExceptionTypes().length == 0){
1481 vivien   1.1.2.1 //                  HashSet faulty = new HashSet();
1482 vivien   1.1.2.1 //                  for(Iterator x_it= new_pig.G.excp.iterator(); x_it.hasNext(); ){
1483 vivien   1.1.2.1 //                      PANode n = (PANode) x_it.next();
1484 vivien   1.1.2.1 //                      GenType[] types = n.getPossibleClasses();
1485 vivien   1.1.2.1 //                      if ((types!=null)&&(types.length!=0)){
1486 vivien   1.1.2.1 //                          Linker linker = Loader.systemLinker;
1487 vivien   1.1.2.1 //                          HClass excp_class = 
1488 vivien   1.1.2.1 //                              linker.forName("java.lang.RuntimeException");
1489 vivien   1.1.2.1 //                          boolean false_excp = true;
1490 vivien   1.1.2.1 //                          for(int i=0; (i<types.length)&&(false_excp); i++){
1491 vivien   1.1.2.1 //                              if (excp_class.isSuperclassOf(types[i].getHClass()))
1492 vivien   1.1.2.1 //                                  false_excp = false;
1493 vivien   1.1.2.1 //                          }
1494 vivien   1.1.2.1 //                          if(false_excp){
1495 vivien   1.1.2.1 //                              System.err.println("Type length: " + types.length);
1496 vivien   1.1.2.1 //                              for(int i=0; (i<types.length)&&(false_excp); i++){
1497 vivien   1.1.2.1 //                                  System.err.println("Type : " + 
1498 vivien   1.1.2.1 //                                                     types[i].getHClass());
1499 vivien   1.1.2.1 //                              System.err.println("Remove " + n);
1500 vivien   1.1.2.1 //                              faulty.add(n);
1501 vivien   1.1.2.1 //                          }
1502 vivien   1.1.2.1 //                      }
1503 vivien   1.1.2.1 //                  }
1504 vivien   1.1.2.1 //                  new_pig.G.excp.removeAll(faulty);
1505 vivien   1.1.2.1 //              }
1506 vivien   1.1.2.1 //              hash_proc_ext_d[current_analysis_depth].
1507 vivien   1.1.2.1 //                  put(current_intra_mmethod,new_pig);
1508 vivien   1.1.2.1 //          }
1509 vivien   1.1.2.1         }
1510 vivien   1.1.2.1     }
1511 vivien   1.1.2.1     
1512 vivien   1.1.2.1 
1513 vivien   1.1.2.1     // Quad Visitor used by analayze_basic_block
1514 vivien   1.1.2.1     private PAVisitor pa_visitor = new PAVisitor();
1515 vivien   1.1.2.1     
1516 vivien   1.1.2.1     /** Analyzes a basic block - a Parallel Interaction Graph is computed at
1517 vivien   1.1.2.1      *  the beginning of the basic block, it is next updated by all the 
1518 vivien   1.1.2.1      *  instructions appearing in the basic block (in the order they appear
1519 vivien   1.1.2.1      *  in the original program). */
1520 vivien   1.1.2.1     private void analyze_basic_block(LightBasicBlock lbb){
1521 vivien   1.1.2.1         if(DEBUG2){
1522 vivien   1.1.2.1             System.out.println("BEGIN: Analyze_basic_block " + lbb);
1523 vivien   1.1.2.1             System.out.print("Prev BBs: ");
1524 vivien   1.1.2.1             Object[] prev_lbbs = lbb.getPrevLBBs();
1525 vivien   1.1.2.1             Arrays.sort(prev_lbbs, UComp.uc);
1526 vivien   1.1.2.1             for(int i = 0 ; i < prev_lbbs.length ; i++)
1527 vivien   1.1.2.1                 System.out.print((LightBasicBlock) prev_lbbs[i] + " ");
1528 vivien   1.1.2.1             System.out.println();
1529 vivien   1.1.2.1         }
1530 vivien   1.1.2.1 
1531 vivien   1.1.2.1         // lbbpig is the graph at the *bb point; it will be 
1532 vivien   1.1.2.1         // updated till it becomes the graph at the bb* point
1533 vivien   1.1.2.1         lbbpig = get_initial_bb_pig(lbb);
1534 vivien   1.1.2.1 
1535 vivien   1.1.2.1         if(DEBUG2){
1536 vivien   1.1.2.1             System.out.println("Before:");
1537 vivien   1.1.2.1             System.out.println(lbbpig);
1538 vivien   1.1.2.1         }
1539 vivien   1.1.2.1 
1540 vivien   1.1.2.1         // go through all the instructions of this basic block
1541 vivien   1.1.2.1         HCodeElement[] instrs = lbb.getElements();
1542 vivien   1.1.2.1         int len = instrs.length;
1543 vivien   1.1.2.1         for(int i = 0; i < len; i++){
1544 vivien   1.1.2.1             Quad q = (Quad) instrs[i];
1545 vivien   1.1.2.1 
1546 vivien   1.1.2.1             if(DEBUG2)
1547 vivien   1.1.2.1                 System.out.println("INSTR: " + q.getSourceFile() + ":" +
1548 vivien   1.1.2.1                                    q.getLineNumber() + " " + q);
1549 vivien   1.1.2.1             
1550 vivien   1.1.2.1             // update the Parallel Interaction Graph according
1551 vivien   1.1.2.1             // to the current instruction
1552 vivien   1.1.2.1             q.accept(pa_visitor);
1553 vivien   1.1.2.1         }
1554 vivien   1.1.2.1 
1555 vivien   1.1.2.1         // if there was a pair, store the pair computed by the inter proc
1556 vivien   1.1.2.1         // module, otherwise, only the first element of the pair is essential.
1557 vivien   1.1.2.1         if(call_pp != null){
1558 vivien   1.1.2.1             lbb.user_info = call_pp;
1559 vivien   1.1.2.1             call_pp = null;
1560 vivien   1.1.2.1         }
1561 vivien   1.1.2.1         else
1562 vivien   1.1.2.1             lbb.user_info = new ODParIntGraphPair(lbbpig, null);
1563 vivien   1.1.2.1 
1564 vivien   1.1.2.1         if(DEBUG2){
1565 vivien   1.1.2.1             System.out.println("After:");
1566 vivien   1.1.2.1             System.out.println(lbbpig);
1567 vivien   1.1.2.1             System.out.print("Next BBs: ");
1568 vivien   1.1.2.1             Object[] next_lbbs = lbb.getNextLBBs();
1569 vivien   1.1.2.1             Arrays.sort(next_lbbs, UComp.uc);
1570 vivien   1.1.2.1             for(int i = 0 ; i < next_lbbs.length ; i++)
1571 vivien   1.1.2.1                 System.out.print((LightBasicBlock) next_lbbs[i] + " ");
1572 vivien   1.1.2.1             System.out.println("\n");
1573 vivien   1.1.2.1         }
1574 vivien   1.1.2.1     }
1575 vivien   1.1.2.1     
1576 vivien   1.1.2.1     /** Returns the Parallel Interaction Graph at the point bb*
1577 vivien   1.1.2.1      *  The returned <code>ODParIntGraph</code> must not be modified 
1578 vivien   1.1.2.1      *  by the caller. This function is used by 
1579 vivien   1.1.2.1      *  <code>get_initial_bb_pig</code>. */
1580 vivien   1.1.2.1     private ODParIntGraph get_after_bb_pig(LightBasicBlock lbb,
1581 vivien   1.1.2.1                                          LightBasicBlock lbb_son){
1582 vivien   1.1.2.1 
1583 vivien   1.1.2.1         ODParIntGraphPair pp = (ODParIntGraphPair) lbb.user_info;
1584 vivien   1.1.2.1         if(pp == null)
1585 vivien   1.1.2.1             return ODParIntGraph.EMPTY_GRAPH;
1586 vivien   1.1.2.1 
1587 vivien   1.1.2.1         int k = 0;
1588 vivien   1.1.2.1         HCodeElement last_lbb = lbb.getLastElement();
1589 vivien   1.1.2.1         if((last_lbb != null) && (last_lbb instanceof CALL)){
1590 vivien   1.1.2.1             CALL call = (CALL) last_lbb;
1591 vivien   1.1.2.1             HCodeElement first_lbb_son = lbb_son.getFirstElement();
1592 vivien   1.1.2.1             if(!call.next(0).equals(first_lbb_son)) k = 1;
1593 vivien   1.1.2.1         }
1594 vivien   1.1.2.1 
1595 vivien   1.1.2.1         //ODParIntGraph pig = (ODParIntGraph) lbb2pig.get(lbb);
1596 vivien   1.1.2.1         ODParIntGraph pig = pp.pig[k];
1597 vivien   1.1.2.1         return (pig==null)?ODParIntGraph.EMPTY_GRAPH:pig;
1598 vivien   1.1.2.1     }
1599 vivien   1.1.2.1 
1600 vivien   1.1.2.1 
1601 vivien   1.1.2.1     /** (Re)computes the Parallel Interaction Thread associated with
1602 vivien   1.1.2.1      *  the beginning of the <code>LightBasicBlock</code> <code>lbb</code>.
1603 vivien   1.1.2.1      *  This method is recomputing the stuff (instead of just grabbing it
1604 vivien   1.1.2.1      *  from the cache) because the information attached with some of
1605 vivien   1.1.2.1      *  the predecessors has changed (that's why <code>bb</code> is 
1606 vivien   1.1.2.1      *  reanalyzed) */
1607 vivien   1.1.2.1     private ODParIntGraph get_initial_bb_pig(LightBasicBlock lbb){
1608 vivien   1.1.2.1         LightBasicBlock[] prev = lbb.getPrevLBBs();
1609 vivien   1.1.2.1         int len = prev.length;
1610 vivien   1.1.2.1         if(len == 0){
1611 vivien   1.1.2.1             // This case is treated specially, it's about the
1612 vivien   1.1.2.1             // graph at the beginning of the current method.
1613 vivien   1.1.2.1             ODParIntGraph pig = initial_pig;
1614 vivien   1.1.2.1             return pig;
1615 vivien   1.1.2.1         }
1616 vivien   1.1.2.1         else{
1617 vivien   1.1.2.1             // do the union of the <code>ODParIntGraph</code>s attached to
1618 vivien   1.1.2.1             // all the predecessors of this basic block
1619 vivien   1.1.2.1 //          System.out.println("\n\nFrom ");
1620 vivien   1.1.2.1 //          System.out.println(get_after_bb_pig(prev[0], lbb));
1621 vivien   1.1.2.1 
1622 vivien   1.1.2.1             ODParIntGraph pig = 
1623 vivien   1.1.2.1                 (ODParIntGraph) (get_after_bb_pig(prev[0], lbb)).clone();
1624 vivien   1.1.2.1 
1625 vivien   1.1.2.1             for(int i = 1; i < len; i++){
1626 vivien   1.1.2.1 //              System.out.println("Join (1) on ");
1627 vivien   1.1.2.1 //              System.out.println(pig);
1628 vivien   1.1.2.1 //              System.out.println("\n and \n");
1629 vivien   1.1.2.1 //              System.out.println(get_after_bb_pig(prev[i], lbb));
1630 vivien   1.1.2.1                 pig.join(get_after_bb_pig(prev[i], lbb));
1631 vivien   1.1.2.1             }
1632 vivien   1.1.2.1 //          System.out.println("\n\n\nResult");
1633 vivien   1.1.2.1 //          System.out.println(pig);
1634 vivien   1.1.2.1             return pig;
1635 vivien   1.1.2.1         }
1636 vivien   1.1.2.1     }
1637 vivien   1.1.2.1 
1638 vivien   1.1.2.1 
1639 vivien   1.1.2.1     /** Computes the parallel interaction graph at the beginning of a 
1640 vivien   1.1.2.1      *  method; an almost empty graph except for the parameter nodes
1641 vivien   1.1.2.1      *  for the object formal parameter (i.e. primitive type parameters
1642 vivien   1.1.2.1      *  such as <code>int</code>, <code>float</code> do not have associated
1643 vivien   1.1.2.1      *  nodes */
1644 vivien   1.1.2.1     private ODParIntGraph get_mmethod_initial_pig(MetaMethod mm, METHOD m){
1645 vivien   1.1.2.1         Temp[]  params = m.params();
1646 vivien   1.1.2.1         HMethod     hm = mm.getHMethod();
1647 vivien   1.1.2.1         HClass[] types = hm.getParameterTypes();
1648 vivien   1.1.2.1 
1649 vivien   1.1.2.1         ODParIntGraph pig = new ODParIntGraph();
1650 vivien   1.1.2.1 
1651 vivien   1.1.2.1         // the following code is quite messy ... The problem is that I 
1652 vivien   1.1.2.1         // create param nodes only for the parameter with object types;
1653 vivien   1.1.2.1         // unfortunately, the types could be found only in HMethod (and
1654 vivien   1.1.2.1         // do not include the evetual this parameter for non-static nodes)
1655 vivien   1.1.2.1         // while the actual Temps associated with all the formal parameters
1656 vivien   1.1.2.1         // could be found only in METHOD. So, we have to coordinate
1657 vivien   1.1.2.1         // information from two different places and, even more, we have
1658 vivien   1.1.2.1         // to handle the missing this parameter (which is present in METHOD
1659 vivien   1.1.2.1         // but not in HMethod). 
1660 vivien   1.1.2.1         boolean isStatic = 
1661 vivien   1.1.2.1             java.lang.reflect.Modifier.isStatic(hm.getModifiers());
1662 vivien   1.1.2.1         // if the method is non-static, the first parameter is not metioned
1663 vivien   1.1.2.1         // in HMethod - it's the implicit this parameter.
1664 vivien   1.1.2.1         int skew = isStatic?0:1;
1665 vivien   1.1.2.1         // number of object formal parameters = the number of param nodes
1666 vivien   1.1.2.1         int count = skew;
1667 vivien   1.1.2.1         for(int i = 0; i < types.length; i++)
1668 vivien   1.1.2.1             if(!types[i].isPrimitive()) count++;
1669 vivien   1.1.2.1         
1670 vivien   1.1.2.1         nodes.addParamNodes(mm,count);
1671 vivien   1.1.2.1         Stats.record_mmethod_params(mm,count);
1672 vivien   1.1.2.1 
1673 vivien   1.1.2.1         // add all the edges of type <p,np> (i.e. parameter to 
1674 vivien   1.1.2.1         // parameter node) - just for the non-primitive types (e.g. int params
1675 vivien   1.1.2.1         // do not clutter our analysis)
1676 vivien   1.1.2.1         // the edges for the static fields will
1677 vivien   1.1.2.1         // be added later.
1678 vivien   1.1.2.1         count = 0;
1679 vivien   1.1.2.1         for(int i = 0; i < params.length; i++)
1680 vivien   1.1.2.1             if((i<skew) || ((i>=skew) && !types[i-skew].isPrimitive())){
1681 vivien   1.1.2.1                 PANode param_node = nodes.getParamNode(mm,count);
1682 vivien   1.1.2.1                 pig.G.I.addEdge(params[i],param_node);
1683 vivien   1.1.2.1                 //tbu ??
1684 vivien   1.1.2.1                 // The param nodes are escaping through themselves */
1685 vivien   1.1.2.1                 pig.G.e.addNodeHole(param_node,param_node);
1686 vivien   1.1.2.1                 count++;
1687 vivien   1.1.2.1             }
1688 vivien   1.1.2.1 
1689 vivien   1.1.2.1         return pig;
1690 vivien   1.1.2.1     }
1691 vivien   1.1.2.1 
1692 vivien   1.1.2.1     /** Check if <code>hm</code> can be analyzed by the pointer analysis. */
1693 vivien   1.1.2.1     public static final boolean analyzable(HMethod hm){
1694 vivien   1.1.2.1         int modifier = hm.getModifiers();
1695 vivien   1.1.2.1         return ! (
1696 vivien   1.1.2.1             (java.lang.reflect.Modifier.isNative(modifier)) ||
1697 vivien   1.1.2.1             (java.lang.reflect.Modifier.isAbstract(modifier))
1698 vivien   1.1.2.1             );
1699 vivien   1.1.2.1     }
1700 vivien   1.1.2.1 
1701 vivien   1.1.2.1 
1702 vivien   1.1.2.1     // the set of harmful native methods
1703 vivien   1.1.2.1     private static Set hns = new HashSet();
1704 vivien   1.1.2.1     //    static{
1705 vivien   1.1.2.1     // here should be put some initializations for the hns set
1706 vivien   1.1.2.1     //}
1707 vivien   1.1.2.1 
1708 vivien   1.1.2.1     public final boolean harmful_native(HMethod hm){
1709 vivien   1.1.2.1         if(!Modifier.isNative(hm.getModifiers()))
1710 vivien   1.1.2.1             return false;
1711 vivien   1.1.2.1         return hns.contains(hm);
1712 vivien   1.1.2.1     }
1713 vivien   1.1.2.1 
1714 vivien   1.1.2.1     /** Prints some statistics. */
1715 vivien   1.1.2.1     public final void  print_stats(){
1716 vivien   1.1.2.1         if(!STATS){
1717 vivien   1.1.2.1             System.out.println("Statistics are deactivated.");
1718 vivien   1.1.2.1             System.out.println("Turn on the ODPointerAnalysis.STATS flag!");
1719 vivien   1.1.2.1             return;
1720 vivien   1.1.2.1         }
1721 vivien   1.1.2.1 
1722 vivien   1.1.2.1         Stats.print_stats();
1723 vivien   1.1.2.1         nodes.print_stats();
1724 vivien   1.1.2.1         System.out.println("==========================================");
1725 vivien   1.1.2.1         if(SHOW_NODES){
1726 vivien   1.1.2.1             System.out.println("BASIC NODES");
1727 vivien   1.1.2.1             System.out.println(nodes);
1728 vivien   1.1.2.1             System.out.println("NODE SPECIALIZATIONS:");
1729 vivien   1.1.2.1             nodes.show_specializations();
1730 vivien   1.1.2.1         }
1731 vivien   1.1.2.1     }
1732 vivien   1.1.2.1 
1733 vivien   1.1.2.1     /** Returns the parallel interaction graph valid at the program point
1734 vivien   1.1.2.1         right before <code>q</code>. <code>q</code> belongs to the light basic
1735 vivien   1.1.2.1         block <code>lbb</code> of the <code>current_intra_mmethod</code>.
1736 vivien   1.1.2.1         The analysis is re-executed from the beginning of <code>lbb</code>,
1737 vivien   1.1.2.1         till we reach <code>q</code> when we stop it and return the 
1738 vivien   1.1.2.1         parallel intercation graph valid at that moment. */
1739 vivien   1.1.2.1     private ODParIntGraph analyze_lbb_up_to_q(LightBasicBlock lbb, Quad q){
1740 vivien   1.1.2.1         lbbpig = get_initial_bb_pig(lbb);
1741 vivien   1.1.2.1 
1742 vivien   1.1.2.1         HCodeElement[] instrs = lbb.getElements();
1743 vivien   1.1.2.1         for(int i = 0; i < instrs.length; i++){
1744 vivien   1.1.2.1             Quad q_curr = (Quad) instrs[i];
1745 vivien   1.1.2.1             if(q_curr.equals(q)) return lbbpig;
1746 vivien   1.1.2.1             q_curr.accept(pa_visitor);
1747 vivien   1.1.2.1         }
1748 cananian 1.3.2.1         assert false : q + " was not in " + lbb;
1749 vivien   1.1.2.1         return null; // this should never happen
1750 vivien   1.1.2.1     }
1751 vivien   1.1.2.1     
1752 vivien   1.1.2.1 
1753 vivien   1.1.2.1     /** Returns the parallel interaction graph attached to the program point
1754 vivien   1.1.2.1         right before <code>q</code> in the body of meta-method
1755 vivien   1.1.2.1         <code>mm</code>. */
1756 vivien   1.1.2.1     public final ODParIntGraph getPIGAtQuad(MetaMethod mm, Quad q){
1757 cananian 1.3.2.1         assert mcg.getAllMetaMethods().contains(mm) : "Uncalled/unknown meta-method!";
1758 vivien   1.1.2.1         LBBConverter lbbconv = scc_lbb_factory.getLBBConverter();
1759 vivien   1.1.2.1         LightBasicBlock.Factory lbbf = lbbconv.convert2lbb(mm.getHMethod());
1760 cananian 1.3.2.1         assert lbbf != null : "Fatal error";
1761 vivien   1.1.2.1         LightBasicBlock lbb = lbbf.getBlock(q);
1762 cananian 1.3.2.1         assert lbb != null : "No (Light)BasicBlock found for " + q;
1763 vivien   1.1.2.1         // as all the ODParIntGraph's for methods are computed, a simple
1764 vivien   1.1.2.1         // intra-procedural analysis of mm (with some caller-callee
1765 vivien   1.1.2.1         // interactions) is enough.
1766 vivien   1.1.2.1         analyze_intra_proc(mm);
1767 vivien   1.1.2.1         // now, we found the right basic block, we also have the results
1768 vivien   1.1.2.1         // for all the basic block of the concerned method; all we need
1769 vivien   1.1.2.1         // is to redo the pointer analysis for that basic block, stopping
1770 vivien   1.1.2.1         // when we meet q.
1771 vivien   1.1.2.1         ODParIntGraph retval = analyze_lbb_up_to_q(lbb, q);
1772 vivien   1.1.2.1 
1773 vivien   1.1.2.1         // clear the LightBasicBlock -> ODParIntGraph cache generated by
1774 vivien   1.1.2.1         // analyze_intra_proc
1775 vivien   1.1.2.1         //lbb2pig.clear();
1776 vivien   1.1.2.1         clear_lbb2pig(lbbf); // annotation;
1777 vivien   1.1.2.1 
1778 vivien   1.1.2.1         return retval;
1779 vivien   1.1.2.1     }
1780 vivien   1.1.2.1 
1781 vivien   1.1.2.1     // activates the GC
1782 vivien   1.1.2.1     private final void clear_lbb2pig(LightBasicBlock.Factory lbbf){
1783 vivien   1.1.2.1         LightBasicBlock[] lbbs = lbbf.getAllBBs();
1784 vivien   1.1.2.1         for(int i = 0; i < lbbs.length; i++)
1785 vivien   1.1.2.1             lbbs[i].user_info = null;
1786 vivien   1.1.2.1     }
1787 vivien   1.1.2.1 
1788 vivien   1.1.2.1     /** Returns the set of the nodes pointed by the temporary <code>t</code>
1789 vivien   1.1.2.1         at the point right before executing instruction <code>q</code>
1790 vivien   1.1.2.1         from the body of meta-method <code>mm</code>. */
1791 vivien   1.1.2.1     public final Set pointedNodes(MetaMethod mm, Quad q, Temp l){
1792 vivien   1.1.2.1         // 1. obtain the Parallel Interaction Graph attached to the point
1793 vivien   1.1.2.1         // right before the execution of q (noted .q in the article). 
1794 vivien   1.1.2.1         ODParIntGraph pig = getPIGAtQuad(mm,q);
1795 vivien   1.1.2.1         // 2. look at the nodes pointed by l; as from a temporary we can
1796 vivien   1.1.2.1         // have only inside edges, it is enough to look in the I set.
1797 vivien   1.1.2.1         return pig.G.I.pointedNodes(l);
1798 vivien   1.1.2.1     }
1799 vivien   1.1.2.1 
1800 vivien   1.1.2.1 
1801 vivien   1.1.2.1     /*
1802 vivien   1.1.2.1     ////////// SPECIAL HANDLING FOR SOME NATIVE METHODS ////////////////////
1803 vivien   1.1.2.1 
1804 vivien   1.1.2.1     final ODParIntGraph getExpODParIntGraph(MetaMethod mm){
1805 vivien   1.1.2.1         HMethod hm = mm.getHMethod();
1806 vivien   1.1.2.1 
1807 vivien   1.1.2.1         ODParIntGraph pig = (ODParIntGraph) hash_proc_ext.get(mm);
1808 vivien   1.1.2.1         if(pig == null){
1809 vivien   1.1.2.1             pig = ext_pig_for_native(hm);
1810 vivien   1.1.2.1             if(pig != null) hash_proc_ext.put(mm, pig);
1811 vivien   1.1.2.1         }
1812 vivien   1.1.2.1 
1813 vivien   1.1.2.1         return pig;
1814 vivien   1.1.2.1     }
1815 vivien   1.1.2.1 
1816 vivien   1.1.2.1     private final ODParIntGraph ext_pig_for_native(HMethod hm){
1817 vivien   1.1.2.1         HClass hclass = hm.getDeclaringClass();
1818 vivien   1.1.2.1         String clname = hclass.getName();
1819 vivien   1.1.2.1         String hmname = hm.getName();
1820 vivien   1.1.2.1 
1821 vivien   1.1.2.1         if(clname.equals("java.lang.Object") &&
1822 vivien   1.1.2.1            hmname.equals("hashCode"));
1823 vivien   1.1.2.1             
1824 vivien   1.1.2.1     }
1825 vivien   1.1.2.1     */
1826 vivien   1.1.2.1 }
1827 vivien   1.1.2.1 
1828 cananian 1.2