1 vivien   1.1.2.1 // ODMAInfo.java, created Mon Apr  3 18:17:57 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 
   5 vivien   1.1.2.1 // NOTE: I eliminated lots of debug messages by commenting them with
   6 vivien   1.1.2.1 //   "//B/" - I don't trust the ability of "javac" to eliminate the
   7 vivien   1.1.2.1 //    unuseful "if(DEBUG) ..." stuff.
   8 vivien   1.1.2.1 //       If you need this messages back replace "//B/" with "" (nothing).
   9 vivien   1.1.2.1 
  10 vivien   1.1.2.1 package harpoon.Analysis.PointerAnalysis;
  11 vivien   1.1.2.1 
  12 vivien   1.1.2.1 
  13 vivien   1.1.2.1 import java.util.Iterator;
  14 vivien   1.1.2.1 import java.util.Set;
  15 vivien   1.1.2.1 import java.util.HashSet;
  16 vivien   1.1.2.1 import java.util.Map;
  17 vivien   1.1.2.1 import java.util.HashMap;
  18 vivien   1.1.2.1 
  19 vivien   1.1.2.1 import harpoon.ClassFile.HCodeElement;
  20 vivien   1.1.2.1 import harpoon.ClassFile.HCodeFactory;
  21 vivien   1.1.2.1 import harpoon.ClassFile.HCode;
  22 vivien   1.1.2.1 import harpoon.ClassFile.HClass;
  23 vivien   1.1.2.1 import harpoon.ClassFile.HMethod;
  24 vivien   1.1.2.1 import harpoon.ClassFile.Linker;
  25 vivien   1.1.2.1 import harpoon.ClassFile.Loader;
  26 vivien   1.1.2.1 import harpoon.Analysis.Maps.AllocationInformation;
  27 vivien   1.1.2.1 
  28 vivien   1.1.2.1 import harpoon.Analysis.Quads.Unreachable;
  29 vivien   1.1.2.1 
  30 vivien   1.1.2.1 import harpoon.Analysis.MetaMethods.MetaMethod;
  31 vivien   1.1.2.1 import harpoon.Analysis.MetaMethods.MetaCallGraph;
  32 vivien   1.1.2.1 import harpoon.Analysis.MetaMethods.MetaAllCallers;
  33 vivien   1.1.2.1 import harpoon.Analysis.MetaMethods.GenType;
  34 vivien   1.1.2.1 
  35 vivien   1.1.2.1 import harpoon.Analysis.DefaultAllocationInformation;
  36 vivien   1.1.2.1 
  37 vivien   1.1.2.1 import harpoon.IR.Quads.Edge;
  38 vivien   1.1.2.1 import harpoon.IR.Quads.Quad;
  39 vivien   1.1.2.1 import harpoon.IR.Quads.METHOD;
  40 vivien   1.1.2.1 import harpoon.IR.Quads.HEADER;
  41 vivien   1.1.2.1 import harpoon.IR.Quads.NEW;
  42 vivien   1.1.2.1 import harpoon.IR.Quads.ANEW;
  43 vivien   1.1.2.1 import harpoon.IR.Quads.MOVE;
  44 vivien   1.1.2.1 import harpoon.IR.Quads.CALL;
  45 vivien   1.1.2.1 import harpoon.IR.Quads.RETURN;
  46 vivien   1.1.2.1 import harpoon.IR.Quads.THROW;
  47 vivien   1.1.2.1 import harpoon.IR.Quads.NOP;
  48 vivien   1.1.2.1 import harpoon.IR.Quads.PHI;
  49 vivien   1.1.2.1 import harpoon.IR.Quads.QuadFactory;
  50 vivien   1.1.2.1 
  51 vivien   1.1.2.1 import harpoon.Temp.Temp;
  52 vivien   1.1.2.1 import harpoon.Temp.TempFactory;
  53 vivien   1.1.2.1 
  54 vivien   1.1.2.1 import harpoon.Util.Util;
  55 cananian 1.8     import net.cscott.jutil.WorkSet;
  56 vivien   1.1.2.1 
  57 vivien   1.1.2.1 import harpoon.IR.Quads.QuadVisitor;
  58 vivien   1.1.2.1 import harpoon.Util.Graphs.SCComponent;
  59 salcianu 1.6     import harpoon.Util.Graphs.Navigator;
  60 salcianu 1.10    import harpoon.Util.Graphs.TopSortedCompDiGraph;
  61 vivien   1.1.2.1 
  62 vivien   1.1.2.1 import harpoon.Util.DataStructs.Relation;
  63 vivien   1.1.2.1 import harpoon.Util.DataStructs.LightRelation;
  64 vivien   1.1.2.1 import harpoon.Util.DataStructs.LightMap;
  65 vivien   1.1.2.1 
  66 vivien   1.1.2.1 
  67 vivien   1.1.2.1 /**
  68 vivien   1.1.2.1  * <code>ODMAInfo</code>
  69 vivien   1.1.2.1  * 
  70 cananian 1.1.2.3  * @author  Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu>
  71 salcianu 1.12     * @version $Id: ODMAInfo.java,v 1.12 2004/03/06 21:52:24 salcianu Exp $
  72 vivien   1.1.2.1  */
  73 vivien   1.1.2.1 public class ODMAInfo implements AllocationInformation, java.io.Serializable {
  74 vivien   1.1.2.1 
  75 vivien   1.1.2.1     private static boolean DEBUG = false;
  76 vivien   1.1.2.1 
  77 vivien   1.1.2.1     /** Enabless the application of some method inlining to increase the
  78 vivien   1.1.2.1         effectiveness of the stack allocation. Only inlinings that
  79 vivien   1.1.2.1         increase the effectiveness of the stack allocation are done.
  80 vivien   1.1.2.1         For the time being, only 1-level inlining is done. */
  81 vivien   1.1.2.1     public static boolean DO_METHOD_INLINING = false;
  82 vivien   1.1.2.1 
  83 vivien   1.1.2.1     /** Only methods that have less than <code>MAX_INLINING_SIZE</code>
  84 vivien   1.1.2.1         instructions can be inlined. Just a simple way of preventing
  85 vivien   1.1.2.1         the code bloat. */
  86 vivien   1.1.2.1     public static int MAX_INLINING_SIZE = 50; 
  87 vivien   1.1.2.1 
  88 vivien   1.1.2.1     /** Enables the use of preallocation: if an object will be accessed only
  89 vivien   1.1.2.1         by a thread (<i>ie</i> it is created just to pass some parameters
  90 vivien   1.1.2.1         to a thread), it can be preallocated into the heap of that thread.
  91 vivien   1.1.2.1         For the moment, it is potentially dangerous so it is deactivated by
  92 vivien   1.1.2.1         default. */
  93 vivien   1.1.2.1     public static boolean DO_PREALLOCATION = false;
  94 vivien   1.1.2.1 
  95 vivien   1.1.2.1     /** Forces the allocation of ALL the threads on the stack. Of course,
  96 vivien   1.1.2.1         dummy and unsafe. */
  97 vivien   1.1.2.1     public static boolean NO_TG = false;
  98 vivien   1.1.2.1 
  99 vivien   1.1.2.1     public static Map Nodes2Status = new LightMap();
 100 vivien   1.1.2.1     public static int nStudiedNode = 0;
 101 vivien   1.1.2.1 
 102 vivien   1.1.2.1     private static Set good_holes = null;
 103 vivien   1.1.2.1     private void initialize_good_holes(){
 104 vivien   1.1.2.1         good_holes = new HashSet();
 105 vivien   1.1.2.1 
 106 vivien   1.1.2.1         // "java.lang.Thread.currentThread()" is not harmful with regard to
 107 vivien   1.1.2.1         // the thread specific heaps stuff; add it to the set "good_holes"
 108 vivien   1.1.2.1         HClass hclass = linker.forName("java.lang.Thread");
 109 vivien   1.1.2.1         HMethod[] hms = hclass.getDeclaredMethods();
 110 vivien   1.1.2.1         for(int i = 0; i < hms.length; i++)
 111 vivien   1.1.2.1             if("currentThread".equals(hms[i].getName()))
 112 vivien   1.1.2.1                 good_holes.add(hms[i]);
 113 vivien   1.1.2.1 
 114 vivien   1.1.2.1         if(DEBUG)
 115 vivien   1.1.2.1             System.out.println("GOOD HOLES: " + good_holes);
 116 vivien   1.1.2.1     }
 117 vivien   1.1.2.1 
 118 vivien   1.1.2.1     ODPointerAnalysis pa;
 119 vivien   1.1.2.1     HCodeFactory    hcf;
 120 vivien   1.1.2.1     // the meta-method we are interested in (only those that could be
 121 vivien   1.1.2.1     // started by the main or by one of the threads (transitively) started
 122 vivien   1.1.2.1     // by the main thread.
 123 vivien   1.1.2.1     Set             mms;
 124 vivien   1.1.2.1     NodeRepository  node_rep;
 125 vivien   1.1.2.1     MetaCallGraph   mcg;
 126 vivien   1.1.2.1     MetaAllCallers  mac;
 127 vivien   1.1.2.1 
 128 vivien   1.1.2.1     private static Linker linker = null;
 129 vivien   1.1.2.1 
 130 vivien   1.1.2.1     // use the inter-thread analysis
 131 vivien   1.1.2.1     private boolean USE_INTER_THREAD = false;
 132 vivien   1.1.2.1     private boolean DO_STACK_ALLOCATION  = false;
 133 vivien   1.1.2.1     private boolean DO_THREAD_ALLOCATION = false;
 134 vivien   1.1.2.1     private boolean GEN_SYNC_FLAG        = false;
 135 vivien   1.1.2.1     public static boolean SYNC_ELIM        = false;
 136 vivien   1.1.2.1     public static boolean MEM_OPTIMIZATION = true;
 137 vivien   1.1.2.1     
 138 vivien   1.1.2.1         /** Creates a <code>ODMAInfo</code>. */
 139 vivien   1.1.2.1     public ODMAInfo(ODPointerAnalysis pa, HCodeFactory hcf,
 140 vivien   1.1.2.1                     Set mms, boolean USE_INTER_THREAD,
 141 vivien   1.1.2.1                     boolean DO_STACK_ALLOCATION,
 142 vivien   1.1.2.1                     boolean DO_THREAD_ALLOCATION,
 143 vivien   1.1.2.1                     boolean GEN_SYNC_FLAG){
 144 vivien   1.1.2.1         this.pa  = pa;
 145 vivien   1.1.2.1         this.mcg = pa.getMetaCallGraph();
 146 vivien   1.1.2.1         this.mac = pa.getMetaAllCallers();
 147 vivien   1.1.2.1         this.hcf = hcf;
 148 vivien   1.1.2.1         this.mms = mms;
 149 vivien   1.1.2.1         this.node_rep = pa.getNodeRepository();
 150 vivien   1.1.2.1         this.USE_INTER_THREAD = USE_INTER_THREAD;
 151 vivien   1.1.2.1         this.DO_PREALLOCATION = USE_INTER_THREAD;
 152 vivien   1.1.2.1         this.DO_STACK_ALLOCATION  = DO_STACK_ALLOCATION;
 153 vivien   1.1.2.1         this.DO_THREAD_ALLOCATION = DO_THREAD_ALLOCATION;
 154 vivien   1.1.2.1         this.GEN_SYNC_FLAG        = GEN_SYNC_FLAG;
 155 vivien   1.1.2.1 
 156 vivien   1.1.2.1         if(mms.size()==0)
 157 vivien   1.1.2.1             linker = null;
 158 vivien   1.1.2.1         else{
 159 vivien   1.1.2.1             Iterator it = mms.iterator();
 160 vivien   1.1.2.1             MetaMethod mm = (MetaMethod) it.next();
 161 vivien   1.1.2.1             linker = mm.getHMethod().getDeclaringClass().getLinker();
 162 vivien   1.1.2.1         }
 163 vivien   1.1.2.1 
 164 vivien   1.1.2.1         initialize_good_holes();
 165 vivien   1.1.2.1         java_lang_Thread = linker.forName("java.lang.Thread");
 166 vivien   1.1.2.1         java_lang_Throwable = linker.forName("java.lang.Throwable");
 167 vivien   1.1.2.1 
 168 vivien   1.1.2.1 
 169 vivien   1.1.2.1         if(!ODPointerAnalysis.ON_DEMAND_ANALYSIS)
 170 vivien   1.1.2.1             analyze();
 171 vivien   1.1.2.1         
 172 vivien   1.1.2.1         this.MAX_LEVEL_BOTTOM_MODE = ODPointerAnalysis.MAX_ANALYSIS_ABOVE_SPEC;
 173 vivien   1.1.2.1 
 174 vivien   1.1.2.1         if(DO_METHOD_INLINING)
 175 vivien   1.1.2.1             this.ih = new HashMap();
 176 vivien   1.1.2.1         // the nullify part was moved to prepareForSerialization
 177 vivien   1.1.2.1     }
 178 vivien   1.1.2.1 
 179 vivien   1.1.2.1     /** Nullifies some stuff to make the serialization possible. 
 180 vivien   1.1.2.1         This method <b>MUST</b> be called before serializing <code>this</code>
 181 vivien   1.1.2.1         object. */
 182 vivien   1.1.2.1     public void prepareForSerialization(){
 183 vivien   1.1.2.1         this.pa  = null;
 184 vivien   1.1.2.1         this.hcf = null;
 185 vivien   1.1.2.1         this.mms = null;
 186 vivien   1.1.2.1         this.mcg = null;
 187 vivien   1.1.2.1         this.mac = null;
 188 vivien   1.1.2.1         this.node_rep = null;
 189 vivien   1.1.2.1     }
 190 vivien   1.1.2.1 
 191 vivien   1.1.2.1     // Map<NEW, AllocationProperties>
 192 vivien   1.1.2.1     private final Map aps = new HashMap();
 193 vivien   1.1.2.1     
 194 vivien   1.1.2.1     /** Returns the allocation policy for <code>allocationSite</code>. */
 195 vivien   1.1.2.1     public AllocationInformation.AllocationProperties query
 196 vivien   1.1.2.1         (HCodeElement allocationSite){
 197 vivien   1.1.2.1         
 198 vivien   1.1.2.1         AllocationInformation.AllocationProperties ap = 
 199 vivien   1.1.2.1             (AllocationInformation.AllocationProperties)
 200 vivien   1.1.2.1             aps.get(allocationSite);
 201 vivien   1.1.2.1 
 202 vivien   1.1.2.1         if(ap != null)
 203 vivien   1.1.2.1             return ap;
 204 vivien   1.1.2.1 
 205 vivien   1.1.2.1         // conservative allocation property: on the global heap
 206 vivien   1.1.2.1         // (by default).
 207 vivien   1.1.2.1         return new MyAP(getAllocatedType(allocationSite));
 208 vivien   1.1.2.1     }
 209 vivien   1.1.2.1 
 210 vivien   1.1.2.1     // map to store the inline hints:
 211 vivien   1.1.2.1     //  CALL to be inlined -> array of (A)NEWs that can be stack allocated
 212 vivien   1.1.2.1     private Map ih = null;
 213 vivien   1.1.2.1 
 214 vivien   1.1.2.1     // analyze all the methods
 215 vivien   1.1.2.1     public void analyze(){
 216 vivien   1.1.2.1         if(DO_METHOD_INLINING)
 217 vivien   1.1.2.1             ih = new HashMap();
 218 vivien   1.1.2.1 
 219 cananian 1.9             for(Object mmO : mms){
 220 cananian 1.9                 MetaMethod mm = (MetaMethod) mmO;
 221 vivien   1.1.2.1             if(pa.analyzable(mm.getHMethod()))
 222 vivien   1.1.2.1                 analyze_mm(mm);
 223 vivien   1.1.2.1         }
 224 vivien   1.1.2.1 
 225 vivien   1.1.2.1         if(DO_METHOD_INLINING) {
 226 vivien   1.1.2.1             do_the_inlining(hcf, ih);
 227 vivien   1.1.2.1             ih = null; // allow some GC
 228 vivien   1.1.2.1         }
 229 vivien   1.1.2.1     }
 230 vivien   1.1.2.1 
 231 vivien   1.1.2.1 
 232 vivien   1.1.2.1     // get the type of the object allocated by the object creation site hce;
 233 vivien   1.1.2.1     // hce should be NEW or ANEW.
 234 vivien   1.1.2.1     public HClass getAllocatedType(final HCodeElement hce){
 235 vivien   1.1.2.1         if(hce instanceof NEW)
 236 vivien   1.1.2.1             return ((NEW) hce).hclass();
 237 vivien   1.1.2.1         if(hce instanceof ANEW)
 238 vivien   1.1.2.1             return ((ANEW) hce).hclass();
 239 cananian 1.3.2.1         assert false : ("Not a NEW or ANEW: " + hce);
 240 vivien   1.1.2.1         return null; // should never happen
 241 vivien   1.1.2.1     }
 242 vivien   1.1.2.1 
 243 vivien   1.1.2.1     /* Analyze a single method: take the object creation sites from it
 244 vivien   1.1.2.1        and generate an allocation policy for each one. */
 245 vivien   1.1.2.1     public final void analyze_mm(MetaMethod mm){
 246 vivien   1.1.2.1         HMethod hm  = mm.getHMethod();
 247 vivien   1.1.2.1 
 248 vivien   1.1.2.1         if(DEBUG)
 249 vivien   1.1.2.1             System.out.println("\n\nODMAInfo: Analyzed Meta-Method: " + mm);
 250 vivien   1.1.2.1 
 251 vivien   1.1.2.1         HCode hcode = hcf.convert(hm);
 252 vivien   1.1.2.1 
 253 vivien   1.1.2.1         ODParIntGraph initial_pig = pa.getIntParIntGraph(mm,true);
 254 vivien   1.1.2.1         ////        USE_INTER_THREAD ? pa.threadInteraction(mm): 
 255 vivien   1.1.2.1         ////                       pa.getIntParIntGraph(mm);
 256 vivien   1.1.2.1         
 257 vivien   1.1.2.1 //tbu   ODParIntGraph pig = (ODParIntGraph) initial_pig.clone();
 258 vivien   1.1.2.1         ODParIntGraph pig = initial_pig;
 259 vivien   1.1.2.1         if(pig == null) return;
 260 vivien   1.1.2.1         pig.G.flushCaches();
 261 vivien   1.1.2.1         pig.G.e.removeMethodHoles(good_holes);
 262 vivien   1.1.2.1 
 263 vivien   1.1.2.1         if(DEBUG)
 264 vivien   1.1.2.1             System.out.println("Parallel Interaction Graph:" + pig);
 265 vivien   1.1.2.1 
 266 vivien   1.1.2.1         ((harpoon.IR.Quads.Code) hcode).setAllocationInformation(this);
 267 vivien   1.1.2.1 
 268 vivien   1.1.2.1         Set news = new HashSet();
 269 vivien   1.1.2.1 
 270 vivien   1.1.2.1         for(Iterator it = hcode.getElementsI(); it.hasNext(); ){
 271 vivien   1.1.2.1             HCodeElement hce = (HCodeElement) it.next();
 272 vivien   1.1.2.1             if((hce instanceof NEW) || (hce instanceof ANEW)){
 273 vivien   1.1.2.1                 news.add(hce);
 274 vivien   1.1.2.1                 MyAP ap = getAPObj((Quad) hce);
 275 vivien   1.1.2.1                 HClass hclass = getAllocatedType(hce);
 276 vivien   1.1.2.1                 ap.hip = 
 277 vivien   1.1.2.1                     DefaultAllocationInformation.hasInteriorPointers(hclass);
 278 vivien   1.1.2.1             }
 279 vivien   1.1.2.1         }
 280 vivien   1.1.2.1 
 281 vivien   1.1.2.1         Set nodes = pig.allNodes();
 282 vivien   1.1.2.1         HClass excp_class = 
 283 vivien   1.1.2.1             linker.forName("java.lang.Exception");
 284 vivien   1.1.2.1 
 285 cananian 1.9             for(Object nodeO : nodes) {
 286 cananian 1.9                 PANode node = (PANode) nodeO;
 287 vivien   1.1.2.1             if(node.type != PANode.INSIDE) continue;
 288 vivien   1.1.2.1             GenType[] types = node.getPossibleClasses();
 289 vivien   1.1.2.1             boolean isExcp = false;
 290 vivien   1.1.2.1             if(types==null){
 291 vivien   1.1.2.1 //              node2Code(node);
 292 vivien   1.1.2.1                 isExcp = true;
 293 vivien   1.1.2.1             }
 294 vivien   1.1.2.1             else {
 295 vivien   1.1.2.1                 for(int i=0; (i<types.length)&&(!isExcp); i++){
 296 vivien   1.1.2.1                     if (excp_class.isSuperclassOf(types[i].getHClass()))
 297 vivien   1.1.2.1                         isExcp = true;
 298 vivien   1.1.2.1                 }
 299 vivien   1.1.2.1             }
 300 vivien   1.1.2.1             if (isExcp)
 301 vivien   1.1.2.1                 continue;
 302 vivien   1.1.2.1 
 303 vivien   1.1.2.1             nStudiedNode++;
 304 vivien   1.1.2.1             if (ODMAInfo.Nodes2Status.get(node)==null){
 305 vivien   1.1.2.1                 ODNodeStatus newstatus = new ODNodeStatus();
 306 vivien   1.1.2.1                 newstatus.node = node;
 307 vivien   1.1.2.1                 ODMAInfo.Nodes2Status.put(node, newstatus);
 308 vivien   1.1.2.1             }
 309 vivien   1.1.2.1             else {
 310 vivien   1.1.2.1                 System.err.println("Processing twice a node... ??? " + node);
 311 vivien   1.1.2.1             }
 312 vivien   1.1.2.1             ODNodeStatus status = (ODNodeStatus) Nodes2Status.get(node);
 313 vivien   1.1.2.1 
 314 vivien   1.1.2.1 
 315 vivien   1.1.2.1             // we are interested in objects allocated in the current thread
 316 vivien   1.1.2.1             if(node.isTSpec()) continue;
 317 vivien   1.1.2.1             
 318 vivien   1.1.2.1             int depth = node.getCallChainDepth();
 319 vivien   1.1.2.1             System.out.println("CallChainDepth = " + depth); 
 320 vivien   1.1.2.1             if (depth!=0) continue;
 321 vivien   1.1.2.1 
 322 vivien   1.1.2.1             //FV This test has to be changed
 323 vivien   1.1.2.1             boolean iscaptured = captured(pig, mm, node);
 324 vivien   1.1.2.1             pig = pa.getIntParIntGraph(mm);
 325 vivien   1.1.2.1 
 326 vivien   1.1.2.1 //          if(iscaptured)
 327 vivien   1.1.2.1 //              System.out.println("--captured " + node + " in " + mm + pig);
 328 vivien   1.1.2.1 //          else
 329 vivien   1.1.2.1 //              System.out.println("--escaping " + node + " in " + mm + pig);
 330 vivien   1.1.2.1 
 331 vivien   1.1.2.1             //      if(pig.G.captured(node)){
 332 vivien   1.1.2.1             if(iscaptured){
 333 vivien   1.1.2.1                 if((depth == 0) 
 334 vivien   1.1.2.1                    /* && news.contains(node_rep.node2Code(node)) */ ) {
 335 vivien   1.1.2.1                     // captured nodes of depth 0 (ie allocated in this method,
 336 vivien   1.1.2.1                     // not in a callee) are allocated on the stack.
 337 vivien   1.1.2.1                     Quad q  = (Quad) node_rep.node2Code(node);
 338 cananian 1.3.2.1                     assert q != null : "No quad for " + node;
 339 vivien   1.1.2.1 
 340 vivien   1.1.2.1                     if(stack_alloc_extra_cond(node, q)) {
 341 vivien   1.1.2.1                         MyAP ap = getAPObj(q);
 342 vivien   1.1.2.1                         if (ODMAInfo.MEM_OPTIMIZATION)
 343 vivien   1.1.2.1                             ap.sa = true;
 344 vivien   1.1.2.1                         else
 345 vivien   1.1.2.1                             ap.sa = false;
 346 vivien   1.1.2.1                         if (ODMAInfo.SYNC_ELIM)
 347 vivien   1.1.2.1                             ap.ns = true;
 348 vivien   1.1.2.1                         else
 349 vivien   1.1.2.1                             ap.ns = false;
 350 vivien   1.1.2.1 //                      if(DEBUG)
 351 vivien   1.1.2.1                             System.out.println("STACK: " +
 352 vivien   1.1.2.1                                                " was stack allocated " +
 353 salcianu 1.5                                                    Util.getLine(q) + " " + node);
 354 vivien   1.1.2.1                         status.onStack = true;
 355 vivien   1.1.2.1                     }
 356 vivien   1.1.2.1                 }
 357 vivien   1.1.2.1             }
 358 vivien   1.1.2.1             else {
 359 vivien   1.1.2.1                 if((depth == 0)
 360 vivien   1.1.2.1                    /* && news.contains(node_rep.node2Code(node)) */ ) {
 361 vivien   1.1.2.1                     if(remainInThread(node, hm, "")) {
 362 vivien   1.1.2.1                         System.out.println("node remainInThread");
 363 vivien   1.1.2.1                         Quad q = (Quad) node_rep.node2Code(node);
 364 cananian 1.3.2.1                         assert q != null : "No quad for " + node;
 365 vivien   1.1.2.1 
 366 vivien   1.1.2.1                         MyAP ap = getAPObj(q);
 367 vivien   1.1.2.1                         if (ODMAInfo.MEM_OPTIMIZATION)
 368 vivien   1.1.2.1                             ap.ta = true; // thread allocation
 369 vivien   1.1.2.1 //                          ap.ta = false;
 370 vivien   1.1.2.1                         else
 371 vivien   1.1.2.1                             ap.ta = false;
 372 vivien   1.1.2.1                         ap.ah = null; // on the current heap
 373 vivien   1.1.2.1                         if (ODMAInfo.SYNC_ELIM)
 374 vivien   1.1.2.1                             ap.ns = true;
 375 vivien   1.1.2.1                         else
 376 vivien   1.1.2.1                             ap.ns = false;
 377 vivien   1.1.2.1                         status.onLocalHeap = true;
 378 vivien   1.1.2.1                                
 379 vivien   1.1.2.1 
 380 vivien   1.1.2.1                         //if(DEBUG)
 381 vivien   1.1.2.1                            {
 382 vivien   1.1.2.1                                System.out.print("THREAD:  was thread allocated " +
 383 salcianu 1.5                                                    Util.getLine(q) + " " + node);
 384 vivien   1.1.2.1                                if (pig.G.excp.contains(node))
 385 vivien   1.1.2.1                                    System.out.println(" (returned as exception)");
 386 vivien   1.1.2.1                                else
 387 vivien   1.1.2.1                                    System.out.println(" ()");
 388 vivien   1.1.2.1                                System.out.println("Analyzed Meta-Method: " + mm);
 389 vivien   1.1.2.1                            }
 390 vivien   1.1.2.1                     }
 391 vivien   1.1.2.1                     else{
 392 vivien   1.1.2.1                         Quad q = (Quad) node_rep.node2Code(node);
 393 salcianu 1.5                             System.out.print("node escapes of Thread " + Util.getLine(q) + ".");
 394 vivien   1.1.2.1                         if (pig.G.excp.contains(node))
 395 vivien   1.1.2.1                             System.out.println(" (returned as exception)");
 396 vivien   1.1.2.1                         else
 397 vivien   1.1.2.1                             System.out.println(" ()");
 398 vivien   1.1.2.1                     }
 399 vivien   1.1.2.1                 }
 400 vivien   1.1.2.1                 else {
 401 vivien   1.1.2.1                     System.out.println("Depth != 0 (" + depth + ")");
 402 vivien   1.1.2.1                 }
 403 vivien   1.1.2.1             }
 404 vivien   1.1.2.1         }
 405 vivien   1.1.2.1         
 406 vivien   1.1.2.1         PAThreadMap tau = (PAThreadMap) (pa.getIntParIntGraph(mm).tau.clone());
 407 vivien   1.1.2.1 
 408 vivien   1.1.2.1         if(DO_PREALLOCATION && (tau.activeThreadSet().size() == 1))
 409 vivien   1.1.2.1             analyze_prealloc(mm, hcode, pig, tau);
 410 vivien   1.1.2.1 
 411 vivien   1.1.2.1         /// DUMMY CODE: we don't have NSTK_malloc_with_heap yet
 412 vivien   1.1.2.1         if(!NO_TG)
 413 vivien   1.1.2.1             set_make_heap(tau.activeThreadSet());
 414 vivien   1.1.2.1 
 415 vivien   1.1.2.1         /// DUMMY CODE: Stack allocate ALL the threads
 416 vivien   1.1.2.1         if(NO_TG) {
 417 vivien   1.1.2.1             Set set = getLevel0InsideNodes(pig);
 418 cananian 1.9                 for(Object nodeO : set) {
 419 cananian 1.9                     PANode node = (PANode) nodeO;
 420 vivien   1.1.2.1                 Quad q = (Quad) node_rep.node2Code(node);
 421 vivien   1.1.2.1                 if(q == null) {
 422 vivien   1.1.2.1                     System.out.println("BELL: " + node + " " + q);
 423 vivien   1.1.2.1                     continue;
 424 vivien   1.1.2.1                 }
 425 vivien   1.1.2.1                 if(thread_on_stack(node, q)) {
 426 vivien   1.1.2.1                     MyAP ap = getAPObj(q);
 427 vivien   1.1.2.1                     if (ODMAInfo.MEM_OPTIMIZATION){
 428 vivien   1.1.2.1                         ap.sa = true;
 429 vivien   1.1.2.1                         ap.ta = false;
 430 vivien   1.1.2.1                     }
 431 vivien   1.1.2.1                     else{
 432 vivien   1.1.2.1                         ap.sa = false;
 433 vivien   1.1.2.1                         ap.ta = false;
 434 vivien   1.1.2.1                     }
 435 vivien   1.1.2.1                     if (ODMAInfo.SYNC_ELIM)
 436 vivien   1.1.2.1                         ap.ns = true;
 437 vivien   1.1.2.1                     else
 438 vivien   1.1.2.1                         ap.ns = false;
 439 vivien   1.1.2.1 
 440 vivien   1.1.2.1                 }
 441 vivien   1.1.2.1             }
 442 vivien   1.1.2.1         }
 443 vivien   1.1.2.1 
 444 vivien   1.1.2.1         if(DO_METHOD_INLINING)
 445 vivien   1.1.2.1             generate_inlining_hints(mm, pig);
 446 vivien   1.1.2.1     }
 447 vivien   1.1.2.1 
 448 vivien   1.1.2.1     public final void analyze_mm(MetaMethod mm, Set nodes){
 449 vivien   1.1.2.1         HMethod hm  = mm.getHMethod();
 450 vivien   1.1.2.1 
 451 vivien   1.1.2.1         if(DEBUG)
 452 vivien   1.1.2.1             System.out.println("\n\nODMAInfo: Analyzed Meta-Method: " + mm);
 453 vivien   1.1.2.1 
 454 vivien   1.1.2.1         System.out.println("MEM_OPTIMIZATION = " + ODMAInfo.MEM_OPTIMIZATION);
 455 vivien   1.1.2.1         System.out.println("SYNC_ELIM = " + SYNC_ELIM);
 456 vivien   1.1.2.1 
 457 vivien   1.1.2.1         HCode hcode = hcf.convert(hm);
 458 vivien   1.1.2.1         if(hcode == null) return;
 459 vivien   1.1.2.1 
 460 vivien   1.1.2.1         ((harpoon.IR.Quads.Code) hcode).setAllocationInformation(this);
 461 vivien   1.1.2.1         System.out.println("WOW: ai set for " + hm);
 462 vivien   1.1.2.1         AllocationInformation ai = ((harpoon.IR.Quads.Code) hcode).getAllocationInformation();
 463 vivien   1.1.2.1 //      System.out.println("0. " + (ai==null?
 464 vivien   1.1.2.1 //                         (hm + " baaad!") :
 465 vivien   1.1.2.1 //                         (hm + " good!")));
 466 vivien   1.1.2.1 
 467 vivien   1.1.2.1 //      System.out.println("\nB4 getIntParIntGraph");
 468 vivien   1.1.2.1         ODParIntGraph initial_pig = pa.getIntParIntGraph(mm,true);
 469 vivien   1.1.2.1 //      System.out.println("AFTER getIntParIntGraph\n");
 470 vivien   1.1.2.1         ////        USE_INTER_THREAD ? pa.threadInteraction(mm): 
 471 vivien   1.1.2.1         ////                       pa.getIntParIntGraph(mm);
 472 vivien   1.1.2.1         
 473 vivien   1.1.2.1 //tbu   ODParIntGraph pig = (ODParIntGraph) initial_pig.clone();
 474 vivien   1.1.2.1         ODParIntGraph pig = initial_pig;
 475 vivien   1.1.2.1         if(pig == null) return;
 476 vivien   1.1.2.1         pig.G.flushCaches();
 477 vivien   1.1.2.1         pig.G.e.removeMethodHoles(good_holes);
 478 vivien   1.1.2.1 
 479 vivien   1.1.2.1         if(DEBUG)
 480 vivien   1.1.2.1             System.out.println("Parallel Interaction Graph:" + pig);
 481 vivien   1.1.2.1 
 482 vivien   1.1.2.1         Set news = new HashSet();
 483 vivien   1.1.2.1 
 484 vivien   1.1.2.1         for(Iterator it = hcode.getElementsI(); it.hasNext(); ){
 485 vivien   1.1.2.1             HCodeElement hce = (HCodeElement) it.next();
 486 vivien   1.1.2.1             if((hce instanceof NEW) || (hce instanceof ANEW)){
 487 vivien   1.1.2.1                 news.add(hce);
 488 vivien   1.1.2.1                 MyAP ap = getAPObj((Quad) hce);
 489 vivien   1.1.2.1                 HClass hclass = getAllocatedType(hce);
 490 vivien   1.1.2.1                 ap.hip = 
 491 vivien   1.1.2.1                     DefaultAllocationInformation.hasInteriorPointers(hclass);
 492 vivien   1.1.2.1             }
 493 vivien   1.1.2.1         }
 494 vivien   1.1.2.1 
 495 cananian 1.9             for(Object nodeO : nodes) {
 496 cananian 1.9                 PANode node = (PANode) nodeO;
 497 vivien   1.1.2.1             if(node.type != PANode.INSIDE) continue;
 498 vivien   1.1.2.1 
 499 vivien   1.1.2.1             if (ODMAInfo.Nodes2Status.get(node)==null){
 500 vivien   1.1.2.1                 ODMAInfo.Nodes2Status.put(node,new ODNodeStatus());
 501 vivien   1.1.2.1             }
 502 vivien   1.1.2.1             else {
 503 vivien   1.1.2.1                 System.err.println("Processing twice a node... ??? " + node);
 504 vivien   1.1.2.1             }
 505 vivien   1.1.2.1 //          ODMAInfo.Nodes2Status.put(node,new Integer(3));
 506 vivien   1.1.2.1             ODNodeStatus status = (ODNodeStatus) Nodes2Status.get(node);
 507 vivien   1.1.2.1 
 508 vivien   1.1.2.1             // we are interested in objects allocated in the current thread
 509 vivien   1.1.2.1             if(node.isTSpec()) continue;
 510 vivien   1.1.2.1             
 511 vivien   1.1.2.1             int depth = node.getCallChainDepth();
 512 vivien   1.1.2.1             System.out.println("CallChainDepth = " + depth); 
 513 vivien   1.1.2.1             if (depth!=0) continue;
 514 vivien   1.1.2.1 
 515 vivien   1.1.2.1             //FV This test has to be changed
 516 vivien   1.1.2.1             boolean iscaptured = captured(pig, mm, node);
 517 vivien   1.1.2.1             pig = pa.getIntParIntGraph(mm);
 518 vivien   1.1.2.1 
 519 vivien   1.1.2.1 //          if(iscaptured)
 520 vivien   1.1.2.1 //              System.out.println("--captured " + node + " in " + mm + pig);
 521 vivien   1.1.2.1 //          else
 522 vivien   1.1.2.1 //              System.out.println("--escaping " + node + " in " + mm + pig);
 523 vivien   1.1.2.1 
 524 vivien   1.1.2.1             //      if(pig.G.captured(node)){
 525 vivien   1.1.2.1             if(iscaptured){
 526 vivien   1.1.2.1                 if((depth == 0) 
 527 vivien   1.1.2.1                    /* && news.contains(node_rep.node2Code(node)) */ ) {
 528 vivien   1.1.2.1                     // captured nodes of depth 0 (ie allocated in this method,
 529 vivien   1.1.2.1                     // not in a callee) are allocated on the stack.
 530 vivien   1.1.2.1                     Quad q  = (Quad) node_rep.node2Code(node);
 531 cananian 1.3.2.1                     assert q != null : "No quad for " + node;
 532 vivien   1.1.2.1 
 533 vivien   1.1.2.1                     if(stack_alloc_extra_cond(node, q)) {
 534 vivien   1.1.2.1                         MyAP ap = getAPObj(q);
 535 vivien   1.1.2.1                         if (ODMAInfo.MEM_OPTIMIZATION){
 536 vivien   1.1.2.1                             ap.sa = true;
 537 vivien   1.1.2.1                             ap.ta = false;
 538 vivien   1.1.2.1                         }
 539 vivien   1.1.2.1                         else{
 540 vivien   1.1.2.1                             ap.sa = false;
 541 vivien   1.1.2.1                             ap.ta = false;
 542 vivien   1.1.2.1                         }
 543 vivien   1.1.2.1                         if (ODMAInfo.SYNC_ELIM)
 544 vivien   1.1.2.1                             ap.ns = true;
 545 vivien   1.1.2.1                         else
 546 vivien   1.1.2.1                             ap.ns = false;
 547 vivien   1.1.2.1 //                      if(DEBUG)
 548 vivien   1.1.2.1                             System.out.println("STACK: " + 
 549 vivien   1.1.2.1                                                " was stack allocated " +
 550 salcianu 1.5                                                    Util.getLine(q)  +  " " + node );
 551 vivien   1.1.2.1                         status.onStack = true;
 552 vivien   1.1.2.1 //                      ODMAInfo.Nodes2Status.put(node,new Integer(1));
 553 vivien   1.1.2.1                     }
 554 vivien   1.1.2.1                 }
 555 vivien   1.1.2.1             }
 556 vivien   1.1.2.1             else {
 557 vivien   1.1.2.1                 if((depth == 0)
 558 vivien   1.1.2.1                    /* && news.contains(node_rep.node2Code(node)) */ ) {
 559 vivien   1.1.2.1                     if(remainInThread(node, hm, "")) {
 560 vivien   1.1.2.1                         System.out.println("node remainInThread");
 561 vivien   1.1.2.1                         Quad q = (Quad) node_rep.node2Code(node);
 562 cananian 1.3.2.1                         assert q != null : "No quad for " + node;
 563 vivien   1.1.2.1 
 564 vivien   1.1.2.1                         MyAP ap = getAPObj(q);
 565 vivien   1.1.2.1                         if (ODMAInfo.MEM_OPTIMIZATION){
 566 vivien   1.1.2.1                             ap.sa = false;
 567 vivien   1.1.2.1 //                          ap.ta = false;
 568 vivien   1.1.2.1                             ap.ta = true;
 569 vivien   1.1.2.1                             ap.ah = null; // on the current heap
 570 vivien   1.1.2.1                         }
 571 vivien   1.1.2.1                         else{
 572 vivien   1.1.2.1                             ap.sa = false;
 573 vivien   1.1.2.1                             ap.ta = false;
 574 vivien   1.1.2.1                         }
 575 vivien   1.1.2.1                         if (ODMAInfo.SYNC_ELIM)
 576 vivien   1.1.2.1                             ap.ns = true;
 577 vivien   1.1.2.1                         else
 578 vivien   1.1.2.1                             ap.ns = false;
 579 vivien   1.1.2.1                         status.onLocalHeap = true;
 580 vivien   1.1.2.1 //                      ODMAInfo.Nodes2Status.put(node,new Integer(2));
 581 vivien   1.1.2.1                         //if(DEBUG)
 582 vivien   1.1.2.1                            {
 583 vivien   1.1.2.1                                System.out.print("THREAD: " + " was thread allocated " +
 584 salcianu 1.5                                                    Util.getLine(q) + " " + node );
 585 vivien   1.1.2.1                                if (pig.G.excp.contains(node))
 586 vivien   1.1.2.1                                    System.out.println(" (returned as exception)");
 587 vivien   1.1.2.1                                else
 588 vivien   1.1.2.1                                    System.out.println(" ()");
 589 vivien   1.1.2.1                                System.out.println("Analyzed Meta-Method: " + mm);
 590 vivien   1.1.2.1                            }
 591 vivien   1.1.2.1                     }
 592 vivien   1.1.2.1                     else{
 593 vivien   1.1.2.1                         Quad q = (Quad) node_rep.node2Code(node);
 594 salcianu 1.5                             System.out.print("node escapes of Thread " + Util.getLine(q) 
 595 vivien   1.1.2.1                                          + " " + node);
 596 vivien   1.1.2.1                         if (pig.G.excp.contains(node))
 597 vivien   1.1.2.1                             System.out.println(" (returned as exception)");
 598 vivien   1.1.2.1                         else
 599 vivien   1.1.2.1                             System.out.println(" ()");
 600 vivien   1.1.2.1                     }
 601 vivien   1.1.2.1                 }
 602 vivien   1.1.2.1                 else {
 603 vivien   1.1.2.1                     System.out.println("Depth != 0 (" + depth + ")");
 604 vivien   1.1.2.1                 }
 605 vivien   1.1.2.1             }
 606 vivien   1.1.2.1         }
 607 vivien   1.1.2.1         
 608 vivien   1.1.2.1         PAThreadMap tau = (PAThreadMap) (pa.getIntParIntGraph(mm).tau.clone());
 609 vivien   1.1.2.1 
 610 vivien   1.1.2.1         if(DO_PREALLOCATION && (tau.activeThreadSet().size() == 1))
 611 vivien   1.1.2.1             analyze_prealloc(mm, hcode, pig, tau);
 612 vivien   1.1.2.1 
 613 vivien   1.1.2.1         /// DUMMY CODE: we don't have NSTK_malloc_with_heap yet
 614 vivien   1.1.2.1         if(!NO_TG)
 615 vivien   1.1.2.1             set_make_heap(tau.activeThreadSet());
 616 vivien   1.1.2.1 
 617 vivien   1.1.2.1         /// DUMMY CODE: Stack allocate ALL the threads
 618 vivien   1.1.2.1         if(NO_TG) {
 619 vivien   1.1.2.1             Set set = getLevel0InsideNodes(pig);
 620 cananian 1.9                 for(Object nodeO : set) {
 621 cananian 1.9                     PANode node = (PANode) nodeO;
 622 vivien   1.1.2.1                 Quad q = (Quad) node_rep.node2Code(node);
 623 vivien   1.1.2.1                 if(q == null) {
 624 vivien   1.1.2.1                     System.out.println("BELL: " + node + " " + q);
 625 vivien   1.1.2.1                     continue;
 626 vivien   1.1.2.1                 }
 627 vivien   1.1.2.1                 if(thread_on_stack(node, q)) {
 628 vivien   1.1.2.1                     MyAP ap = getAPObj(q);
 629 vivien   1.1.2.1                     if (ODMAInfo.MEM_OPTIMIZATION){
 630 vivien   1.1.2.1                         ap.sa = true;
 631 vivien   1.1.2.1                         ap.ta = false;
 632 vivien   1.1.2.1                     }
 633 vivien   1.1.2.1                     else{
 634 vivien   1.1.2.1                         ap.sa = false;
 635 vivien   1.1.2.1                         ap.ta = false;
 636 vivien   1.1.2.1                     }
 637 vivien   1.1.2.1                     if (ODMAInfo.SYNC_ELIM)
 638 vivien   1.1.2.1                         ap.ns = true;
 639 vivien   1.1.2.1                     else
 640 vivien   1.1.2.1                         ap.ns = false;
 641 vivien   1.1.2.1                 }
 642 vivien   1.1.2.1             }
 643 vivien   1.1.2.1         }
 644 vivien   1.1.2.1 
 645 vivien   1.1.2.1         if(DO_METHOD_INLINING)
 646 vivien   1.1.2.1             generate_inlining_hints(mm, pig, nodes);
 647 vivien   1.1.2.1     }
 648 vivien   1.1.2.1 
 649 vivien   1.1.2.1     /** Only try to stack allocate the node given as second argument.
 650 vivien   1.1.2.1      */
 651 vivien   1.1.2.1     public final void analyze_mm(MetaMethod mm, PANode node, boolean tryThread){
 652 vivien   1.1.2.1         HMethod hm  = mm.getHMethod();
 653 vivien   1.1.2.1 
 654 vivien   1.1.2.1         if(DEBUG)
 655 vivien   1.1.2.1             System.out.println("\n\nODMAInfo: Analyzed Meta-Method: " + mm);
 656 vivien   1.1.2.1 
 657 vivien   1.1.2.1         System.out.println("MEM_OPTIMIZATION = " + ODMAInfo.MEM_OPTIMIZATION);
 658 vivien   1.1.2.1         System.out.println("SYNC_ELIM = " + SYNC_ELIM);
 659 vivien   1.1.2.1 
 660 vivien   1.1.2.1         HCode hcode = hcf.convert(hm);
 661 vivien   1.1.2.1         if(hcode == null) return;
 662 vivien   1.1.2.1 
 663 vivien   1.1.2.1         ((harpoon.IR.Quads.Code) hcode).setAllocationInformation(this);
 664 vivien   1.1.2.1         System.out.println("WOW: ai set for " + hm);
 665 vivien   1.1.2.1         AllocationInformation ai = ((harpoon.IR.Quads.Code) hcode).getAllocationInformation();
 666 vivien   1.1.2.1 
 667 vivien   1.1.2.1         ODParIntGraph initial_pig = pa.getIntParIntGraph(mm,true);
 668 vivien   1.1.2.1         
 669 vivien   1.1.2.1 //tbu   ODParIntGraph pig = (ODParIntGraph) initial_pig.clone();
 670 vivien   1.1.2.1         ODParIntGraph pig = initial_pig;
 671 vivien   1.1.2.1         if(pig == null) return;
 672 vivien   1.1.2.1         pig.G.flushCaches();
 673 vivien   1.1.2.1         pig.G.e.removeMethodHoles(good_holes);
 674 vivien   1.1.2.1 
 675 vivien   1.1.2.1         if(DEBUG)
 676 vivien   1.1.2.1             System.out.println("Parallel Interaction Graph:" + pig);
 677 vivien   1.1.2.1 
 678 vivien   1.1.2.1         Set news = new HashSet();
 679 vivien   1.1.2.1 
 680 vivien   1.1.2.1         for(Iterator it = hcode.getElementsI(); it.hasNext(); ){
 681 vivien   1.1.2.1             HCodeElement hce = (HCodeElement) it.next();
 682 vivien   1.1.2.1             if((hce instanceof NEW) || (hce instanceof ANEW)){
 683 vivien   1.1.2.1                 news.add(hce);
 684 vivien   1.1.2.1                 MyAP ap = getAPObj((Quad) hce);
 685 vivien   1.1.2.1                 HClass hclass = getAllocatedType(hce);
 686 vivien   1.1.2.1                 ap.hip = 
 687 vivien   1.1.2.1                     DefaultAllocationInformation.hasInteriorPointers(hclass);
 688 vivien   1.1.2.1             }
 689 vivien   1.1.2.1         }
 690 vivien   1.1.2.1 
 691 cananian 1.3.2.1         assert node.type == PANode.INSIDE : "This node should be an inside node" + node;
 692 vivien   1.1.2.1 
 693 vivien   1.1.2.1         if (ODMAInfo.Nodes2Status.get(node)==null){
 694 vivien   1.1.2.1             ODMAInfo.Nodes2Status.put(node,new ODNodeStatus());
 695 vivien   1.1.2.1         }
 696 vivien   1.1.2.1 //      else {
 697 vivien   1.1.2.1 //          System.err.println("Processing twice a node... ??? " + node);
 698 vivien   1.1.2.1 //      }
 699 vivien   1.1.2.1         ODNodeStatus status = (ODNodeStatus) Nodes2Status.get(node);
 700 vivien   1.1.2.1 
 701 vivien   1.1.2.1         // we are interested in objects allocated in the current thread
 702 cananian 1.3.2.1         assert node.isTSpec()==false : "This node should not be a specialization " + node;
 703 vivien   1.1.2.1             
 704 vivien   1.1.2.1         int depth = node.getCallChainDepth();
 705 vivien   1.1.2.1         System.out.println("CallChainDepth = " + depth); 
 706 cananian 1.3.2.1         assert depth==0 : "This node should have be created by the current MetaMethod!";
 707 vivien   1.1.2.1 
 708 vivien   1.1.2.1         boolean iscaptured = captured(pig, mm, node);
 709 vivien   1.1.2.1         pig = pa.getIntParIntGraph(mm);
 710 vivien   1.1.2.1 
 711 vivien   1.1.2.1         if(iscaptured){
 712 vivien   1.1.2.1             // captured nodes of depth 0 (ie allocated in this method,
 713 vivien   1.1.2.1             // not in a callee) are allocated on the stack.
 714 vivien   1.1.2.1             Quad q  = (Quad) node_rep.node2Code(node);
 715 cananian 1.3.2.1             assert q != null : "No quad for " + node;
 716 vivien   1.1.2.1             
 717 vivien   1.1.2.1             if(stack_alloc_extra_cond(node, q)) {
 718 vivien   1.1.2.1                 MyAP ap = getAPObj(q);
 719 vivien   1.1.2.1                 if (ODMAInfo.MEM_OPTIMIZATION){
 720 vivien   1.1.2.1                     ap.sa = true;
 721 vivien   1.1.2.1                     ap.ta = false;
 722 vivien   1.1.2.1                 }
 723 vivien   1.1.2.1                 else{
 724 vivien   1.1.2.1                     ap.sa = false;
 725 vivien   1.1.2.1                     ap.ta = false;
 726 vivien   1.1.2.1                 }
 727 vivien   1.1.2.1                 if (ODMAInfo.SYNC_ELIM)
 728 vivien   1.1.2.1                     ap.ns = true;
 729 vivien   1.1.2.1                 else
 730 vivien   1.1.2.1                     ap.ns = false;
 731 vivien   1.1.2.1                 //                      if(DEBUG)
 732 vivien   1.1.2.1                 System.out.println("STACK: " + 
 733 vivien   1.1.2.1                                    " was stack allocated " +
 734 salcianu 1.5                                        Util.getLine(q)  +  " " + node );
 735 vivien   1.1.2.1                 status.onStack = true;
 736 vivien   1.1.2.1             }
 737 vivien   1.1.2.1         }
 738 vivien   1.1.2.1         else if(tryThread){
 739 vivien   1.1.2.1             if(remainInThread(node, hm, "")) {
 740 vivien   1.1.2.1                 System.out.println("node remainInThread");
 741 vivien   1.1.2.1                 Quad q = (Quad) node_rep.node2Code(node);
 742 cananian 1.3.2.1                 assert q != null : "No quad for " + node;
 743 vivien   1.1.2.1                 
 744 vivien   1.1.2.1                 MyAP ap = getAPObj(q);
 745 vivien   1.1.2.1                 if (ODMAInfo.MEM_OPTIMIZATION){
 746 vivien   1.1.2.1                     ap.sa = false;
 747 vivien   1.1.2.1                     ap.ta = true;
 748 vivien   1.1.2.1                     ap.ah = null; // on the current heap
 749 vivien   1.1.2.1                 }
 750 vivien   1.1.2.1                 else{
 751 vivien   1.1.2.1                     ap.sa = false;
 752 vivien   1.1.2.1                     ap.ta = false;
 753 vivien   1.1.2.1                 }
 754 vivien   1.1.2.1                 if (ODMAInfo.SYNC_ELIM)
 755 vivien   1.1.2.1                     ap.ns = true;
 756 vivien   1.1.2.1                 else
 757 vivien   1.1.2.1                     ap.ns = false;
 758 vivien   1.1.2.1                 status.onLocalHeap = true;
 759 vivien   1.1.2.1 
 760 vivien   1.1.2.1                 if(DEBUG)
 761 vivien   1.1.2.1                     {
 762 vivien   1.1.2.1                         System.out.print("THREAD: " + " was thread allocated " +
 763 salcianu 1.5                                              Util.getLine(q) + " " + node );
 764 vivien   1.1.2.1                         if (pig.G.excp.contains(node))
 765 vivien   1.1.2.1                             System.out.println(" (returned as exception)");
 766 vivien   1.1.2.1                         else
 767 vivien   1.1.2.1                             System.out.println(" ()");
 768 vivien   1.1.2.1                         System.out.println("Analyzed Meta-Method: " + mm);
 769 vivien   1.1.2.1                     }
 770 vivien   1.1.2.1             }
 771 vivien   1.1.2.1             else{
 772 vivien   1.1.2.1                 Quad q = (Quad) node_rep.node2Code(node);
 773 salcianu 1.5                     System.out.print("node escapes of Thread " + Util.getLine(q) 
 774 vivien   1.1.2.1                                  + " " + node);
 775 vivien   1.1.2.1                 if (pig.G.excp.contains(node))
 776 vivien   1.1.2.1                     System.out.println(" (returned as exception)");
 777 vivien   1.1.2.1                 else
 778 vivien   1.1.2.1                     System.out.println(" ()");
 779 vivien   1.1.2.1             }
 780 vivien   1.1.2.1         }
 781 vivien   1.1.2.1         
 782 vivien   1.1.2.1         PAThreadMap tau = (PAThreadMap) (pa.getIntParIntGraph(mm).tau.clone());
 783 vivien   1.1.2.1 
 784 vivien   1.1.2.1         if(DO_PREALLOCATION && (tau.activeThreadSet().size() == 1))
 785 vivien   1.1.2.1             analyze_prealloc(mm, hcode, pig, tau);
 786 vivien   1.1.2.1 
 787 vivien   1.1.2.1         set_make_heap(tau.activeThreadSet());
 788 vivien   1.1.2.1     }
 789 vivien   1.1.2.1 
 790 vivien   1.1.2.1     // Returns the INSIDE nodes of level 0 from pig.
 791 vivien   1.1.2.1     private Set getLevel0InsideNodes(ODParIntGraph pig) {
 792 vivien   1.1.2.1         final Set retval = new HashSet();
 793 vivien   1.1.2.1         pig.forAllNodes(new PANodeVisitor() {
 794 vivien   1.1.2.1                 public void visit(PANode node) {
 795 vivien   1.1.2.1                     if((node.type == PANode.INSIDE) &&
 796 vivien   1.1.2.1                        !(node.isTSpec()) &&
 797 vivien   1.1.2.1                        (node.getCallChainDepth() == 0))
 798 vivien   1.1.2.1                         retval.add(node);
 799 vivien   1.1.2.1                 }
 800 vivien   1.1.2.1             });
 801 vivien   1.1.2.1         retval.remove(ActionRepository.THIS_THREAD);
 802 vivien   1.1.2.1         return retval;
 803 vivien   1.1.2.1     }
 804 vivien   1.1.2.1 
 805 vivien   1.1.2.1     /** Set the allocation policy info such that each of the threads allocated
 806 vivien   1.1.2.1         and started into the currently analyzed method has a thread specific
 807 vivien   1.1.2.1         heap associated with it. */
 808 vivien   1.1.2.1     private void set_make_heap(Set threads){
 809 cananian 1.9             for(Object ntO : threads) {
 810 cananian 1.9                 PANode nt = (PANode) ntO;
 811 vivien   1.1.2.1             if((nt.type != PANode.INSIDE) || 
 812 vivien   1.1.2.1                (nt.getCallChainDepth() != 0) ||
 813 vivien   1.1.2.1                (nt.isTSpec())) continue;
 814 vivien   1.1.2.1 
 815 vivien   1.1.2.1             NEW qnt = (NEW) node_rep.node2Code(nt);
 816 vivien   1.1.2.1             MyAP ap = getAPObj(qnt);
 817 vivien   1.1.2.1             ap.mh = true;
 818 vivien   1.1.2.1         }
 819 vivien   1.1.2.1     }
 820 vivien   1.1.2.1 
 821 vivien   1.1.2.1 
 822 vivien   1.1.2.1     // checks whether node escapes only in some method. We assume that
 823 vivien   1.1.2.1     // no method hole starts a new thread and so, we can allocate
 824 vivien   1.1.2.1     // the onject on the thread specific heap
 825 vivien   1.1.2.1     private boolean escapes_only_in_methods(PANode node, ODParIntGraph pig){
 826 vivien   1.1.2.1         if(!pig.G.e.nodeHolesSet(node).isEmpty())
 827 vivien   1.1.2.1             return false;
 828 vivien   1.1.2.1         if(pig.G.getReachableFromR().contains(node))
 829 vivien   1.1.2.1             return false;
 830 vivien   1.1.2.1         if(pig.G.getReachableFromExcp().contains(node))
 831 vivien   1.1.2.1             return false;
 832 vivien   1.1.2.1         
 833 vivien   1.1.2.1         return true;
 834 vivien   1.1.2.1     }
 835 vivien   1.1.2.1 
 836 vivien   1.1.2.1     // hope that this evil string really doesn't exist anywhere else
 837 vivien   1.1.2.1     private static String my_scope = "pa!";
 838 vivien   1.1.2.1     private static final TempFactory 
 839 vivien   1.1.2.1         temp_factory = Temp.tempFactory(my_scope);
 840 vivien   1.1.2.1 
 841 vivien   1.1.2.1     // try to apply some aggressive preallocation into the thread specific
 842 vivien   1.1.2.1     // heap.
 843 vivien   1.1.2.1     private void analyze_prealloc(MetaMethod mm, HCode hcode, ODParIntGraph pig,
 844 vivien   1.1.2.1                                   PAThreadMap tau){
 845 vivien   1.1.2.1 
 846 vivien   1.1.2.1         Set active_threads = tau.activeThreadSet();
 847 vivien   1.1.2.1         PANode nt = (PANode) (active_threads.iterator().next());
 848 vivien   1.1.2.1 
 849 vivien   1.1.2.1         // protect against some patological cases
 850 vivien   1.1.2.1         if((nt.type != PANode.INSIDE) || 
 851 vivien   1.1.2.1            (nt.getCallChainDepth() != 0) ||
 852 vivien   1.1.2.1            (nt.isTSpec()) ||
 853 vivien   1.1.2.1            (tau.getValue(nt) != 1))
 854 vivien   1.1.2.1             return;
 855 vivien   1.1.2.1 
 856 vivien   1.1.2.1         // pray that no thread is allocated through an ANEW!
 857 vivien   1.1.2.1         // (it seems quite a reasonable assumption)
 858 vivien   1.1.2.1         NEW qnt = (NEW) node_rep.node2Code(nt);
 859 vivien   1.1.2.1 
 860 vivien   1.1.2.1         // compute the nodes pointed to by the thread node at the moment of 
 861 vivien   1.1.2.1         // the "start()" call. Since we analyze only "good" programs (we
 862 vivien   1.1.2.1         // have to produce a paper, don't we?) we know that the start() is
 863 vivien   1.1.2.1         // the last operation in the method so we just take the info from
 864 vivien   1.1.2.1         // the graph at the end of the method.
 865 vivien   1.1.2.1         Set pointed = pig.G.I.pointedNodes(nt);
 866 vivien   1.1.2.1 
 867 vivien   1.1.2.1         ////////
 868 vivien   1.1.2.1         //if(DEBUG)
 869 vivien   1.1.2.1         //System.out.println("Pointed = " + pointed);
 870 vivien   1.1.2.1 
 871 vivien   1.1.2.1         // retain in "pointed" only the nodes allocated in this method, 
 872 vivien   1.1.2.1         // and which escaped only through the thread nt.
 873 vivien   1.1.2.1         for(Iterator it = pointed.iterator(); it.hasNext(); ){
 874 vivien   1.1.2.1             PANode node = (PANode) it.next();
 875 vivien   1.1.2.1             if( (node.type != PANode.INSIDE) ||
 876 vivien   1.1.2.1                 (node.getCallChainDepth() != 0) ||
 877 vivien   1.1.2.1                 !escapes_only_in_thread(node, nt, pig) ){
 878 vivien   1.1.2.1                 /// System.out.println(node + " escapes somewhere else too");
 879 vivien   1.1.2.1                 it.remove();
 880 vivien   1.1.2.1                 //FV the last test should be refined...
 881 vivien   1.1.2.1             }
 882 vivien   1.1.2.1         }
 883 vivien   1.1.2.1 
 884 vivien   1.1.2.1         ////////
 885 vivien   1.1.2.1         ///if(DEBUG)
 886 vivien   1.1.2.1         //System.out.println("Good Pointed = " + pointed);
 887 vivien   1.1.2.1 
 888 vivien   1.1.2.1         // grab into "news" the set of the NEW/ANEW quads allocating objects
 889 vivien   1.1.2.1         // that should be put into the heap of "nt".
 890 vivien   1.1.2.1         Set news = new HashSet();
 891 cananian 1.9             for(Object nodeO : pointed){
 892 cananian 1.9                 PANode node = (PANode) nodeO;
 893 vivien   1.1.2.1             news.add(node_rep.node2Code(node));
 894 vivien   1.1.2.1         }
 895 vivien   1.1.2.1         
 896 vivien   1.1.2.1         if(news.isEmpty()){
 897 vivien   1.1.2.1             // specially treat this simple case:
 898 vivien   1.1.2.1             // just allocate the thread node nt on its own heap
 899 vivien   1.1.2.1             MyAP ap = getAPObj(qnt);
 900 vivien   1.1.2.1             if (ODMAInfo.MEM_OPTIMIZATION){
 901 vivien   1.1.2.1                 ap.sa = false;
 902 vivien   1.1.2.1 //              ap.ta = false;
 903 vivien   1.1.2.1                 ap.ta = true;
 904 vivien   1.1.2.1                 ap.mh = true;  // makeHeap
 905 vivien   1.1.2.1             }
 906 vivien   1.1.2.1             else{
 907 vivien   1.1.2.1                 ap.sa = false;
 908 vivien   1.1.2.1                 ap.ta = false;
 909 vivien   1.1.2.1             }
 910 vivien   1.1.2.1             if (ODMAInfo.SYNC_ELIM)
 911 vivien   1.1.2.1                 ap.ns = true;
 912 vivien   1.1.2.1             else
 913 vivien   1.1.2.1                 ap.ns = false;
 914 vivien   1.1.2.1 
 915 vivien   1.1.2.1             // ap.ah = qnt.dst(); // use own heap
 916 vivien   1.1.2.1             return;
 917 vivien   1.1.2.1         }
 918 vivien   1.1.2.1         
 919 vivien   1.1.2.1         // this NEW no longer exists
 920 vivien   1.1.2.1         aps.remove(qnt);
 921 vivien   1.1.2.1 
 922 vivien   1.1.2.1         Temp l2 = new Temp(temp_factory);
 923 vivien   1.1.2.1         QuadFactory qf = qnt.getFactory();
 924 vivien   1.1.2.1         MOVE moveq = new MOVE(qf, null, qnt.dst(), l2);
 925 vivien   1.1.2.1         NEW  newq  = new  NEW(qf, null, l2, qnt.hclass());
 926 vivien   1.1.2.1 
 927 vivien   1.1.2.1         // insert the MOVE instead of the original allocation
 928 vivien   1.1.2.1         Quad.replace(qnt, moveq);
 929 vivien   1.1.2.1         // insert the new NEW quad right after the METHOD quad
 930 vivien   1.1.2.1         // (at the very top of the method)
 931 vivien   1.1.2.1         insert_newq((METHOD) (((Quad)hcode.getRootElement()).next(1)), newq);
 932 vivien   1.1.2.1 
 933 vivien   1.1.2.1         // since the object creation site for the thread node has been changed,
 934 vivien   1.1.2.1         // we need to update the node2code relation.
 935 vivien   1.1.2.1         node_rep.updateNode2Code(nt, newq);
 936 vivien   1.1.2.1 
 937 vivien   1.1.2.1         // the thread object should be allocated in its own
 938 vivien   1.1.2.1         // thread specific heap.
 939 vivien   1.1.2.1         MyAP newq_ap = getAPObj(newq);
 940 vivien   1.1.2.1         if (ODMAInfo.MEM_OPTIMIZATION){
 941 vivien   1.1.2.1             newq_ap.sa = false;
 942 vivien   1.1.2.1 //          newq_ap.ta = false;
 943 vivien   1.1.2.1             newq_ap.ta = true;
 944 vivien   1.1.2.1             newq_ap.mh = true;  // makeHeap
 945 vivien   1.1.2.1         }
 946 vivien   1.1.2.1         else{
 947 vivien   1.1.2.1             newq_ap.sa = false;
 948 vivien   1.1.2.1             newq_ap.ta = false;
 949 vivien   1.1.2.1         }
 950 vivien   1.1.2.1 
 951 vivien   1.1.2.1 //      newq_ap.ta = true;       // thread allocation
 952 vivien   1.1.2.1 //      newq_ap.mh = true;       // makeHeap for the thread object
 953 vivien   1.1.2.1         if (ODMAInfo.SYNC_ELIM)
 954 vivien   1.1.2.1             newq_ap.ns = true;
 955 vivien   1.1.2.1         else
 956 vivien   1.1.2.1             newq_ap.ns = false;
 957 vivien   1.1.2.1         // newq_ap.ah = newq.dst(); // use own heap
 958 vivien   1.1.2.1         HClass hclass = getAllocatedType(newq);
 959 vivien   1.1.2.1         newq_ap.hip = 
 960 vivien   1.1.2.1             DefaultAllocationInformation.hasInteriorPointers(hclass);
 961 vivien   1.1.2.1         
 962 vivien   1.1.2.1         // the objects pointed by the thread node and which don't escape
 963 vivien   1.1.2.1         // anywhere else are allocated on the heap of the thread node
 964 cananian 1.9             for(Object cnewqO : news){
 965 cananian 1.9                 Quad cnewq = (Quad) cnewqO;
 966 vivien   1.1.2.1             MyAP cnewq_ap = getAPObj(cnewq);
 967 vivien   1.1.2.1             if (ODMAInfo.MEM_OPTIMIZATION){
 968 vivien   1.1.2.1                 cnewq_ap.sa = false;
 969 vivien   1.1.2.1 //              cnewq_ap.ta = false;
 970 vivien   1.1.2.1                 cnewq_ap.ta = true;
 971 vivien   1.1.2.1                 cnewq_ap.ah = l2;
 972 vivien   1.1.2.1             }
 973 vivien   1.1.2.1             else{
 974 vivien   1.1.2.1                 cnewq_ap.sa = false;
 975 vivien   1.1.2.1                 cnewq_ap.ta = false;
 976 vivien   1.1.2.1             }
 977 vivien   1.1.2.1 
 978 vivien   1.1.2.1 //          cnewq_ap.ta = true;
 979 vivien   1.1.2.1 //          cnewq_ap.ah = l2;
 980 vivien   1.1.2.1             if (ODMAInfo.SYNC_ELIM)
 981 vivien   1.1.2.1                 cnewq_ap.ns = true;
 982 vivien   1.1.2.1             else
 983 vivien   1.1.2.1                 cnewq_ap.ns = false;
 984 vivien   1.1.2.1 
 985 vivien   1.1.2.1         }
 986 vivien   1.1.2.1 
 987 vivien   1.1.2.1         /* //B/ */
 988 vivien   1.1.2.1         /*
 989 vivien   1.1.2.1         if(DEBUG){
 990 vivien   1.1.2.1         System.out.println("After the preallocation transformation:");
 991 vivien   1.1.2.1             hcode.print(new java.io.PrintWriter(System.out, true));
 992 vivien   1.1.2.1             System.out.println("Thread specific NEW:");
 993 cananian 1.9                 for(Object new_siteO : news){
 994 cananian 1.9                     Quad new_site = (Quad) new_siteO;
 995 vivien   1.1.2.1                 System.out.println(new_site.getSourceFile() + ":" + 
 996 vivien   1.1.2.1                                    new_site.getLineNumber() + " " + 
 997 vivien   1.1.2.1                                    new_site);
 998 vivien   1.1.2.1             }
 999 vivien   1.1.2.1         }
1000 vivien   1.1.2.1         */
1001 vivien   1.1.2.1     }
1002 vivien   1.1.2.1 
1003 vivien   1.1.2.1     private void insert_newq(METHOD method, NEW newq){
1004 cananian 1.3.2.1         assert method.nextLength() == 1 : "A METHOD quad should have exactly one successor!";
1005 vivien   1.1.2.1         Edge nextedge = method.nextEdge(0);
1006 vivien   1.1.2.1         Quad nextquad = method.next(0);
1007 vivien   1.1.2.1         Quad.addEdge(method, nextedge.which_succ(), newq, 0);
1008 vivien   1.1.2.1         Quad.addEdge(newq, 0, nextquad, nextedge.which_pred());
1009 vivien   1.1.2.1     }
1010 vivien   1.1.2.1 
1011 vivien   1.1.2.1 
1012 vivien   1.1.2.1     // returns the AllocationProperties object for the object creation site q
1013 vivien   1.1.2.1     // if no such object exists, create a default one. 
1014 vivien   1.1.2.1     public MyAP getAPObj(Quad q){
1015 vivien   1.1.2.1         MyAP retval = (MyAP) aps.get(q);
1016 vivien   1.1.2.1         if(retval == null)
1017 vivien   1.1.2.1             aps.put(q, retval = new MyAP(getAllocatedType(q)));
1018 vivien   1.1.2.1         return retval;
1019 vivien   1.1.2.1     }
1020 vivien   1.1.2.1 
1021 vivien   1.1.2.1     // Set the allocation policy for q to be ap. Discard whatever allocation
1022 vivien   1.1.2.1     // policy info was assigned to q before.
1023 vivien   1.1.2.1     private void setAPObj(Quad q, MyAP ap) {
1024 vivien   1.1.2.1         aps.put(q, ap);
1025 vivien   1.1.2.1     }
1026 vivien   1.1.2.1 
1027 vivien   1.1.2.1     // checks whether "node" escapes only through the thread node "nt".
1028 vivien   1.1.2.1     private boolean escapes_only_in_thread(PANode node, PANode nt,
1029 vivien   1.1.2.1                                            ODParIntGraph pig){
1030 vivien   1.1.2.1         if(pig.G.e.hasEscapedIntoAMethod(node)){
1031 vivien   1.1.2.1             if(DEBUG)
1032 vivien   1.1.2.1                 System.out.println(node + " escapes into a method");
1033 vivien   1.1.2.1             return false;
1034 vivien   1.1.2.1         }
1035 vivien   1.1.2.1         if(pig.G.getReachableFromR().contains(node)) {
1036 vivien   1.1.2.1             if(DEBUG)
1037 vivien   1.1.2.1                 System.out.println(node + " is reachable from R");
1038 vivien   1.1.2.1             return false;
1039 vivien   1.1.2.1         }
1040 vivien   1.1.2.1         if(pig.G.getReachableFromExcp().contains(node)) {
1041 vivien   1.1.2.1             if(DEBUG)
1042 vivien   1.1.2.1                 System.out.println(node + " is reachable from Excp");
1043 vivien   1.1.2.1             return false;
1044 vivien   1.1.2.1         }
1045 vivien   1.1.2.1         return true;
1046 vivien   1.1.2.1     }
1047 vivien   1.1.2.1 
1048 vivien   1.1.2.1 
1049 vivien   1.1.2.1     /** Checks whether <code>node</code> escapes only in the caller:
1050 vivien   1.1.2.1         it is reached through a parameter or it is returned from the
1051 vivien   1.1.2.1         method but not lost due to some other reasons. */
1052 vivien   1.1.2.1     private boolean lostOnlyInCaller(PANode node, ODParIntGraph pig,
1053 vivien   1.1.2.1                                      MetaMethod mm){
1054 vivien   1.1.2.1         // if node escapes into a method hole it's wrong ...
1055 vivien   1.1.2.1         System.out.println("lostOnlyInCaller");
1056 vivien   1.1.2.1 
1057 vivien   1.1.2.1         analyzeholes(pig, mm, node);
1058 vivien   1.1.2.1         pig = pa.getIntParIntGraph(mm);
1059 vivien   1.1.2.1         if(pig.G.e.hasEscapedIntoAMethod(node)){
1060 vivien   1.1.2.1             System.out.println("lostOnlyInCaller: hasEscapedIntoAMethod");
1061 vivien   1.1.2.1             return false;
1062 vivien   1.1.2.1         }
1063 vivien   1.1.2.1 
1064 cananian 1.9             for(Object nholeO : pig.G.e.nodeHolesSet(node)){
1065 cananian 1.9                 PANode nhole = (PANode) nholeO;
1066 vivien   1.1.2.1             // if the node escapes through some node that is not a parameter
1067 vivien   1.1.2.1             // it's wrong ...
1068 vivien   1.1.2.1             if(nhole.type != PANode.PARAM){
1069 vivien   1.1.2.1                 System.out.println("lostOnlyInCaller: escapes through non param nodes "
1070 vivien   1.1.2.1                                    + nhole);
1071 vivien   1.1.2.1                 return false;
1072 vivien   1.1.2.1             }
1073 vivien   1.1.2.1         }
1074 vivien   1.1.2.1 
1075 vivien   1.1.2.1         System.out.println(node + "is lostOnlyInCaller");
1076 vivien   1.1.2.1         return true;
1077 vivien   1.1.2.1     }
1078 vivien   1.1.2.1     
1079 vivien   1.1.2.1     private static int MAX_LEVEL_BOTTOM_MODE = 10;
1080 vivien   1.1.2.1     private boolean remainInThreadBottom(PANode node, MetaMethod mm,
1081 vivien   1.1.2.1                                          int level, String ident){
1082 vivien   1.1.2.1         if(node == null){
1083 vivien   1.1.2.1             System.out.println("Null node");
1084 vivien   1.1.2.1             return false;
1085 vivien   1.1.2.1         }
1086 vivien   1.1.2.1 
1087 vivien   1.1.2.1         if(DEBUG)
1088 vivien   1.1.2.1             System.out.println(ident + "remainInThreadBottom called for " + 
1089 vivien   1.1.2.1                                node + " mm = " + mm);
1090 vivien   1.1.2.1 
1091 vivien   1.1.2.1         ODParIntGraph pig = pa.getIntParIntGraph(mm,true);
1092 vivien   1.1.2.1         
1093 vivien   1.1.2.1         if (!(pig.allNodes().contains(node))){
1094 vivien   1.1.2.1             System.out.println("--escaping (does not belong to the graph)");
1095 vivien   1.1.2.1             return false;
1096 vivien   1.1.2.1         }
1097 vivien   1.1.2.1 
1098 vivien   1.1.2.1         if(captured(pig, mm, node, true, false)){
1099 vivien   1.1.2.1 //      if(pig.G.captured(node)){
1100 vivien   1.1.2.1             if(DEBUG)
1101 vivien   1.1.2.1                 System.out.println(ident + node+ " is captured -> true");
1102 vivien   1.1.2.1             return true;
1103 vivien   1.1.2.1         }
1104 vivien   1.1.2.1         pig = pa.getIntParIntGraph(mm);
1105 vivien   1.1.2.1         
1106 vivien   1.1.2.1         if(!lostOnlyInCaller(node, pig, mm)){
1107 vivien   1.1.2.1             if(DEBUG)
1108 vivien   1.1.2.1                 System.out.println(ident + node +
1109 vivien   1.1.2.1                                    " escapes somewhere else -> false");
1110 vivien   1.1.2.1             return false;
1111 vivien   1.1.2.1         }
1112 vivien   1.1.2.1         pig = pa.getIntParIntGraph(mm);
1113 vivien   1.1.2.1 
1114 vivien   1.1.2.1         if(level == MAX_LEVEL_BOTTOM_MODE){
1115 vivien   1.1.2.1             if(DEBUG)
1116 vivien   1.1.2.1                 System.out.println(ident + node + 
1117 vivien   1.1.2.1                                    "max level reached -> false");
1118 vivien   1.1.2.1             return false;
1119 vivien   1.1.2.1         }
1120 vivien   1.1.2.1 
1121 vivien   1.1.2.1 //      //Conservative approximation
1122 vivien   1.1.2.1 //      if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1123 vivien   1.1.2.1 //          System.out.println("ODA: conservative approximation");
1124 vivien   1.1.2.1 //          return false;
1125 vivien   1.1.2.1 //      }
1126 vivien   1.1.2.1 
1127 vivien   1.1.2.1         MetaMethod[] callers = mac.getCallers(mm);
1128 vivien   1.1.2.1 
1129 vivien   1.1.2.1         // This is a very, very delicate case: if there is no caller, it means
1130 vivien   1.1.2.1         // the currently analyzed method is either "main" or the run method of
1131 vivien   1.1.2.1         // some thread; the node might accessible from outside the current
1132 vivien   1.1.2.1         // thread => we conservatively return "false".
1133 vivien   1.1.2.1         if(callers.length == 0){
1134 vivien   1.1.2.1             if(DEBUG)
1135 vivien   1.1.2.1                 System.out.println(ident + node + "pours out of main/run");
1136 vivien   1.1.2.1             return false;
1137 vivien   1.1.2.1         }
1138 vivien   1.1.2.1 
1139 vivien   1.1.2.1         for(int i = 0; i < callers.length; i++){
1140 vivien   1.1.2.1             if (ODPointerAnalysis.ON_DEMAND_ANALYSIS)
1141 vivien   1.1.2.1                 if (mm.equals(callers[i])){
1142 vivien   1.1.2.1                     System.out.println("Identical to callee: skipping");
1143 vivien   1.1.2.1                 }
1144 vivien   1.1.2.1                 else{
1145 vivien   1.1.2.1                     int old_depth = pa.current_analysis_depth;
1146 vivien   1.1.2.1                     pa.current_analysis_depth=0;
1147 vivien   1.1.2.1                     ODParIntGraph caller_pig = (ODParIntGraph)
1148 vivien   1.1.2.1                         pa.getIntParIntGraph(callers[i],true).clone();
1149 vivien   1.1.2.1                     pa.current_analysis_depth=old_depth;
1150 vivien   1.1.2.1                     pa.hash_proc_int_d[pa.current_analysis_depth].put(callers[i],
1151 vivien   1.1.2.1                                                                       caller_pig);
1152 vivien   1.1.2.1                     pa.hash_proc_ext_d[pa.current_analysis_depth].put(callers[i],
1153 vivien   1.1.2.1                                                                       caller_pig.clone());
1154 vivien   1.1.2.1                     System.out.println("Analyzing " + callers[i]);
1155 vivien   1.1.2.1                     analyze_call(callers[i], mm.getHMethod());
1156 vivien   1.1.2.1                 }
1157 vivien   1.1.2.1         
1158 vivien   1.1.2.1 
1159 vivien   1.1.2.1             if (!mm.equals(callers[i]))
1160 vivien   1.1.2.1                 if(!remainInThreadBottom(node.getBottom(), callers[i], level+1,
1161 vivien   1.1.2.1                                          ident + " ")){
1162 vivien   1.1.2.1                     if(DEBUG)
1163 vivien   1.1.2.1                         System.out.println(ident + node + " -> false");
1164 vivien   1.1.2.1                     return false;
1165 vivien   1.1.2.1                 }
1166 vivien   1.1.2.1         }
1167 vivien   1.1.2.1         
1168 vivien   1.1.2.1         if(DEBUG)
1169 vivien   1.1.2.1             System.out.println(ident + node +
1170 vivien   1.1.2.1                                " remains in the current thread");
1171 vivien   1.1.2.1         return true;
1172 vivien   1.1.2.1     }
1173 vivien   1.1.2.1 
1174 vivien   1.1.2.1 
1175 vivien   1.1.2.1     // Checks whether node defined into hm, remain into the current
1176 vivien   1.1.2.1     // thread even if it escapes from the method which defines it.
1177 vivien   1.1.2.1     
1178 vivien   1.1.2.1     private boolean remainInThread(PANode node, HMethod hm, String ident){
1179 vivien   1.1.2.1         
1180 vivien   1.1.2.1         if(DEBUG)
1181 vivien   1.1.2.1             System.out.println(ident + "remainInThread called for " +
1182 vivien   1.1.2.1                                node + "  hm = " + hm);
1183 vivien   1.1.2.1 
1184 vivien   1.1.2.1         if(node.getCallChainDepth() == ODPointerAnalysis.MAX_SPEC_DEPTH){
1185 vivien   1.1.2.1             System.out.println(ident + node + " is too old -> might escape");
1186 vivien   1.1.2.1             return false;
1187 vivien   1.1.2.1         }
1188 vivien   1.1.2.1 
1189 vivien   1.1.2.1         MetaMethod mm = new MetaMethod(hm, true);
1190 vivien   1.1.2.1         ODParIntGraph pig = pa.getIntParIntGraph(mm,true);
1191 vivien   1.1.2.1 
1192 vivien   1.1.2.1         System.out.println(ident + "remainInThread called for " +
1193 vivien   1.1.2.1                            node + "  hm = " + hm);
1194 vivien   1.1.2.1 //      System.out.println(pig);
1195 vivien   1.1.2.1 
1196 cananian 1.3.2.1         assert pig != null : "pig is null for hm = " + hm + " " + mm;
1197 vivien   1.1.2.1         
1198 vivien   1.1.2.1         if (!(pig.allNodes().contains(node))){
1199 vivien   1.1.2.1             System.out.println("--escaping (does not belong to the graph)");
1200 vivien   1.1.2.1             return false;
1201 vivien   1.1.2.1         }
1202 vivien   1.1.2.1 
1203 vivien   1.1.2.1 //      if(pig.G.captured(node)){
1204 vivien   1.1.2.1         if(captured(pig, mm, node, true, false)){
1205 vivien   1.1.2.1             if(DEBUG)
1206 vivien   1.1.2.1                 System.out.println(ident + node+ " is captured -> true");
1207 vivien   1.1.2.1             return true;
1208 vivien   1.1.2.1         }
1209 vivien   1.1.2.1         pig = pa.getIntParIntGraph(mm);
1210 vivien   1.1.2.1         
1211 vivien   1.1.2.1         if(!lostOnlyInCaller(node, pig, mm)){
1212 vivien   1.1.2.1             if(DEBUG)
1213 vivien   1.1.2.1                 System.out.println(ident + node +
1214 vivien   1.1.2.1                                          " escapes somewhere else -> false");
1215 vivien   1.1.2.1             return false;
1216 vivien   1.1.2.1         }
1217 vivien   1.1.2.1         pig = pa.getIntParIntGraph(mm);
1218 vivien   1.1.2.1 
1219 vivien   1.1.2.1         if(node.getCallChainDepth() == ODPointerAnalysis.MAX_SPEC_DEPTH - 1){
1220 vivien   1.1.2.1             if(DEBUG)
1221 vivien   1.1.2.1                 System.out.println(ident + node + 
1222 vivien   1.1.2.1                                    " is almost too old and uncaptured -> " + 
1223 vivien   1.1.2.1                                    "bottom mode");
1224 vivien   1.1.2.1             boolean retval = remainInThreadBottom(node, mm, 0, ident);
1225 vivien   1.1.2.1             if(DEBUG)
1226 vivien   1.1.2.1                 System.out.println(ident + node + " " + retval);
1227 vivien   1.1.2.1             return retval;
1228 vivien   1.1.2.1         }
1229 vivien   1.1.2.1         
1230 vivien   1.1.2.1         if (PointerAnalysis.CALL_CONTEXT_SENSITIVE)
1231 vivien   1.1.2.1             System.out.println("CONTEXT_SENSITIVE");
1232 vivien   1.1.2.1         else
1233 vivien   1.1.2.1             System.out.println("CONTEXT_insensitive :-(");
1234 vivien   1.1.2.1 
1235 vivien   1.1.2.1         System.out.println("FV Node " + node);
1236 vivien   1.1.2.1         System.out.println("FV spec " + node.getAllCSSpecs());
1237 vivien   1.1.2.1 
1238 vivien   1.1.2.1         // In the case of On Demand Analysis, we must ensure that all
1239 vivien   1.1.2.1         // the specializations of the current node where created (one
1240 vivien   1.1.2.1         // depth further)
1241 vivien   1.1.2.1         if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1242 vivien   1.1.2.1             // Find all the metamethods which call the current
1243 vivien   1.1.2.1             // metamethod
1244 vivien   1.1.2.1             System.out.println("\nMetaMethod : " + mm);
1245 vivien   1.1.2.1             System.out.println("HMethod : " + mm.getHMethod());
1246 vivien   1.1.2.1             MetaMethod[] callers = mac.getCallers(mm);
1247 vivien   1.1.2.1             // Analyze them for the current meta method
1248 vivien   1.1.2.1 //          System.out.println("Callers:");
1249 vivien   1.1.2.1             for(int i = 0; i < callers.length; i++){
1250 vivien   1.1.2.1                 if (mm.equals(callers[i])){
1251 vivien   1.1.2.1                     System.out.println("Identical to callee: skipping");
1252 vivien   1.1.2.1                 }
1253 vivien   1.1.2.1                 else{
1254 vivien   1.1.2.1                     int old_depth = pa.current_analysis_depth;
1255 vivien   1.1.2.1                     pa.current_analysis_depth=0;
1256 vivien   1.1.2.1                     ODParIntGraph caller_pig = (ODParIntGraph)
1257 vivien   1.1.2.1                         pa.getIntParIntGraph(callers[i],true).clone();
1258 vivien   1.1.2.1                     pa.current_analysis_depth=old_depth;
1259 vivien   1.1.2.1                     pa.hash_proc_int_d[pa.current_analysis_depth].put(callers[i],
1260 vivien   1.1.2.1                                                                       caller_pig);
1261 vivien   1.1.2.1                     pa.hash_proc_ext_d[pa.current_analysis_depth].put(callers[i],
1262 vivien   1.1.2.1                                                                       caller_pig.clone());
1263 vivien   1.1.2.1                     System.out.println("Analyzing " + callers[i]);
1264 vivien   1.1.2.1                     analyze_call(callers[i], mm.getHMethod());
1265 vivien   1.1.2.1                 }
1266 vivien   1.1.2.1             }
1267 vivien   1.1.2.1         }
1268 vivien   1.1.2.1 
1269 vivien   1.1.2.1         System.out.println("FV Node " + node);
1270 vivien   1.1.2.1         System.out.println("FV spec " + node.getAllCSSpecs());
1271 vivien   1.1.2.1 
1272 cananian 1.9             for(Object entryO : node.getAllCSSpecs()){
1273 cananian 1.9                 Map.Entry entry = (Map.Entry) entryO;
1274 vivien   1.1.2.1             CALL   call = (CALL) entry.getKey();
1275 vivien   1.1.2.1             PANode spec = (PANode) entry.getValue();
1276 vivien   1.1.2.1             
1277 vivien   1.1.2.1             QuadFactory qf = call.getFactory();
1278 vivien   1.1.2.1             HMethod hm_caller = qf.getMethod();
1279 vivien   1.1.2.1             MetaMethod mm_caller = new MetaMethod(hm_caller, true);
1280 vivien   1.1.2.1             if (mm.equals(mm_caller)){
1281 vivien   1.1.2.1                 System.out.println("Identical to callee: skipping");
1282 vivien   1.1.2.1             }
1283 vivien   1.1.2.1             else{
1284 vivien   1.1.2.1                 
1285 vivien   1.1.2.1 
1286 vivien   1.1.2.1                 if(!remainInThread(spec, hm_caller, ident + " ")){
1287 vivien   1.1.2.1                     if(DEBUG)
1288 vivien   1.1.2.1                         System.out.println(ident + node +
1289 vivien   1.1.2.1                                            " might escape -> false");
1290 vivien   1.1.2.1                     return false;
1291 vivien   1.1.2.1                 }
1292 vivien   1.1.2.1             }
1293 vivien   1.1.2.1         }
1294 vivien   1.1.2.1 
1295 vivien   1.1.2.1         if(DEBUG)
1296 vivien   1.1.2.1             System.out.println(ident + node + 
1297 vivien   1.1.2.1                                " remains in thread -> true");
1298 vivien   1.1.2.1 
1299 vivien   1.1.2.1         return true;
1300 vivien   1.1.2.1     }
1301 vivien   1.1.2.1 
1302 vivien   1.1.2.1     
1303 vivien   1.1.2.1     /** Checks some additional conditions for the stack allocation of the
1304 vivien   1.1.2.1         objects created at Quad q (something else than just captured(node)
1305 vivien   1.1.2.1 
1306 vivien   1.1.2.1         For the time being, we do just a minor hack to save our experimental
1307 vivien   1.1.2.1         results: the Thread objects that are captured (e.g. a Thread object
1308 vivien   1.1.2.1         that is created but never started and remains captured into its
1309 vivien   1.1.2.1         creating method) should NOT be stack allocated. The constructor
1310 vivien   1.1.2.1         of Thread does a very nasty thing: it puts a reference to the
1311 vivien   1.1.2.1         newly created Thread object into the ThreadGroup of the current
1312 vivien   1.1.2.1         Thread. Normally, this means that any thread escapes into the
1313 vivien   1.1.2.1         currentThread native method but we did some special tricks for this
1314 vivien   1.1.2.1         case to ignore it (so that we can allocate a Thread object in its
1315 vivien   1.1.2.1         own thread specific heap).
1316 vivien   1.1.2.1 
1317 vivien   1.1.2.1         Normally, some other conditions should be tested too: e.g. do not
1318 vivien   1.1.2.1         stack allocate objects that are too big etc. */
1319 vivien   1.1.2.1     private boolean stack_alloc_extra_cond(PANode node, Quad q) {
1320 vivien   1.1.2.1         // a hack for the Thread objects ...
1321 vivien   1.1.2.1         HClass hclass = getAllocatedType(q);
1322 vivien   1.1.2.1         if(java_lang_Thread.isSuperclassOf(hclass)){
1323 vivien   1.1.2.1             //if(DEBUG)
1324 vivien   1.1.2.1                 System.out.println(node + " allocated in " + q + 
1325 vivien   1.1.2.1                                    " could be a thread -> NOT stack alloc");
1326 vivien   1.1.2.1             return false;
1327 vivien   1.1.2.1         }
1328 vivien   1.1.2.1         // ... and nothing else
1329 vivien   1.1.2.1         return true;
1330 vivien   1.1.2.1     }
1331 vivien   1.1.2.1     private static HClass java_lang_Thread = null;
1332 vivien   1.1.2.1 
1333 vivien   1.1.2.1     private boolean thread_on_stack(PANode node, Quad q) {
1334 vivien   1.1.2.1         HClass hclass = getAllocatedType(q);
1335 vivien   1.1.2.1         if(java_lang_Thread.isSuperclassOf(hclass)) {
1336 vivien   1.1.2.1             // if(DEBUG)
1337 salcianu 1.5                     System.out.println(Util.code2str(q) + " Thread on Stack");
1338 vivien   1.1.2.1             return true;
1339 vivien   1.1.2.1         }
1340 vivien   1.1.2.1         return false;
1341 vivien   1.1.2.1     }
1342 vivien   1.1.2.1 
1343 vivien   1.1.2.1 
1344 vivien   1.1.2.1 
1345 vivien   1.1.2.1     /** Pretty printer for debug. */
1346 vivien   1.1.2.1     public void print(){
1347 vivien   1.1.2.1         System.out.println("ALLOCATION POLLICIES:");
1348 cananian 1.9             for(Object newqO : aps.keySet()){
1349 cananian 1.9                 Quad newq = (Quad) newqO;
1350 vivien   1.1.2.1             MyAP ap   = (MyAP) aps.get(newq);
1351 vivien   1.1.2.1             HMethod hm = newq.getFactory().getMethod();
1352 vivien   1.1.2.1             HClass hclass = hm.getDeclaringClass();
1353 vivien   1.1.2.1             PANode node = node_rep.getCodeNode(newq, PANode.INSIDE, false);
1354 vivien   1.1.2.1             
1355 vivien   1.1.2.1             System.out.println(hclass.getPackage() + "." + 
1356 vivien   1.1.2.1                                newq.getSourceFile() + ":" +
1357 vivien   1.1.2.1                                newq.getLineNumber() + " " +
1358 vivien   1.1.2.1                                newq + "(" + node + ") (" + 
1359 vivien   1.1.2.1                                hm + ") \t -> " + ap); 
1360 vivien   1.1.2.1         }
1361 vivien   1.1.2.1         System.out.println("====================");
1362 vivien   1.1.2.1 
1363 vivien   1.1.2.1 //      ODMAInfo.do_additional_testing(hcf);
1364 vivien   1.1.2.1     }
1365 vivien   1.1.2.1     
1366 vivien   1.1.2.1     public static void do_additional_testing(HCodeFactory hcf) {
1367 vivien   1.1.2.1         System.out.println("ADDITIONAL TESTING of java.util.AbstractList.equals");
1368 vivien   1.1.2.1         HMethod hm = get_hmethod_for_name("java.util.AbstractList","equals");
1369 vivien   1.1.2.1         HCode hcode = hcf.convert(hm);
1370 vivien   1.1.2.1         AllocationInformation ai = ((harpoon.IR.Quads.Code) hcode).getAllocationInformation();
1371 vivien   1.1.2.1         System.out.println("NEW sites inside it");
1372 vivien   1.1.2.1         for(Iterator it = hcode.getElementsI(); it.hasNext(); ) {
1373 vivien   1.1.2.1             Quad quad = (Quad) it.next();
1374 vivien   1.1.2.1             if(!(quad instanceof NEW)) continue;
1375 vivien   1.1.2.1             NEW qn = (NEW) quad;
1376 vivien   1.1.2.1             MyAP ap = (MyAP) ai.query(qn);
1377 salcianu 1.5                 System.out.println(Util.code2str(qn) + "->" + ap);                         
1378 vivien   1.1.2.1         }
1379 vivien   1.1.2.1         System.out.println("--------------------");
1380 vivien   1.1.2.1     }
1381 vivien   1.1.2.1 
1382 vivien   1.1.2.1     private static HMethod get_hmethod_for_name(String cls, String mthd) {
1383 vivien   1.1.2.1         HClass hclass = linker.forName(cls);
1384 vivien   1.1.2.1         HMethod[] ms = hclass.getMethods();
1385 vivien   1.1.2.1         for(int i = 0; i < ms.length; i++) {
1386 vivien   1.1.2.1             HMethod hm = ms[i];
1387 vivien   1.1.2.1             if(hm.getName().equals(mthd))
1388 vivien   1.1.2.1                 return hm;
1389 vivien   1.1.2.1         }
1390 vivien   1.1.2.1         return null;
1391 vivien   1.1.2.1     }
1392 vivien   1.1.2.1 
1393 vivien   1.1.2.1     private void generate_inlining_hints(MetaMethod mm, ODParIntGraph pig){
1394 vivien   1.1.2.1         generate_inlining_hints(mm, pig, null);
1395 vivien   1.1.2.1     }
1396 vivien   1.1.2.1 
1397 vivien   1.1.2.1     private void generate_inlining_hints(MetaMethod mm, ODParIntGraph pig, Set candidates){
1398 vivien   1.1.2.1 //      if (DEBUG)
1399 vivien   1.1.2.1             System.out.println("In generate_inlining_hints " + mm);
1400 vivien   1.1.2.1 
1401 vivien   1.1.2.1         HMethod hm  = mm.getHMethod();
1402 vivien   1.1.2.1         HCode hcode = hcf.convert(hm);
1403 vivien   1.1.2.1 //      if(hcode.getElementsL().size() > MAX_INLINING_SIZE) return;
1404 vivien   1.1.2.1 
1405 vivien   1.1.2.1         // obtain in A the set of nodes that might be captured after inlining 
1406 vivien   1.1.2.1         Set level0 = getLevel0InsideNodes(pig);
1407 vivien   1.1.2.1         if (candidates!=null) 
1408 vivien   1.1.2.1             level0.retainAll(candidates);
1409 vivien   1.1.2.1 //      System.out.println("original candidates " + level0);
1410 vivien   1.1.2.1         Set A = new HashSet();
1411 cananian 1.9             for(Object nodeO : level0) {
1412 cananian 1.9                 PANode node = (PANode) nodeO;
1413 vivien   1.1.2.1 //          if(!pig.G.captured(node) && lostOnlyInCaller(node, pig, mm)) {
1414 vivien   1.1.2.1             if(!captured(pig, mm, node)){
1415 vivien   1.1.2.1                 pig = pa.getIntParIntGraph(mm);
1416 vivien   1.1.2.1                 if(lostOnlyInCaller(node, pig, mm)) {
1417 vivien   1.1.2.1                     pig = pa.getIntParIntGraph(mm);
1418 vivien   1.1.2.1                     // we are not interested in stack allocating the exceptions
1419 vivien   1.1.2.1                     // since they  don't appear in normal case and so, they
1420 vivien   1.1.2.1                     // are not critical for the memory management
1421 vivien   1.1.2.1                     HClass hclass = getAllocatedType(node_rep.node2Code(node));
1422 vivien   1.1.2.1                     if(!java_lang_Throwable.isSuperclassOf(hclass))
1423 vivien   1.1.2.1                         A.add(node);
1424 vivien   1.1.2.1                 }
1425 vivien   1.1.2.1             }
1426 vivien   1.1.2.1         }
1427 vivien   1.1.2.1 
1428 vivien   1.1.2.1         if(A.isEmpty()) {
1429 vivien   1.1.2.1 //          System.out.println("No candidate for inlining");
1430 vivien   1.1.2.1             return;
1431 vivien   1.1.2.1         }
1432 vivien   1.1.2.1         else{
1433 vivien   1.1.2.1 //          System.out.println("Candidates for inlining " + A);
1434 vivien   1.1.2.1         }
1435 vivien   1.1.2.1 
1436 vivien   1.1.2.1 //      System.out.println("Looking for " + mm);
1437 vivien   1.1.2.1         // very dummy 1-level inlining
1438 vivien   1.1.2.1         int n_sites=0;
1439 vivien   1.1.2.1         MetaMethod[] callers = mac.getCallers(mm);
1440 vivien   1.1.2.1         for(int i = 0; i < callers.length; i++) {
1441 vivien   1.1.2.1             MetaMethod mcaller = callers[i];
1442 vivien   1.1.2.1             HMethod hcaller = mcaller.getHMethod();
1443 vivien   1.1.2.1 //          System.out.println("Caller : " + mcaller);
1444 cananian 1.9                 for(Object csO : mcg.getCallSites(mcaller)) {
1445 cananian 1.9                     CALL cs = (CALL) csO;
1446 vivien   1.1.2.1                 MetaMethod[] callees = mcg.getCallees(mcaller, cs);
1447 vivien   1.1.2.1 
1448 vivien   1.1.2.1                 if (callees.length==0) continue;
1449 vivien   1.1.2.1                 if (callees[0].equals(mm))
1450 vivien   1.1.2.1                     n_sites++;
1451 vivien   1.1.2.1 
1452 vivien   1.1.2.1                 if((callees.length == 1) && (callees[0].equals(mm)) && good_cs(cs)){
1453 vivien   1.1.2.1                     if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1454 vivien   1.1.2.1                         int old_depth = pa.current_analysis_depth;
1455 vivien   1.1.2.1                         pa.current_analysis_depth=0;
1456 vivien   1.1.2.1                         ODParIntGraph caller_pig = (ODParIntGraph)
1457 vivien   1.1.2.1                             pa.getIntParIntGraph(mcaller,true).clone();
1458 vivien   1.1.2.1                         pa.current_analysis_depth=old_depth;
1459 vivien   1.1.2.1                         pa.hash_proc_int_d[pa.current_analysis_depth].
1460 vivien   1.1.2.1                             put(mcaller,caller_pig);
1461 vivien   1.1.2.1                         pa.hash_proc_ext_d[pa.current_analysis_depth].
1462 vivien   1.1.2.1                             put(mcaller,caller_pig.clone());
1463 vivien   1.1.2.1 //                      System.out.println("In generate_inlining_hints: " + 
1464 vivien   1.1.2.1 //                                         "Analyzing " + mcaller);
1465 vivien   1.1.2.1                         analyze_call(mcaller, mm.getHMethod());
1466 vivien   1.1.2.1                     }
1467 vivien   1.1.2.1                     try_inlining(mcaller, cs, A);
1468 vivien   1.1.2.1                 }
1469 vivien   1.1.2.1             }
1470 vivien   1.1.2.1         }
1471 vivien   1.1.2.1         
1472 cananian 1.9             for(Object nO : A) {
1473 cananian 1.9                 PANode n = (PANode) nO;
1474 vivien   1.1.2.1             ODNodeStatus status = (ODNodeStatus) Nodes2Status.get(n);
1475 vivien   1.1.2.1             if (status==null) {
1476 vivien   1.1.2.1                 System.err.println("Problem somewhere with Nodes2Status");
1477 vivien   1.1.2.1                 continue;
1478 vivien   1.1.2.1             }
1479 vivien   1.1.2.1             status.nCallers = n_sites;
1480 vivien   1.1.2.1         }
1481 vivien   1.1.2.1 
1482 vivien   1.1.2.1 
1483 vivien   1.1.2.1 
1484 vivien   1.1.2.1     }
1485 vivien   1.1.2.1 
1486 vivien   1.1.2.1 
1487 vivien   1.1.2.1     
1488 vivien   1.1.2.1     public void generate_inlining_hints(MetaMethod mm, 
1489 vivien   1.1.2.1                                         Set candidates, Set winners,
1490 vivien   1.1.2.1                                         MetaMethod mcaller, CALL cs){
1491 vivien   1.1.2.1 //      if (DEBUG)
1492 vivien   1.1.2.1             System.out.println("In generate_inlining_hints " + mm);
1493 vivien   1.1.2.1 
1494 vivien   1.1.2.1         HMethod hm  = mm.getHMethod();
1495 vivien   1.1.2.1         HCode hcode = hcf.convert(hm);
1496 vivien   1.1.2.1         ODParIntGraph pig = (ODParIntGraph) pa.getIntParIntGraph(mm);
1497 vivien   1.1.2.1 
1498 vivien   1.1.2.1         // obtain in A the set of nodes that might be captured after inlining 
1499 vivien   1.1.2.1         Set A = new HashSet();
1500 cananian 1.9             for(Object nodeO : candidates) {
1501 cananian 1.9                 PANode node = (PANode) nodeO;
1502 vivien   1.1.2.1             if(!captured(pig, mm, node)){
1503 vivien   1.1.2.1                 pig = pa.getIntParIntGraph(mm);
1504 vivien   1.1.2.1                 if(lostOnlyInCaller(node, pig, mm)) {
1505 vivien   1.1.2.1                     pig = pa.getIntParIntGraph(mm);
1506 vivien   1.1.2.1                     // we are not interested in stack allocating the exceptions
1507 vivien   1.1.2.1                     // since they  don't appear in normal case and so, they
1508 vivien   1.1.2.1                     // are not critical for the memory management
1509 vivien   1.1.2.1                     HClass hclass = getAllocatedType(node_rep.node2Code(node));
1510 vivien   1.1.2.1                     if(!java_lang_Throwable.isSuperclassOf(hclass))
1511 vivien   1.1.2.1                         A.add(node);
1512 vivien   1.1.2.1                 }
1513 vivien   1.1.2.1             }
1514 vivien   1.1.2.1         }
1515 vivien   1.1.2.1 
1516 vivien   1.1.2.1         if(A.isEmpty()) {
1517 vivien   1.1.2.1             System.out.println("No candidate for inlining");
1518 vivien   1.1.2.1             return;
1519 vivien   1.1.2.1         }
1520 vivien   1.1.2.1         else{
1521 vivien   1.1.2.1             System.out.println("Candidates for inlining " + A);
1522 vivien   1.1.2.1         }
1523 vivien   1.1.2.1 
1524 vivien   1.1.2.1         // very dummy 1-level inlining
1525 vivien   1.1.2.1         HMethod hcaller = mcaller.getHMethod();
1526 vivien   1.1.2.1         MetaMethod[] callees = mcg.getCallees(mcaller, cs);
1527 vivien   1.1.2.1         System.out.println("callees : " + callees.length);
1528 vivien   1.1.2.1         if(callees.length==0){
1529 vivien   1.1.2.1             System.err.println("Call site with no callees !!!");
1530 vivien   1.1.2.1             System.out.println("Call site with no callees !!!");
1531 vivien   1.1.2.1             return;
1532 vivien   1.1.2.1         }
1533 vivien   1.1.2.1         System.out.println("callees[0].equals(mm) " + callees[0].equals(mm)
1534 vivien   1.1.2.1                            + callees[0] + mm);
1535 vivien   1.1.2.1         System.out.println("good_cs(cs) " + good_cs(cs));
1536 vivien   1.1.2.1         if((callees.length == 1) && (callees[0].equals(mm)) && good_cs(cs)){
1537 vivien   1.1.2.1             System.out.println(" no problem");
1538 vivien   1.1.2.1             if (ODPointerAnalysis.ON_DEMAND_ANALYSIS){
1539 vivien   1.1.2.1                 int old_depth = pa.current_analysis_depth;
1540 vivien   1.1.2.1                 pa.current_analysis_depth=0;
1541 vivien   1.1.2.1                 ODParIntGraph caller_pig = (ODParIntGraph)
1542 vivien   1.1.2.1                     pa.getIntParIntGraph(mcaller,true).clone();
1543 vivien   1.1.2.1                 pa.current_analysis_depth=old_depth;
1544 vivien   1.1.2.1                 pa.hash_proc_int_d[pa.current_analysis_depth].
1545 vivien   1.1.2.1                     put(mcaller,caller_pig);
1546 vivien   1.1.2.1                 pa.hash_proc_ext_d[pa.current_analysis_depth].
1547 vivien   1.1.2.1                     put(mcaller,caller_pig.clone());
1548 vivien   1.1.2.1                 analyze_call(mcaller, mm.getHMethod());
1549 vivien   1.1.2.1             }
1550 vivien   1.1.2.1             try_inlining(mcaller, cs, A, winners);
1551 vivien   1.1.2.1         }
1552 vivien   1.1.2.1     }
1553 vivien   1.1.2.1 
1554 vivien   1.1.2.1 
1555 vivien   1.1.2.1     private static HClass java_lang_Throwable = null;
1556 vivien   1.1.2.1 
1557 vivien   1.1.2.1     /* Normally, we should refuse to inline calls that are inside loops
1558 vivien   1.1.2.1        because that + stack allocation might lead to stack overflow errors.
1559 vivien   1.1.2.1        However, at this moment we don't test this condition. */
1560 vivien   1.1.2.1     private boolean good_cs(CALL cs){
1561 vivien   1.1.2.1         return true;
1562 vivien   1.1.2.1     }
1563 vivien   1.1.2.1 
1564 vivien   1.1.2.1     private void try_inlining(MetaMethod mcaller, CALL cs, Set A) {
1565 vivien   1.1.2.1         try_inlining(mcaller, cs, A, new HashSet());
1566 vivien   1.1.2.1     }
1567 vivien   1.1.2.1 
1568 vivien   1.1.2.1     private void try_inlining(MetaMethod mcaller, CALL cs, Set A, Set C) {
1569 vivien   1.1.2.1         ODParIntGraph caller_pig = pa.getIntParIntGraph(mcaller,true);
1570 vivien   1.1.2.1 
1571 vivien   1.1.2.1         System.out.println("Inside try_inlining");
1572 vivien   1.1.2.1 
1573 vivien   1.1.2.1         Set B = new HashSet();
1574 cananian 1.9             for(Object nodeO : A){
1575 cananian 1.9                 PANode node = (PANode) nodeO;
1576 vivien   1.1.2.1             PANode spec = node.csSpecialize(cs);
1577 vivien   1.1.2.1             if(spec == null) continue;
1578 vivien   1.1.2.1             if(captured(caller_pig, mcaller, spec, true, false)){
1579 vivien   1.1.2.1                 B.add(spec);
1580 vivien   1.1.2.1                 C.add(node);
1581 vivien   1.1.2.1                 caller_pig = pa.getIntParIntGraph(mcaller);
1582 vivien   1.1.2.1             }
1583 vivien   1.1.2.1         }
1584 vivien   1.1.2.1 
1585 vivien   1.1.2.1         // no stack allocation benefits from this inlining
1586 vivien   1.1.2.1         if(B.isEmpty())
1587 vivien   1.1.2.1             return;
1588 vivien   1.1.2.1 
1589 vivien   1.1.2.1         Set news = new HashSet();
1590 vivien   1.1.2.1         for(Iterator it = B.iterator(); it.hasNext(); ) {
1591 vivien   1.1.2.1             PANode node = ((PANode) it.next()).getRoot();
1592 vivien   1.1.2.1             Quad q = (Quad) node_rep.node2Code(node);
1593 cananian 1.3.2.1             assert (q != null) && 
1594 cananian 1.3.2.1                         ((q instanceof NEW) || (q instanceof ANEW)) : " Bad quad attached to " + node + " " + q;
1595 vivien   1.1.2.1             news.add(q);
1596 vivien   1.1.2.1         }
1597 vivien   1.1.2.1 
1598 vivien   1.1.2.1         Quad[] news_array = (Quad[]) news.toArray(new Quad[news.size()]);
1599 vivien   1.1.2.1         ih.put(cs, news_array);
1600 vivien   1.1.2.1 
1601 vivien   1.1.2.1 //      if(DEBUG) 
1602 vivien   1.1.2.1         {
1603 salcianu 1.5                 System.err.println("INLINING HINT: " + Util.code2str(cs));
1604 salcianu 1.5                 System.out.println("\nINLINING HINT: " + Util.code2str(cs));
1605 vivien   1.1.2.1             System.out.println("NEW STACK ALLOCATION SITES:");
1606 vivien   1.1.2.1             for(int i = 0; i < news_array.length; i++)
1607 salcianu 1.5                     System.out.println(" " + Util.code2str(news_array[i]));
1608 vivien   1.1.2.1         }
1609 vivien   1.1.2.1     }
1610 vivien   1.1.2.1 
1611 vivien   1.1.2.1     public void do_the_inlining(){
1612 vivien   1.1.2.1         do_the_inlining(hcf,ih);
1613 vivien   1.1.2.1     }
1614 vivien   1.1.2.1 
1615 vivien   1.1.2.1     private void do_the_inlining(HCodeFactory hcf, Map ih){
1616 salcianu 1.10            Set toPrune = new WorkSet();
1617 salcianu 1.10    
1618 salcianu 1.11            for(SCComponent scc : reverse_top_sort_of_cs(ih).incrOrder()) {
1619 vivien   1.1.2.1             if(DEBUG) {
1620 vivien   1.1.2.1                 System.out.println("Processed SCC:{");
1621 salcianu 1.12                    for(Object node : scc.nodes())
1622 salcianu 1.12                        System.out.println(" " + Util.code2str((CALL) node));
1623 vivien   1.1.2.1                 System.out.println("}");
1624 vivien   1.1.2.1             }
1625 salcianu 1.12                for(Object node : scc.nodes()) {
1626 salcianu 1.12                    CALL cs = (CALL) node;
1627 vivien   1.1.2.1                 inline_call_site(cs, hcf, ih);
1628 vivien   1.1.2.1                 toPrune.add(cs.getFactory().getParent());
1629 vivien   1.1.2.1             }
1630 vivien   1.1.2.1         }
1631 salcianu 1.10            for(Iterator pit = toPrune.iterator();pit.hasNext();)
1632 vivien   1.1.2.1             Unreachable.prune((HEADER)((HCode)pit.next()).getRootElement());
1633 vivien   1.1.2.1     }
1634 vivien   1.1.2.1 
1635 vivien   1.1.2.1 
1636 salcianu 1.11        private TopSortedCompDiGraph<Quad> reverse_top_sort_of_cs(Map ih) {
1637 vivien   1.1.2.1         final Relation m2csINm = new LightRelation();
1638 vivien   1.1.2.1         final Relation m2csTOm = new LightRelation();
1639 cananian 1.9             for(Object csO : ih.keySet()) {
1640 cananian 1.9                 CALL cs = (CALL) csO;
1641 vivien   1.1.2.1             m2csINm.add(quad2method(cs), cs);
1642 vivien   1.1.2.1             m2csTOm.add(cs.method(), cs);
1643 vivien   1.1.2.1         }
1644 vivien   1.1.2.1 
1645 salcianu 1.6             final Navigator nav = new Navigator() {
1646 vivien   1.1.2.1                 public Object[] next(final Object node) {
1647 vivien   1.1.2.1                     Set set = m2csINm.getValues(node);
1648 vivien   1.1.2.1                     return set.toArray(new Object[set.size()]);
1649 vivien   1.1.2.1                 }
1650 vivien   1.1.2.1                 public Object[] prev(final Object node) {
1651 vivien   1.1.2.1                     Set set = m2csTOm.getValues(node);
1652 vivien   1.1.2.1                     return set.toArray(new Object[set.size()]);
1653 vivien   1.1.2.1                 }
1654 vivien   1.1.2.1             };
1655 vivien   1.1.2.1 
1656 salcianu 1.10            return
1657 salcianu 1.11                new TopSortedCompDiGraph<Quad>(ih.keySet(), nav);
1658 vivien   1.1.2.1     }
1659 vivien   1.1.2.1 
1660 vivien   1.1.2.1 
1661 vivien   1.1.2.1     // given a quad q, returns the method q is part of 
1662 vivien   1.1.2.1     private final HMethod quad2method(Quad q) {
1663 vivien   1.1.2.1         return q.getFactory().getMethod();
1664 vivien   1.1.2.1     }
1665 vivien   1.1.2.1 
1666 vivien   1.1.2.1 
1667 vivien   1.1.2.1     private void inline_call_site(CALL cs, HCodeFactory hcf, Map ih) {
1668 salcianu 1.5             System.out.println("INLINING " + Util.code2str(cs));
1669 vivien   1.1.2.1         HMethod caller = quad2method(cs);
1670 vivien   1.1.2.1         System.out.println("caller = " + caller);
1671 vivien   1.1.2.1 
1672 vivien   1.1.2.1         HCode hcode = hcf.convert(caller);
1673 vivien   1.1.2.1         ((harpoon.IR.Quads.Code) hcode).setAllocationInformation(this);
1674 vivien   1.1.2.1 
1675 vivien   1.1.2.1 //      AllocationInformation ai = ((harpoon.IR.Quads.Code) hcode).getAllocationInformation();
1676 vivien   1.1.2.1 //      System.out.println("1. " + (ai==null?
1677 vivien   1.1.2.1 //                         (caller + " baaad!") :
1678 vivien   1.1.2.1 //                         (caller + " good!")));
1679 vivien   1.1.2.1         
1680 vivien   1.1.2.1         Map old2new = new HashMap();
1681 vivien   1.1.2.1 
1682 vivien   1.1.2.1         HEADER header_new = null;
1683 vivien   1.1.2.1         try{
1684 vivien   1.1.2.1             header_new = get_cloned_code(cs, caller, old2new, hcf);
1685 vivien   1.1.2.1         } catch(CloneNotSupportedException excp) { return; }
1686 vivien   1.1.2.1 
1687 vivien   1.1.2.1         METHOD qm = (METHOD) (header_new.next(1));
1688 vivien   1.1.2.1 
1689 vivien   1.1.2.1         // add the code for the parameter passing
1690 vivien   1.1.2.1         add_entry_sequence(cs, qm);
1691 vivien   1.1.2.1 
1692 vivien   1.1.2.1         modify_return_and_throw(cs, header_new);
1693 vivien   1.1.2.1 
1694 vivien   1.1.2.1         translate_ap(old2new);
1695 vivien   1.1.2.1         
1696 vivien   1.1.2.1         extra_stack_allocation(cs, ih, old2new);
1697 vivien   1.1.2.1 
1698 vivien   1.1.2.1 //      hcode = hcf.convert(caller);
1699 vivien   1.1.2.1 //      ai = ((harpoon.IR.Quads.Code) hcode).getAllocationInformation();
1700 vivien   1.1.2.1 //      System.out.println("2. " + (ai==null?
1701 vivien   1.1.2.1 //                         (caller + " baaad!") :
1702 vivien   1.1.2.1 //                         (caller + " good!")));
1703 vivien   1.1.2.1 
1704 vivien   1.1.2.1     }
1705 vivien   1.1.2.1 
1706 vivien   1.1.2.1 
1707 vivien   1.1.2.1     private void extra_stack_allocation(CALL cs, Map ih, Map old2new) {
1708 vivien   1.1.2.1         Quad[] news = (Quad[]) ih.get(cs);
1709 vivien   1.1.2.1         for(int i = 0; i < news.length; i++) {
1710 vivien   1.1.2.1             Quad q  = (Quad) old2new.get(news[i]);
1711 cananian 1.3.2.1             assert q != null : "no new Quad for " + news[i];
1712 vivien   1.1.2.1             MyAP ap = new MyAP(getAllocatedType(q));
1713 vivien   1.1.2.1 
1714 salcianu 1.5                 System.out.println("New Stack Allocation " + Util.code2str(q));
1715 vivien   1.1.2.1 
1716 vivien   1.1.2.1             if (ODMAInfo.MEM_OPTIMIZATION)
1717 vivien   1.1.2.1                 ap.sa = true;
1718 vivien   1.1.2.1             else
1719 vivien   1.1.2.1                 ap.sa = false;
1720 vivien   1.1.2.1             if (ODMAInfo.SYNC_ELIM)
1721 vivien   1.1.2.1                 ap.ns = true;
1722 vivien   1.1.2.1             else
1723 vivien   1.1.2.1                 ap.ns = false;
1724 vivien   1.1.2.1             setAPObj(q, ap);
1725 vivien   1.1.2.1         }
1726 vivien   1.1.2.1     }
1727 vivien   1.1.2.1     
1728 vivien   1.1.2.1 
1729 vivien   1.1.2.1     private void add_entry_sequence(CALL cs, METHOD qm) {
1730 vivien   1.1.2.1         // TODO: put something better than null in the 2nd argument
1731 vivien   1.1.2.1         Quad replace_cs = new NOP(cs.getFactory(), null);
1732 vivien   1.1.2.1 
1733 vivien   1.1.2.1         move_pred_edges(cs, replace_cs);
1734 vivien   1.1.2.1 
1735 cananian 1.3.2.1         assert cs.paramsLength() == qm.paramsLength() : " different nb. of parameters between CALL and METHOD";
1736 vivien   1.1.2.1         
1737 vivien   1.1.2.1         Quad previous = replace_cs;
1738 vivien   1.1.2.1 
1739 vivien   1.1.2.1         int nb_params = cs.paramsLength();
1740 vivien   1.1.2.1         for(int i = 0; i < nb_params; i++) {
1741 vivien   1.1.2.1             Temp formal = qm.params(i);
1742 vivien   1.1.2.1             Temp actual = cs.params(i);
1743 vivien   1.1.2.1             // emulate the Java parameter passing semantics
1744 vivien   1.1.2.1             MOVE move = new MOVE(cs.getFactory(), null, formal, actual);
1745 vivien   1.1.2.1             Quad.addEdge(previous, 0, move, 0);
1746 vivien   1.1.2.1             previous = move;
1747 vivien   1.1.2.1         }
1748 vivien   1.1.2.1 
1749 vivien   1.1.2.1         // the edge pointing to the first instruction of the method body
1750 vivien   1.1.2.1         Edge edge = qm.nextEdge(0);
1751 cananian 1.7             Quad.addEdge(previous, 0, edge.to(), edge.which_pred());
1752 vivien   1.1.2.1     }
1753 vivien   1.1.2.1 
1754 vivien   1.1.2.1     
1755 vivien   1.1.2.1     private void modify_return_and_throw(final CALL cs, final HEADER header) {
1756 vivien   1.1.2.1         class QVisitor extends  QuadVisitor {
1757 vivien   1.1.2.1             Set returnset;
1758 vivien   1.1.2.1             Set throwset;
1759 vivien   1.1.2.1             QVisitor() {
1760 vivien   1.1.2.1                 returnset=new WorkSet();
1761 vivien   1.1.2.1                 throwset=new WorkSet();
1762 vivien   1.1.2.1             }
1763 vivien   1.1.2.1 
1764 vivien   1.1.2.1             public void finish() {
1765 vivien   1.1.2.1                 PHI returnphi=new PHI(cs.getFactory(),null, new Temp[0],
1766 vivien   1.1.2.1                                       returnset.size());
1767 vivien   1.1.2.1                 int edge=0;
1768 vivien   1.1.2.1                 for(Iterator returnit=returnset.iterator();returnit.hasNext();)
1769 vivien   1.1.2.1                     Quad.addEdge((Quad)returnit.next(),0,returnphi,edge++);
1770 vivien   1.1.2.1                 
1771 vivien   1.1.2.1                 Quad.addEdge(returnphi,0,cs.next(0),cs.nextEdge(0).which_pred());
1772 vivien   1.1.2.1 
1773 vivien   1.1.2.1                 PHI throwphi=new PHI(cs.getFactory(),null, new Temp[0],
1774 vivien   1.1.2.1                                      throwset.size());
1775 vivien   1.1.2.1                 edge=0;
1776 vivien   1.1.2.1                 for(Iterator throwit=throwset.iterator();throwit.hasNext();)
1777 vivien   1.1.2.1                     Quad.addEdge((Quad)throwit.next(),0,throwphi,edge++);
1778 vivien   1.1.2.1                 
1779 vivien   1.1.2.1                 Quad.addEdge(throwphi,0,cs.next(1),cs.nextEdge(1).which_pred());
1780 vivien   1.1.2.1             }
1781 vivien   1.1.2.1 
1782 vivien   1.1.2.1             public void visit(Quad q) {
1783 vivien   1.1.2.1             } 
1784 vivien   1.1.2.1 
1785 vivien   1.1.2.1             public void visit(RETURN q) {
1786 vivien   1.1.2.1                 Temp retVal = cs.retval(); 
1787 vivien   1.1.2.1                 
1788 vivien   1.1.2.1                 Quad replace;
1789 vivien   1.1.2.1                 if(retVal != null)
1790 vivien   1.1.2.1                 replace = new MOVE
1791 vivien   1.1.2.1                 (cs.getFactory(), null, retVal, q.retval());
1792 vivien   1.1.2.1                 else
1793 vivien   1.1.2.1                 replace = new NOP(cs.getFactory(), null);
1794 vivien   1.1.2.1                 
1795 vivien   1.1.2.1                 // make the predecessors of q point to replace
1796 vivien   1.1.2.1                 move_pred_edges(q, replace);
1797 vivien   1.1.2.1                 
1798 vivien   1.1.2.1                 // the only succesor of replace should now be the
1799 vivien   1.1.2.1                 // 0-successor of the CALL instruction (normal return)
1800 vivien   1.1.2.1                 returnset.add(replace);
1801 vivien   1.1.2.1             }
1802 vivien   1.1.2.1 
1803 vivien   1.1.2.1             public void visit(THROW q) {
1804 vivien   1.1.2.1                 Temp retEx = cs.retex(); 
1805 vivien   1.1.2.1                 
1806 vivien   1.1.2.1                 Quad replace;
1807 vivien   1.1.2.1                 if(retEx != null)
1808 vivien   1.1.2.1                 replace = new MOVE
1809 vivien   1.1.2.1                 (cs.getFactory(), null, retEx, q.throwable());
1810 vivien   1.1.2.1                 else
1811 vivien   1.1.2.1                 replace = new NOP(cs.getFactory(), null);
1812 vivien   1.1.2.1                 
1813 vivien   1.1.2.1                 // make the predecessors of q point to replace
1814 vivien   1.1.2.1                 move_pred_edges(q, replace);
1815 vivien   1.1.2.1                 
1816 vivien   1.1.2.1                 // the only succesor of replace should now be the
1817 vivien   1.1.2.1                 // 1-successor of the CALL instruction (exception return)
1818 vivien   1.1.2.1                 throwset.add(replace);
1819 vivien   1.1.2.1             }
1820 vivien   1.1.2.1         };
1821 vivien   1.1.2.1         QVisitor inlining_qv=new QVisitor();
1822 vivien   1.1.2.1         apply_qv_to_tree(header, inlining_qv);
1823 vivien   1.1.2.1         inlining_qv.finish();
1824 vivien   1.1.2.1     }
1825 vivien   1.1.2.1 
1826 vivien   1.1.2.1 
1827 vivien   1.1.2.1     private static void apply_qv_to_tree(Quad q, QuadVisitor qv) {
1828 vivien   1.1.2.1         recursive_apply_qv(q, qv, new HashSet());
1829 vivien   1.1.2.1     }
1830 vivien   1.1.2.1 
1831 vivien   1.1.2.1     private static void recursive_apply_qv(Quad q, QuadVisitor qv, Set seen) {
1832 vivien   1.1.2.1         if(!seen.add(q)) return; // q has already been seen
1833 vivien   1.1.2.1         
1834 vivien   1.1.2.1         q.accept(qv);
1835 vivien   1.1.2.1         
1836 vivien   1.1.2.1         int nb_next = q.nextLength();
1837 vivien   1.1.2.1         for(int i = 0; i < nb_next; i++)
1838 vivien   1.1.2.1             recursive_apply_qv(q.next(i), qv, seen);
1839 vivien   1.1.2.1     }
1840 vivien   1.1.2.1 
1841 vivien   1.1.2.1 
1842 vivien   1.1.2.1     // For any predecessor pred of oldq, replace the arc pred->oldq
1843 vivien   1.1.2.1     // with old->newq. 
1844 vivien   1.1.2.1     private static void move_pred_edges(Quad oldq, Quad newq) {
1845 vivien   1.1.2.1         Edge[] edges = oldq.prevEdge();
1846 vivien   1.1.2.1         for(int i = 0; i < edges.length; i++) {
1847 vivien   1.1.2.1             Edge e = edges[i];
1848 cananian 1.7                 Quad.addEdge(e.from(), e.which_succ(),
1849 vivien   1.1.2.1                          newq, e.which_pred());
1850 vivien   1.1.2.1         }
1851 vivien   1.1.2.1     }
1852 vivien   1.1.2.1 
1853 vivien   1.1.2.1 
1854 vivien   1.1.2.1     private void translate_ap(Map old2new) {
1855 cananian 1.9             for(Object entryO : old2new.entrySet()) {
1856 cananian 1.9                 Map.Entry entry = (Map.Entry) entryO;
1857 vivien   1.1.2.1             Quad old_q = (Quad) entry.getKey();
1858 vivien   1.1.2.1             Quad new_q = (Quad) entry.getValue();
1859 vivien   1.1.2.1             setAPObj(new_q, (MyAP) (getAPObj(old_q).clone()));
1860 vivien   1.1.2.1         }
1861 vivien   1.1.2.1     }
1862 vivien   1.1.2.1 
1863 vivien   1.1.2.1 
1864 vivien   1.1.2.1     private HEADER get_cloned_code(CALL cs, HMethod caller,
1865 vivien   1.1.2.1                                  Map old2new, HCodeFactory hcf)
1866 vivien   1.1.2.1         throws CloneNotSupportedException {
1867 vivien   1.1.2.1 
1868 vivien   1.1.2.1         MetaMethod mcaller = new MetaMethod(caller, true);      
1869 vivien   1.1.2.1         MetaMethod[] callees = mcg.getCallees(mcaller, cs);
1870 cananian 1.3.2.1         assert callees.length == 1 : "not exactly one callee in " + cs;
1871 vivien   1.1.2.1         HMethod hm = callees[0].getHMethod();
1872 vivien   1.1.2.1 
1873 vivien   1.1.2.1         HCode hcode_orig = hcf.convert(hm);
1874 vivien   1.1.2.1 
1875 vivien   1.1.2.1 //      System.out.println("caller = " + caller);
1876 vivien   1.1.2.1 //      System.out.println("hcode_orig " + hcode_orig);
1877 vivien   1.1.2.1 //      System.out.println("\n\nhm " + hm);
1878 vivien   1.1.2.1 
1879 vivien   1.1.2.1         HEADER header_orig = 
1880 vivien   1.1.2.1             (HEADER) hcode_orig.getRootElement();
1881 vivien   1.1.2.1         HEADER header_new  = 
1882 vivien   1.1.2.1             (HEADER) Quad.clone(cs.getFactory(), header_orig);
1883 vivien   1.1.2.1 
1884 vivien   1.1.2.1         fill_the_map(header_orig, header_new, old2new, new HashSet());
1885 vivien   1.1.2.1 
1886 vivien   1.1.2.1         return header_new;
1887 vivien   1.1.2.1     }
1888 vivien   1.1.2.1 
1889 vivien   1.1.2.1 
1890 vivien   1.1.2.1     // recursively explore two HCode's (the second is the clone of the first
1891 vivien   1.1.2.1     // one) and set up a mapping "old NEW/ANEW -> new NEW/ANEW
1892 vivien   1.1.2.1     private static void fill_the_map(Quad q1, Quad q2, Map map, Set seen) {
1893 vivien   1.1.2.1         // avoid entering infinite loops: return when we meet a previously
1894 vivien   1.1.2.1         // seen instruction 
1895 vivien   1.1.2.1         if(!seen.add(q1)) return;
1896 vivien   1.1.2.1 
1897 vivien   1.1.2.1         if((q1 instanceof NEW) || (q2 instanceof ANEW))
1898 vivien   1.1.2.1             map.put(q1, q2);
1899 vivien   1.1.2.1 
1900 vivien   1.1.2.1         Quad[] next1 = q1.next();
1901 vivien   1.1.2.1         Quad[] next2 = q2.next();
1902 vivien   1.1.2.1 
1903 cananian 1.3.2.1         assert next1.length == next2.length : " Possible error in HCode.clone()";
1904 vivien   1.1.2.1 
1905 vivien   1.1.2.1         for(int i = 0; i < next1.length; i++)
1906 vivien   1.1.2.1             fill_the_map(next1[i], next2[i], map, seen);
1907 vivien   1.1.2.1     }
1908 vivien   1.1.2.1 
1909 vivien   1.1.2.1 
1910 vivien   1.1.2.1     public boolean captured(ODParIntGraph pig, 
1911 vivien   1.1.2.1                             MetaMethod current_mmethod, 
1912 vivien   1.1.2.1                             PANode node) 
1913 vivien   1.1.2.1     {
1914 vivien   1.1.2.1         System.out.println("Inside ODMAInfo.captured() for " + node);
1915 vivien   1.1.2.1         return captured(pig, current_mmethod, node, true, true);
1916 vivien   1.1.2.1 
1917 vivien   1.1.2.1     }
1918 vivien   1.1.2.1 
1919 vivien   1.1.2.1     public boolean analyzeholes(ODParIntGraph pig, 
1920 vivien   1.1.2.1                                 MetaMethod current_mmethod, 
1921 vivien   1.1.2.1                                 PANode node) 
1922 vivien   1.1.2.1     {
1923 vivien   1.1.2.1         System.out.println("Inside ODMAInfo.analyzeholes() for " + node);
1924 vivien   1.1.2.1 
1925 vivien   1.1.2.1         boolean result = captured(pig, current_mmethod, node, false, false);
1926 vivien   1.1.2.1 //      System.out.println("PIG after analysis");
1927 vivien   1.1.2.1 //      System.out.println(pig);
1928 vivien   1.1.2.1         return result;
1929 vivien   1.1.2.1 
1930 vivien   1.1.2.1     }
1931 vivien   1.1.2.1 
1932 vivien   1.1.2.1     public boolean captured(ODParIntGraph pig, 
1933 vivien   1.1.2.1                             MetaMethod current_mmethod, 
1934 vivien   1.1.2.1                             PANode node,
1935 vivien   1.1.2.1                             boolean methodcapture) 
1936 vivien   1.1.2.1     {
1937 vivien   1.1.2.1         return captured(pig, current_mmethod, node, methodcapture, false);
1938 vivien   1.1.2.1     }
1939 vivien   1.1.2.1 
1940 vivien   1.1.2.1     public boolean captured(ODParIntGraph pig, 
1941 vivien   1.1.2.1                             MetaMethod current_mmethod, 
1942 vivien   1.1.2.1                             PANode node,
1943 vivien   1.1.2.1                             boolean methodcapture,
1944 vivien   1.1.2.1                             boolean verbose) 
1945 vivien   1.1.2.1     {
1946 vivien   1.1.2.1         verbose = false;
1947 vivien   1.1.2.1 
1948 vivien   1.1.2.1         if(verbose)
1949 vivien   1.1.2.1             {
1950 vivien   1.1.2.1                 System.out.println("  pig B4 analysis");
1951 vivien   1.1.2.1                 System.out.println(pig);
1952 vivien   1.1.2.1             }   
1953 vivien   1.1.2.1 
1954 vivien   1.1.2.1         if (!(pig.allNodes().contains(node))){
1955 vivien   1.1.2.1             System.err.println("--escaping (does not belong to the graph)");
1956 vivien   1.1.2.1             System.out.println("--escaping (does not belong to the graph)");
1957 vivien   1.1.2.1             return false;
1958 vivien   1.1.2.1         }
1959 vivien   1.1.2.1         
1960 vivien   1.1.2.1         if (pig.G.captured(node)){
1961 vivien   1.1.2.1             System.out.println("--captured (no analysis) " + node);
1962 vivien   1.1.2.1 //          System.out.println(pig);
1963 vivien   1.1.2.1             return true;        
1964 vivien   1.1.2.1         }
1965 vivien   1.1.2.1         else if ((pa.BOUNDED_ANALYSIS_DEPTH==false)
1966 vivien   1.1.2.1                  ||(pa.MAX_ANALYSIS_DEPTH==0)){
1967 vivien   1.1.2.1             System.out.println("--escaping (no recursive analysis) " + node);
1968 vivien   1.1.2.1             return false;       
1969 vivien   1.1.2.1         }
1970 vivien   1.1.2.1 
1971 vivien   1.1.2.1         int depth = 1;
1972 vivien   1.1.2.1         do{
1973 vivien   1.1.2.1 
1974 vivien   1.1.2.1             if (pig.G.captured(node)){
1975 vivien   1.1.2.1                 System.out.println("--captured (no analysis) " + node);
1976 vivien   1.1.2.1 //              System.out.println(pig);
1977 vivien   1.1.2.1                 prepare_exit(current_mmethod);
1978 vivien   1.1.2.1                 return true;    
1979 vivien   1.1.2.1             }
1980 vivien   1.1.2.1             
1981 vivien   1.1.2.1             // If the node escape through a return node, there is nothing
1982 vivien   1.1.2.1             // to be done.
1983 vivien   1.1.2.1             if ((methodcapture)&&(pig.G.willEscape(node))){
1984 vivien   1.1.2.1                 System.out.println("--escaping (no analysis) " + 
1985 vivien   1.1.2.1                                    node + " (returned)");
1986 vivien   1.1.2.1                 prepare_exit(current_mmethod);
1987 vivien   1.1.2.1                 return false;
1988 vivien   1.1.2.1             }
1989 vivien   1.1.2.1 
1990 vivien   1.1.2.1             // If the node escapes through a node (either a parameter node
1991 vivien   1.1.2.1             // or a thread node), there is nothing to be done.
1992 vivien   1.1.2.1 //          if ((methodcapture)&&(pig.G.e.hasEscapedIntoANode(node))){
1993 vivien   1.1.2.1             if (pig.G.e.hasEscapedIntoANode(node)){
1994 vivien   1.1.2.1                 if (!methodcapture){
1995 cananian 1.9                         for(Object nO : pig.G.e.nodeHolesSet(node)){
1996 cananian 1.9                             PANode n = (PANode) nO;
1997 vivien   1.1.2.1                         if (n.type != PANode.PARAM)
1998 vivien   1.1.2.1                             {
1999 vivien   1.1.2.1                                 System.out.println("--escaping (no analysis) " + 
2000 vivien   1.1.2.1                                                    node + " (through non param node " + n
2001 vivien   1.1.2.1                                                    + ") in");
2002 vivien   1.1.2.1 //                              System.out.println(pig);
2003 vivien   1.1.2.1                                 prepare_exit(current_mmethod);
2004 vivien   1.1.2.1                                 return false;
2005 vivien   1.1.2.1                             }
2006 vivien   1.1.2.1                     }
2007 vivien   1.1.2.1                 }
2008 vivien   1.1.2.1                 else {
2009 vivien   1.1.2.1                     System.out.println("--escaping (no analysis) " + 
2010 vivien   1.1.2.1                                        node + " (through a node)");
2011 vivien   1.1.2.1                     prepare_exit(current_mmethod);
2012 vivien   1.1.2.1                     return false;
2013 vivien   1.1.2.1                 }
2014 vivien   1.1.2.1 //              Set nodeholes = (Set) pig.G.e.nodeHolesSet(node);
2015 vivien   1.1.2.1 //              System.out.print("  " + node + " :");
2016 vivien   1.1.2.1 //              for(Iterator nn_it=nodeholes.iterator(); nn_it.hasNext(); ) {
2017 vivien   1.1.2.1 //                  PANode nn_esc_ = (PANode)nn_it.next();
2018 vivien   1.1.2.1 //                  System.out.print(" " + nn_esc_);
2019 vivien   1.1.2.1 //              }
2020 vivien   1.1.2.1 //              System.out.println(" ");
2021 vivien   1.1.2.1                 
2022 vivien   1.1.2.1 
2023 vivien   1.1.2.1             }
2024 vivien   1.1.2.1 
2025 vivien   1.1.2.1 
2026 vivien   1.1.2.1             // If the node does not escape through a method hole, there is
2027 vivien   1.1.2.1             // nothing to be done.
2028 vivien   1.1.2.1             if (!pig.G.e.hasEscapedIntoAMethod(node)){
2029 vivien   1.1.2.1                 if ((methodcapture)&&(depth==1)){
2030 vivien   1.1.2.1                     System.err.println("--escaping (no analysis) " + 
2031 vivien   1.1.2.1                                        node + " (not through method) ERROR ?");
2032 vivien   1.1.2.1                     System.out.println("--escaping (no analysis) " + 
2033 vivien   1.1.2.1                                        node + " (not through method) ERROR ?");
2034 vivien   1.1.2.1                     if(verbose)
2035 vivien   1.1.2.1                         System.out.println(pig);
2036 vivien   1.1.2.1                 }
2037 vivien   1.1.2.1                 else{
2038 vivien   1.1.2.1                     System.out.println("--escaping " + 
2039 vivien   1.1.2.1                                        node + " (not through method)");
2040 vivien   1.1.2.1                     System.out.println(pig);
2041 vivien   1.1.2.1                 }
2042 vivien   1.1.2.1                 prepare_exit(current_mmethod);
2043 vivien   1.1.2.1                 return false;
2044 vivien   1.1.2.1             }
2045 vivien   1.1.2.1 
2046 vivien   1.1.2.1             boolean holefound = true;
2047 vivien   1.1.2.1             
2048 vivien   1.1.2.1             do{
2049 vivien   1.1.2.1                 // Set of unanalyzed methods for current_mmethod
2050 vivien   1.1.2.1                 Set mm_holeset = (Set)pig.odi.skippedCS;
2051 vivien   1.1.2.1                 
2052 vivien   1.1.2.1 //              System.out.println("\n\n pig.method_holes : " + mm_holeset);
2053 vivien   1.1.2.1 
2054 vivien   1.1.2.1                 // If all analyzable methods were already analyzed
2055 vivien   1.1.2.1                 if ((mm_holeset==null)||(mm_holeset.isEmpty())){
2056 vivien   1.1.2.1                     System.out.println(" All analyzable methods were "
2057 vivien   1.1.2.1                                        + "already analyzed...");
2058 vivien   1.1.2.1                     System.out.println("--escaping " + node);
2059 vivien   1.1.2.1                     prepare_exit(current_mmethod);
2060 vivien   1.1.2.1                     return false;
2061 vivien   1.1.2.1                 }
2062 vivien   1.1.2.1 
2063 vivien   1.1.2.1                 // Set of unanalyzed methods for node
2064 vivien   1.1.2.1                 Set methodholes = (Set) pig.G.e.methodHolesSet(node);
2065 vivien   1.1.2.1 //              System.out.println("\n\nunanalyzed methods for the node " + methodholes);
2066 vivien   1.1.2.1 
2067 vivien   1.1.2.1                 
2068 vivien   1.1.2.1                 
2069 vivien   1.1.2.1                 // Select the callsites the studied node escapes through
2070 vivien   1.1.2.1                 HashSet callsites = new HashSet();
2071 vivien   1.1.2.1                 HashSet hmethods_set = new HashSet();
2072 vivien   1.1.2.1                 holefound = false;
2073 vivien   1.1.2.1                 MethodHole thehole = null;
2074 vivien   1.1.2.1 
2075 cananian 1.9                     for(Object holeO : mm_holeset) {
2076 cananian 1.9                         MethodHole hole = (MethodHole) holeO;
2077 vivien   1.1.2.1                     // The node must be reachable from the parameters
2078 vivien   1.1.2.1                     if (hole.arguments()==null)
2079 vivien   1.1.2.1                         System.err.println(hole);
2080 vivien   1.1.2.1                     else 
2081 vivien   1.1.2.1                         if (pig.G.reachableNodes(hole.arguments()).contains(node))
2082 vivien   1.1.2.1                             {
2083 vivien   1.1.2.1                                 hmethods_set.add(hole.method());
2084 vivien   1.1.2.1                                 callsites.add(hole);
2085 vivien   1.1.2.1                                 // It must be of the current depth
2086 vivien   1.1.2.1                                 if (hole.depth()==depth){
2087 vivien   1.1.2.1                                     holefound = true;
2088 vivien   1.1.2.1                                     thehole  = hole;
2089 vivien   1.1.2.1                                 }
2090 vivien   1.1.2.1                             }
2091 vivien   1.1.2.1                 }
2092 vivien   1.1.2.1 
2093 vivien   1.1.2.1                 if (!holefound) {
2094 vivien   1.1.2.1                     System.out.println("No hole found " + depth);
2095 vivien   1.1.2.1                     continue;
2096 vivien   1.1.2.1                 }
2097 vivien   1.1.2.1 
2098 vivien   1.1.2.1                 // The node does not escape through an unanalyzed method...
2099 vivien   1.1.2.1                 if (callsites==null){
2100 vivien   1.1.2.1                     if(verbose) System.out.println(" The node does not escape through an " +
2101 vivien   1.1.2.1                                        "unanalyzed method... (callsites null)");
2102 vivien   1.1.2.1                     System.err.println(" The node does not escape through an " +
2103 vivien   1.1.2.1                                        "unanalyzed method... (callsites null)");
2104 vivien   1.1.2.1                     System.out.println("--escaping " + node);
2105 vivien   1.1.2.1                     prepare_exit(current_mmethod);
2106 vivien   1.1.2.1                     return false;
2107 vivien   1.1.2.1                 }
2108 vivien   1.1.2.1 
2109 vivien   1.1.2.1                 if (callsites.isEmpty()){
2110 vivien   1.1.2.1                     System.out.println(" The node does not escape through an " +
2111 vivien   1.1.2.1                                        "unanalyzed method... (callsites isEmpty)" 
2112 vivien   1.1.2.1                                        + node);
2113 vivien   1.1.2.1                     System.err.println(" The node does not escape through an " +
2114 vivien   1.1.2.1                                        "unanalyzed method... (callsites isEmpty)");
2115 vivien   1.1.2.1                     System.out.println("--escaping " + node);
2116 vivien   1.1.2.1                     prepare_exit(current_mmethod);
2117 vivien   1.1.2.1                     return false;
2118 vivien   1.1.2.1                 }
2119 vivien   1.1.2.1 
2120 vivien   1.1.2.1                 Set arguments = thehole.arguments();
2121 vivien   1.1.2.1                 CALL q     = thehole.callsite();
2122 vivien   1.1.2.1                 HMethod hm = q.method();
2123 vivien   1.1.2.1                 System.out.println("****method hole to be filled:" + hm);
2124 vivien   1.1.2.1                 
2125 vivien   1.1.2.1                 
2126 vivien   1.1.2.1                 
2127 vivien   1.1.2.1                 // Set of unanalyzed method holes for current_mmethod
2128 vivien   1.1.2.1                 Set mm_holes = (Set)pig.odi.skippedCS;
2129 vivien   1.1.2.1                 
2130 vivien   1.1.2.1                 // Check whether, in the remaining unanalyzed call
2131 vivien   1.1.2.1                 // sites, some correspond to the same HMethod, or
2132 vivien   1.1.2.1                 // originally correspond to the same call site.
2133 vivien   1.1.2.1                 boolean hm_esc  = false;
2134 vivien   1.1.2.1                 HashSet hmnodes = new HashSet();
2135 vivien   1.1.2.1                 HashSet hmnodes_ret = new HashSet(); 
2136 vivien   1.1.2.1                 HashSet hmnodes_exc = new HashSet(); 
2137 vivien   1.1.2.1                 HashSet annoyingCS = new HashSet();
2138 vivien   1.1.2.1                 Set mm_holes_whithout_hole = new HashSet(pig.odi.skippedCS);
2139 vivien   1.1.2.1                 mm_holes_whithout_hole.remove(thehole);
2140 vivien   1.1.2.1                 boolean unique = true;
2141 vivien   1.1.2.1                 PANode ret = thehole.ret();
2142 vivien   1.1.2.1                 PANode exc = thehole.exc();
2143 vivien   1.1.2.1 
2144 cananian 1.9                     for(Object mhO : mm_holes_whithout_hole){
2145 cananian 1.9                         MethodHole mh = (MethodHole) mhO;
2146 vivien   1.1.2.1                     CALL cs = mh.callsite();
2147 vivien   1.1.2.1                     if (hm.equals(cs.method())){
2148 vivien   1.1.2.1                         annoyingCS.add(mh);
2149 vivien   1.1.2.1                         hm_esc = true;
2150 vivien   1.1.2.1                         hmnodes_ret.addAll(mh.parameters());
2151 vivien   1.1.2.1                         hmnodes_exc.addAll(mh.parameters());
2152 vivien   1.1.2.1                         hmnodes.addAll(mh.arguments());
2153 vivien   1.1.2.1                         if (mh.ret()!=null){
2154 vivien   1.1.2.1                             if (mh.ret()!=ret){
2155 vivien   1.1.2.1                                 hmnodes_ret.add(mh.ret());
2156 vivien   1.1.2.1                                 hmnodes_exc.add(mh.ret());
2157 vivien   1.1.2.1                             }
2158 vivien   1.1.2.1                             else{
2159 vivien   1.1.2.1                                 hmnodes_exc.add(mh.ret());
2160 vivien   1.1.2.1                             }
2161 vivien   1.1.2.1                         }
2162 vivien   1.1.2.1                         if (mh.exc()!=null){
2163 vivien   1.1.2.1                             if (mh.exc()!=exc){
2164 vivien   1.1.2.1                                 hmnodes_ret.add(mh.exc());
2165 vivien   1.1.2.1                                 hmnodes_exc.add(mh.exc());
2166 vivien   1.1.2.1                             }
2167 vivien   1.1.2.1                             else{
2168 vivien   1.1.2.1                                 hmnodes_ret.add(mh.exc());
2169 vivien   1.1.2.1                             }
2170 vivien   1.1.2.1                         }
2171 vivien   1.1.2.1                     }
2172 vivien   1.1.2.1                     if ((unique)&&((mh.ret()==ret)||(mh.exc()==exc))){
2173 vivien   1.1.2.1                         unique = false;
2174 vivien   1.1.2.1                     }
2175 vivien   1.1.2.1                 }
2176 vivien   1.1.2.1 
2177 vivien   1.1.2.1                 if (hm_esc==false){
2178 vivien   1.1.2.1                     // No more unanalyzed call sites refer to the same
2179 vivien   1.1.2.1                     // HMethod than the actual call site. We safely
2180 vivien   1.1.2.1                     // remove this HMethod from the escaping ones.
2181 vivien   1.1.2.1                     //
2182 vivien   1.1.2.1                     // CAUTION: we make the assumption that if a call
2183 vivien   1.1.2.1                     // site on method hm is unanalyzed and appears in
2184 vivien   1.1.2.1                     // pig.method_holes, this is also the case for all
2185 vivien   1.1.2.1                     // the (unanalyzed) call sites on method hm.
2186 vivien   1.1.2.1                     if(DEBUG) 
2187 vivien   1.1.2.1                         System.out.println("  no other call site has same hmethod");
2188 vivien   1.1.2.1 
2189 vivien   1.1.2.1                     Set oldhole = new HashSet();
2190 vivien   1.1.2.1                     oldhole.add(hm);
2191 vivien   1.1.2.1                     pig.G.e.removeMethodHoles(oldhole);
2192 vivien   1.1.2.1                     // tbu to be optimized with singleton...
2193 vivien   1.1.2.1                 }
2194 vivien   1.1.2.1                 else{
2195 vivien   1.1.2.1                     if(DEBUG)
2196 vivien   1.1.2.1                         System.out.println("  there is at least one "
2197 vivien   1.1.2.1                                            + "other call site "
2198 vivien   1.1.2.1                                            + "with same hmethod");
2199 vivien   1.1.2.1                     
2200 vivien   1.1.2.1                     // Nodes reachable from the call site we are going to analyze.
2201 vivien   1.1.2.1                     Set reachable = pig.G.reachableNodes(arguments);
2202 vivien   1.1.2.1                     if(DEBUG)
2203 vivien   1.1.2.1                         System.out.println("reachable from the call site " +
2204 vivien   1.1.2.1                                            reachable);
2205 vivien   1.1.2.1 
2206 vivien   1.1.2.1                     
2207 vivien   1.1.2.1                     // Nodes reachable from perturbing call sites.
2208 vivien   1.1.2.1                     Set perturbed = pig.G.reachableNodes(hmnodes);
2209 vivien   1.1.2.1                     if(DEBUG)
2210 vivien   1.1.2.1                         {
2211 vivien   1.1.2.1                             System.out.println("reachable from perturbing call sites " +
2212 vivien   1.1.2.1                                                perturbed);
2213 vivien   1.1.2.1                             System.out.println("Perturbing method holes ");
2214 vivien   1.1.2.1                         }
2215 vivien   1.1.2.1 
2216 vivien   1.1.2.1                     // Nodes reachable from the call site we are going to
2217 vivien   1.1.2.1                     // analyze but not from perturbing call sites. These
2218 vivien   1.1.2.1                     // are the nodes we can update the escape function.
2219 vivien   1.1.2.1                     reachable.removeAll(perturbed);
2220 vivien   1.1.2.1                     if(DEBUG)
2221 vivien   1.1.2.1                         System.out.println("nodes than can be updated " +
2222 vivien   1.1.2.1                                            reachable);
2223 vivien   1.1.2.1                     
2224 vivien   1.1.2.1                     // Update of escape functions
2225 cananian 1.9                         for (Object upd_nO : reachable){
2226 cananian 1.9                             PANode upd_n = (PANode) upd_nO;
2227 vivien   1.1.2.1                         if(verbose) 
2228 vivien   1.1.2.1                             System.out.println("    " + upd_n + " updated !!!");
2229 vivien   1.1.2.1                         pig.G.e.removeMethodHole(upd_n, hm);
2230 vivien   1.1.2.1                     }
2231 vivien   1.1.2.1 
2232 vivien   1.1.2.1                     // Checking whether the params are still escaping
2233 cananian 1.9                         for(Object paramO : arguments) {
2234 cananian 1.9                             PANode param = (PANode) paramO;
2235 vivien   1.1.2.1                         if ((!pig.G.willEscape(param))&&(!pig.G.e.hasEscaped(param)))
2236 vivien   1.1.2.1                             pig.G.e.removeNodeHoleFromAll(param);
2237 vivien   1.1.2.1                     }
2238 vivien   1.1.2.1                     
2239 vivien   1.1.2.1                     // Checking whether the actual return and
2240 vivien   1.1.2.1                     // exception nodes will still be escaping into the
2241 vivien   1.1.2.1                     // HMethod of the current hole, due to some other
2242 vivien   1.1.2.1                     // holes in the caller, if there are some other
2243 vivien   1.1.2.1                     // holes corresponding to the same call site
2244 vivien   1.1.2.1                     if(!unique){
2245 vivien   1.1.2.1                         if(pig.G.reachableNodes(hmnodes_ret).contains(thehole.ret()))
2246 vivien   1.1.2.1                             // Still going to escape
2247 vivien   1.1.2.1                             ODInterProcPA.ret_strong_update = false;
2248 vivien   1.1.2.1                         else
2249 vivien   1.1.2.1                             ODInterProcPA.ret_strong_update = true;
2250 vivien   1.1.2.1 
2251 vivien   1.1.2.1                         if(pig.G.reachableNodes(hmnodes_exc).contains(thehole.exc()))
2252 vivien   1.1.2.1                             // Still going to escape
2253 vivien   1.1.2.1                             ODInterProcPA.exc_strong_update = false;
2254 vivien   1.1.2.1                         else
2255 vivien   1.1.2.1                             ODInterProcPA.exc_strong_update = true;
2256 vivien   1.1.2.1                     }
2257 vivien   1.1.2.1                 }
2258 vivien   1.1.2.1 
2259 vivien   1.1.2.1                 // The method-holes set is updated.
2260 vivien   1.1.2.1                 pig.odi.skippedCS = mm_holes;
2261 vivien   1.1.2.1                 
2262 vivien   1.1.2.1                 if(verbose) 
2263 vivien   1.1.2.1                     System.out.println("  pig before analysis " + pig);
2264 vivien   1.1.2.1                 if(verbose) System.out.println("  Nodes ");
2265 vivien   1.1.2.1                 Iterator parsetit=(pig.allNodes()).iterator();
2266 vivien   1.1.2.1                 if(verbose) System.out.print("    ");
2267 vivien   1.1.2.1                 while(parsetit.hasNext()){
2268 vivien   1.1.2.1                     PANode n = (PANode) parsetit.next();
2269 vivien   1.1.2.1                     if(verbose) System.out.print(" " + n + "(" + n.details() + ")");
2270 vivien   1.1.2.1                 }
2271 vivien   1.1.2.1                 if(verbose) System.out.println(" .");
2272 vivien   1.1.2.1                 
2273 vivien   1.1.2.1                 // Finally the method is analyzed
2274 vivien   1.1.2.1                 if(verbose) System.out.println("   before call on hole! " + thehole);
2275 vivien   1.1.2.1                 ODParIntGraphPair pp = 
2276 vivien   1.1.2.1                     ODInterProcPA.analyze_call(pa, current_mmethod,
2277 vivien   1.1.2.1                                                thehole.callsite(), pig, 
2278 vivien   1.1.2.1                                                thehole,
2279 vivien   1.1.2.1                                                verbose,
2280 vivien   1.1.2.1                                                unique);    
2281 vivien   1.1.2.1 
2282 vivien   1.1.2.1                 pig = pp.pig[0];
2283 vivien   1.1.2.1 
2284 vivien   1.1.2.1                 //tbu
2285 vivien   1.1.2.1 //              pa.hash_proc_int_d[pa.current_analysis_depth].put(current_mmethod,pig.clone());
2286 vivien   1.1.2.1                 pa.hash_proc_int_d[pa.current_analysis_depth].put(current_mmethod,pig);
2287 vivien   1.1.2.1 //              ODParIntGraph new_pig = pp.pig[1];
2288 vivien   1.1.2.1 //              pa.hash_proc_ext_d[pa.current_analysis_depth].put(current_mmethod,new_pig);
2289 vivien   1.1.2.1 
2290 vivien   1.1.2.1 //              ODParIntGraph new_pig = (ODParIntGraph) pig.clone();
2291 vivien   1.1.2.1 //              if(current_mmethod.getHMethod().getReturnType().isPrimitive())
2292 vivien   1.1.2.1 //                  new_pig.G.r.clear();
2293 vivien   1.1.2.1 //              if(current_mmethod.getHMethod().getExceptionTypes().length == 0)
2294 vivien   1.1.2.1 //                  new_pig.G.excp.clear();
2295 vivien   1.1.2.1 //              System.out.println("  pig after analysis and cleaning" + pig);
2296 vivien   1.1.2.1 //              System.out.println("  Real value: (" + current_mmethod + ")");
2297 vivien   1.1.2.1 //              System.out.println(pa.getIntODParIntGraph(current_mmethod));
2298 vivien   1.1.2.1             }
2299 vivien   1.1.2.1             while(holefound);
2300 vivien   1.1.2.1             
2301 vivien   1.1.2.1             depth++;
2302 vivien   1.1.2.1         }
2303 vivien   1.1.2.1         while((depth<=pa.MAX_ANALYSIS_DEPTH)&&(!pig.G.captured(node)));
2304 vivien   1.1.2.1 
2305 vivien   1.1.2.1 //      if(depth>pa.MAX_ANALYSIS_DEPTH){
2306 vivien   1.1.2.1 //          System.err.println("Maximal depth reached for node " + node);
2307 vivien   1.1.2.1 //          System.out.println("Maximal depth reached for node " + node);
2308 vivien   1.1.2.1 //          System.out.println("Holes " + pig.G.e.methodHolesSet(node));
2309 vivien   1.1.2.1 //      }
2310 vivien   1.1.2.1 
2311 vivien   1.1.2.1         prepare_exit(current_mmethod);
2312 vivien   1.1.2.1 
2313 vivien   1.1.2.1         if(verbose) System.out.println("  pig after loop " + pig);
2314 vivien   1.1.2.1 
2315 vivien   1.1.2.1         System.out.println("  pig after WHOLE analysis " + current_mmethod);
2316 vivien   1.1.2.1         System.out.println(pig);
2317 vivien   1.1.2.1         
2318 vivien   1.1.2.1         if (pig.G.captured(node))
2319 vivien   1.1.2.1             System.out.println("--captured " + node);
2320 vivien   1.1.2.1         else
2321 vivien   1.1.2.1             System.out.println("--escaping " + node);
2322 vivien   1.1.2.1         return pig.G.captured(node);
2323 vivien   1.1.2.1     }
2324 vivien   1.1.2.1 
2325 vivien   1.1.2.1 
2326 vivien   1.1.2.1     private void prepare_exit(MetaMethod mm){
2327 vivien   1.1.2.1         ODParIntGraph new_pig = (ODParIntGraph)
2328 vivien   1.1.2.1             ((ODParIntGraph) pa.hash_proc_int_d[pa.current_analysis_depth].get(mm))
2329 vivien   1.1.2.1             .clone();
2330 vivien   1.1.2.1         pa.hash_proc_ext_d[pa.current_analysis_depth].put(mm,new_pig);
2331 vivien   1.1.2.1     }
2332 vivien   1.1.2.1 
2333 vivien   1.1.2.1     public void analyze_call(MetaMethod mm, 
2334 vivien   1.1.2.1                              HMethod    hole) {
2335 vivien   1.1.2.1 
2336 vivien   1.1.2.1         boolean holefound = true;
2337 vivien   1.1.2.1         boolean unique    = true;
2338 vivien   1.1.2.1         ODParIntGraph pig = pa.getIntParIntGraph(mm,true);
2339 vivien   1.1.2.1         
2340 vivien   1.1.2.1         System.out.println("Analyze Call on " + hole +
2341 vivien   1.1.2.1                            "\n in " + mm + "\n with pig ");
2342 vivien   1.1.2.1 //      System.out.println(pig);
2343 vivien   1.1.2.1 
2344 vivien   1.1.2.1         do{
2345 vivien   1.1.2.1             // Set of unanalyzed methods for current_mmethod
2346 vivien   1.1.2.1             Set mm_holeset = (Set) pig.odi.skippedCS;
2347 vivien   1.1.2.1                 
2348 vivien   1.1.2.1             // If all analyzable methods were already analyzed
2349 vivien   1.1.2.1             if ((mm_holeset==null)||(mm_holeset.isEmpty())){
2350 vivien   1.1.2.1                 System.out.println(" All analyzable methods were "
2351 vivien   1.1.2.1                                    + "already analyzed...");
2352 vivien   1.1.2.1                 prepare_exit(mm);
2353 vivien   1.1.2.1                 return;
2354 vivien   1.1.2.1             }
2355 vivien   1.1.2.1                 
2356 vivien   1.1.2.1             // Select the callsites corresponding to the targeted hmethod
2357 vivien   1.1.2.1             HashSet callsites = new HashSet();
2358 vivien   1.1.2.1             holefound = false;
2359 vivien   1.1.2.1             MethodHole thehole = null;
2360 vivien   1.1.2.1 
2361 cananian 1.9                 for(Object c_holeO : mm_holeset) {
2362 cananian 1.9                     MethodHole c_hole = (MethodHole) c_holeO;
2363 vivien   1.1.2.1                 // The HMethod of one of its specialization
2364 vivien   1.1.2.1                 // (MetaMethods) must be the targeted one
2365 vivien   1.1.2.1                 MetaMethod[] mms = c_hole.callees();
2366 vivien   1.1.2.1                 for(int i=0; (i<mms.length); i++){
2367 vivien   1.1.2.1                     if (hole.equals(mms[i].getHMethod()))
2368 vivien   1.1.2.1                         // It must be of depth 1
2369 vivien   1.1.2.1                         if ((c_hole.depth()==1)&&(!holefound)){
2370 vivien   1.1.2.1                             holefound = true;
2371 vivien   1.1.2.1                             thehole  = c_hole;
2372 vivien   1.1.2.1                         }
2373 vivien   1.1.2.1                         else {
2374 vivien   1.1.2.1                             callsites.add(c_hole);
2375 vivien   1.1.2.1                         }
2376 vivien   1.1.2.1                 }
2377 vivien   1.1.2.1             }
2378 vivien   1.1.2.1 
2379 vivien   1.1.2.1             if (!holefound){
2380 vivien   1.1.2.1                 if (!callsites.isEmpty()){
2381 vivien   1.1.2.1 //                  System.err.print("ERROR Depth of the found call sites : ");
2382 vivien   1.1.2.1                     System.out.print("ERROR Depth of the found call sites : ");
2383 vivien   1.1.2.1                     for (Iterator cs_it=callsites.iterator(); (cs_it.hasNext()); ){
2384 vivien   1.1.2.1                         MethodHole _hole_ = (MethodHole) cs_it.next();
2385 vivien   1.1.2.1 //                      System.err.print(_hole_.depth() + " ");
2386 vivien   1.1.2.1                         System.out.print(_hole_.depth() + " ");
2387 vivien   1.1.2.1                     }
2388 vivien   1.1.2.1 //                  System.err.println();
2389 vivien   1.1.2.1                     System.out.println();
2390 vivien   1.1.2.1                 }
2391 vivien   1.1.2.1                 continue;
2392 vivien   1.1.2.1             }
2393 vivien   1.1.2.1 
2394 vivien   1.1.2.1             Set arguments = thehole.arguments();
2395 vivien   1.1.2.1             CALL q     = thehole.callsite();
2396 vivien   1.1.2.1             HMethod hm = q.method();
2397 vivien   1.1.2.1             System.out.println("****method hole to be filled:" + hm 
2398 vivien   1.1.2.1                                + " (" + thehole.rank()+ ")");
2399 vivien   1.1.2.1 
2400 vivien   1.1.2.1             // Set of unanalyzed method holes for current_mmethod
2401 vivien   1.1.2.1             Set mm_holes = (Set)pig.odi.skippedCS;
2402 vivien   1.1.2.1                 
2403 vivien   1.1.2.1             // We remove the call site that we are going to analyze
2404 vivien   1.1.2.1             //mm_holes.remove(thehole);
2405 vivien   1.1.2.1             
2406 vivien   1.1.2.1             // Check whether, in the remaining unanalyzed call sites,
2407 vivien   1.1.2.1             // one correspond to the same HMethod or one originally
2408 vivien   1.1.2.1             // corresponds to the same call site.
2409 vivien   1.1.2.1             boolean hm_esc  = false;
2410 vivien   1.1.2.1             if (callsites.size()!=0) hm_esc = true;
2411 vivien   1.1.2.1             unique = true;
2412 vivien   1.1.2.1 
2413 vivien   1.1.2.1             if (hm_esc){
2414 vivien   1.1.2.1                 PANode ret = thehole.ret();
2415 vivien   1.1.2.1                 PANode exc = thehole.exc();
2416 vivien   1.1.2.1                 for (Iterator cs_it=callsites.iterator(); 
2417 vivien   1.1.2.1                      (unique&&(cs_it.hasNext())); )
2418 vivien   1.1.2.1                     {
2419 vivien   1.1.2.1                         MethodHole cur_mh = (MethodHole) cs_it.next();
2420 vivien   1.1.2.1                         if ((cur_mh.ret()==ret)||(cur_mh.exc()==exc))
2421 vivien   1.1.2.1                             unique = false;
2422 vivien   1.1.2.1                     }
2423 vivien   1.1.2.1             }
2424 vivien   1.1.2.1 
2425 vivien   1.1.2.1             System.out.println("MethodHole : " + thehole);
2426 vivien   1.1.2.1 
2427 vivien   1.1.2.1 
2428 vivien   1.1.2.1             if (hm_esc==false){
2429 vivien   1.1.2.1                 // No more unanalyzed call sites refer to the same
2430 vivien   1.1.2.1                 // HMethod than the actual call site. We safely
2431 vivien   1.1.2.1                 // remove this HMethod from the escaping ones.
2432 vivien   1.1.2.1                 //
2433 vivien   1.1.2.1                 // CAUTION: we make the assumption that if a call
2434 vivien   1.1.2.1                 // site on method hm is unanalyzed and appears in
2435 vivien   1.1.2.1                 // pig.odi.skippedCS, this is also the case for all
2436 vivien   1.1.2.1                 // the (unanalyzed) call sites on method hm.
2437 vivien   1.1.2.1 
2438 vivien   1.1.2.1                 System.out.println("No other call sites refer to the same hmethod");
2439 vivien   1.1.2.1                 System.out.println("Removing " + hm);
2440 vivien   1.1.2.1                 
2441 vivien   1.1.2.1                 Set oldhole = new HashSet();
2442 vivien   1.1.2.1                 oldhole.add(hm);
2443 vivien   1.1.2.1                 pig.G.e.removeMethodHoles(oldhole);
2444 vivien   1.1.2.1                 // tbu to be optimized with singleton...
2445 vivien   1.1.2.1             }
2446 vivien   1.1.2.1             else{
2447 vivien   1.1.2.1 //              System.out.println("AT LEAST one other call sites refer to the same hmethod "
2448 vivien   1.1.2.1 //                                 + callsites);
2449 vivien   1.1.2.1 
2450 vivien   1.1.2.1                 // Nodes reachable from the call site we are going to analyze.
2451 vivien   1.1.2.1                 Set reachable = pig.G.reachableNodes(arguments);
2452 vivien   1.1.2.1 //              System.out.println("Nodes escaping through the call site " +
2453 vivien   1.1.2.1 //                                 " we are going to analyze : " +
2454 vivien   1.1.2.1 //                                 reachable);
2455 vivien   1.1.2.1                 
2456 vivien   1.1.2.1                 // Nodes reachable from perturbing call sites.
2457 vivien   1.1.2.1                 HashSet hmnodes = new HashSet();
2458 vivien   1.1.2.1                 HashSet hmnodes_ret = new HashSet(); 
2459 vivien   1.1.2.1                 HashSet hmnodes_exc = new HashSet(); 
2460 vivien   1.1.2.1                 PANode ret = thehole.ret();
2461 vivien   1.1.2.1                 PANode exc = thehole.exc();
2462 vivien   1.1.2.1 
2463 cananian 1.9                     for(Object mhO : callsites){
2464 cananian 1.9                         MethodHole mh = (MethodHole) mhO;
2465 vivien   1.1.2.1                     hmnodes_ret.addAll(mh.parameters());
2466 vivien   1.1.2.1                     hmnodes_exc.addAll(mh.parameters());
2467 vivien   1.1.2.1                     hmnodes.addAll(mh.arguments());
2468 vivien   1.1.2.1                     if (mh.ret()!=null){
2469 vivien   1.1.2.1                         if (mh.ret()!=ret){
2470 vivien   1.1.2.1                             hmnodes_ret.add(mh.ret());
2471 vivien   1.1.2.1                             hmnodes_exc.add(mh.ret());
2472 vivien   1.1.2.1                         }
2473 vivien   1.1.2.1                         else{
2474 vivien   1.1.2.1                             hmnodes_exc.add(mh.ret());
2475 vivien   1.1.2.1                         }
2476 vivien   1.1.2.1                     }
2477 vivien   1.1.2.1                     if (mh.exc()!=null){
2478 vivien   1.1.2.1                         if (mh.exc()!=exc){
2479 vivien   1.1.2.1                             hmnodes_ret.add(mh.exc());
2480 vivien   1.1.2.1                             hmnodes_exc.add(mh.exc());
2481 vivien   1.1.2.1                         }
2482 vivien   1.1.2.1                         else{
2483 vivien   1.1.2.1                             hmnodes_ret.add(mh.exc());
2484 vivien   1.1.2.1                         }
2485 vivien   1.1.2.1                     }
2486 vivien   1.1.2.1                 }
2487 vivien   1.1.2.1                 Set perturbed = pig.G.reachableNodes(hmnodes);
2488 vivien   1.1.2.1 //              System.out.println("Nodes escaping through other call sites " +
2489 vivien   1.1.2.1 //                                 " with same hmethod : " +
2490 vivien   1.1.2.1 //                                 perturbed);
2491 vivien   1.1.2.1 
2492 vivien   1.1.2.1                 // Nodes reachable from the call site we are going to
2493 vivien   1.1.2.1                 // analyze but not from perturbing call sites. These
2494 vivien   1.1.2.1                 // are the nodes we can update the escape function.
2495 vivien   1.1.2.1                 reachable.removeAll(perturbed);
2496 vivien   1.1.2.1 //              System.out.println("Nodes escaping from the hole that we can update: "
2497 vivien   1.1.2.1 //                                 + reachable);
2498 vivien   1.1.2.1 
2499 vivien   1.1.2.1 
2500 vivien   1.1.2.1                     
2501 vivien   1.1.2.1                 // For debugging purposes
2502 vivien   1.1.2.1 //              for(Iterator hole_it=mm_holes.iterator(); hole_it.hasNext(); ) {
2503 vivien   1.1.2.1 //                  MethodHole hole_m = (MethodHole)hole_it.next();
2504 vivien   1.1.2.1 //                  System.out.print(" ");
2505 vivien   1.1.2.1 //                  for(Iterator par_it=
2506 vivien   1.1.2.1 //                          (pig.G.reachableNodes(hole_m.parameters())).iterator(); 
2507 vivien   1.1.2.1 //                      par_it.hasNext(); ) 
2508 vivien   1.1.2.1 //                      {
2509 vivien   1.1.2.1 //                          PANode __par__it = (PANode) par_it.next();
2510 vivien   1.1.2.1 //                          System.out.print(" " + __par__it);
2511 vivien   1.1.2.1 //                      }
2512 vivien   1.1.2.1 //                  System.out.println(" : " + (hole_m.callsite()).method());
2513 vivien   1.1.2.1 //              }
2514 vivien   1.1.2.1                     
2515 vivien   1.1.2.1                 // Update of escape functions
2516 cananian 1.9                     for (Object upd_nO : reachable){
2517 cananian 1.9                         PANode upd_n = (PANode) upd_nO;
2518 vivien   1.1.2.1                     pig.G.e.removeMethodHole(upd_n, hm);
2519 vivien   1.1.2.1                 }
2520 vivien   1.1.2.1                   
2521 vivien   1.1.2.1                 // Checking whether the params are still escaping
2522 cananian 1.9                     for(Object paramO : arguments) {
2523 cananian 1.9                         PANode param = (PANode) paramO;
2524 vivien   1.1.2.1                     if ((!pig.G.willEscape(param))&&(!pig.G.e.hasEscaped(param)))
2525 vivien   1.1.2.1                         pig.G.e.removeNodeHoleFromAll(param);
2526 vivien   1.1.2.1                 }
2527 vivien   1.1.2.1                 
2528 vivien   1.1.2.1                 // Checking whether the actual return and exception
2529 vivien   1.1.2.1                 // nodes will still be escaping into the HMethod of
2530 vivien   1.1.2.1                 // the current hole, due to some other holes in the
2531 vivien   1.1.2.1                 // caller, if there are some other holes corresponding
2532 vivien   1.1.2.1                 // to the same call site
2533 vivien   1.1.2.1                 if(!unique){
2534 vivien   1.1.2.1                     if(pig.G.reachableNodes(hmnodes_ret).contains(thehole.ret()))
2535 vivien   1.1.2.1                         // Still going to escape
2536 vivien   1.1.2.1                         ODInterProcPA.ret_strong_update = false;
2537 vivien   1.1.2.1                     else
2538 vivien   1.1.2.1                         ODInterProcPA.ret_strong_update = true;
2539 vivien   1.1.2.1                     
2540 vivien   1.1.2.1                     if(pig.G.reachableNodes(hmnodes_exc).contains(thehole.exc()))
2541 vivien   1.1.2.1                         // Still going to escape
2542 vivien   1.1.2.1                         ODInterProcPA.exc_strong_update = false;
2543 vivien   1.1.2.1                     else
2544 vivien   1.1.2.1                         ODInterProcPA.exc_strong_update = true;
2545 vivien   1.1.2.1                 }
2546 vivien   1.1.2.1             }
2547 vivien   1.1.2.1                 
2548 vivien   1.1.2.1             // The method-holes set is updated.
2549 vivien   1.1.2.1             pig.odi.skippedCS = mm_holes;
2550 vivien   1.1.2.1 
2551 vivien   1.1.2.1             ODParIntGraphPair pp = 
2552 vivien   1.1.2.1                 ODInterProcPA.analyze_call(pa, mm,
2553 vivien   1.1.2.1                                            thehole.callsite(), pig, thehole,
2554 vivien   1.1.2.1                                            false,
2555 vivien   1.1.2.1                                            unique);    
2556 vivien   1.1.2.1                 
2557 vivien   1.1.2.1             pig = pp.pig[0];
2558 vivien   1.1.2.1             //tbu
2559 vivien   1.1.2.1             pa.hash_proc_int_d[pa.current_analysis_depth].put(mm,pig);
2560 vivien   1.1.2.1 //          ParIntGraph new_pig = (ODParIntGraph) pig.clone();
2561 vivien   1.1.2.1 //          ODParIntGraph new_pig = pp.pig[1];
2562 vivien   1.1.2.1 //          if(mm.getHMethod().getReturnType().isPrimitive())
2563 vivien   1.1.2.1 //              new_pig.G.r.clear();
2564 vivien   1.1.2.1 //          if(mm.getHMethod().getExceptionTypes().length == 0)
2565 vivien   1.1.2.1 //              new_pig.G.excp.clear();
2566 vivien   1.1.2.1 //          pa.hash_proc_ext_d[pa.current_analysis_depth].put(mm,new_pig);
2567 vivien   1.1.2.1 //          System.out.println("  pig after analysis and cleaning" + pig);
2568 vivien   1.1.2.1     }
2569 vivien   1.1.2.1         while(holefound);
2570 vivien   1.1.2.1         System.out.println("  pig after WHOLE analysis");
2571 vivien   1.1.2.1         System.out.println(pig);
2572 vivien   1.1.2.1 
2573 vivien   1.1.2.1         prepare_exit(mm);
2574 vivien   1.1.2.1     }
2575 vivien   1.1.2.1 
2576 vivien   1.1.2.1 
2577 vivien   1.1.2.1 
2578 vivien   1.1.2.1 }
2579 vivien   1.1.2.1 
2580 vivien   1.1.2.1         
2581 cananian 1.2