1 salcianu 1.1 // AllocSyncOptCompStage.java, created Fri Apr 18 22:13:12 2003 by salcianu
  2 salcianu 1.1 // Copyright (C) 2003 Alexandru Salcianu <salcianu@MIT.EDU>
  3 salcianu 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 salcianu 1.1 package harpoon.Analysis.PointerAnalysis;
  5 salcianu 1.1 
  6 salcianu 1.1 import harpoon.ClassFile.HMethod;
  7 salcianu 1.1 
  8 salcianu 1.1 import harpoon.Analysis.PointerAnalysis.MAInfo;
  9 salcianu 1.1 import harpoon.Analysis.PointerAnalysis.MAInfo.MAInfoOptions;
 10 salcianu 1.1 
 11 salcianu 1.1 import harpoon.Analysis.MetaMethods.MetaCallGraph;
 12 salcianu 1.1 import harpoon.Analysis.MetaMethods.MetaMethod;
 13 salcianu 1.1 
 14 salcianu 1.1 import harpoon.Main.CompilerState;
 15 salcianu 1.1 import harpoon.Main.CompilerStage;
 16 salcianu 1.1 import harpoon.Main.CompilerStageEZ;
 17 salcianu 1.1 import harpoon.Main.CompStagePipeline;
 18 salcianu 1.1 import harpoon.Util.Options.Option;
 19 salcianu 1.1 
 20 salcianu 1.1 import java.util.List;
 21 salcianu 1.1 import java.util.LinkedList;
 22 salcianu 1.1 import java.util.Set;
 23 salcianu 1.2 import java.util.HashSet;
 24 salcianu 1.1 import java.util.Iterator;
 25 salcianu 1.1 
 26 salcianu 1.1 
 27 salcianu 1.1 /**
 28 salcianu 1.1  * <code>AllocSyncOptCompStage</code>
 29 salcianu 1.1  * 
 30 salcianu 1.1  * @author  Alexandru Salcianu <salcianu@MIT.EDU>
 31 cananian 1.4  * @version $Id: AllocSyncOptCompStage.java,v 1.4 2004/02/08 03:20:02 cananian Exp $
 32 salcianu 1.1  */
 33 salcianu 1.1 public class AllocSyncOptCompStage extends CompilerStageEZ {
 34 salcianu 1.1 
 35 salcianu 1.1     /** Returns a compiler stage consisting of the sequential
 36 salcianu 1.1         composition of a pointer analysis stage and a stack/heap
 37 salcianu 1.1         allocation and sync removal optimization stage. */
 38 salcianu 1.1     public static CompilerStage getFullStage() {
 39 salcianu 1.1         final CompilerStage optStage = new AllocSyncOptCompStage();
 40 salcianu 1.1         return 
 41 salcianu 1.1             new CompStagePipeline(new PointerAnalysisCompStage(true),
 42 salcianu 1.1                                   optStage) {
 43 salcianu 1.1             public boolean enabled() { return optStage.enabled(); }
 44 salcianu 1.1         };
 45 salcianu 1.1     }
 46 salcianu 1.1 
 47 salcianu 1.1 
 48 salcianu 1.1     public AllocSyncOptCompStage() { super("alloc-sync-opt"); }
 49 salcianu 1.1 
 50 salcianu 1.1     private MAInfoOptions maio = new MAInfoOptions();
 51 salcianu 1.1     private boolean SHOW_ALLOC_PROPERTIES = false;
 52 salcianu 1.1     
 53 salcianu 1.1     public List/*<Option>*/ getOptions() {
 54 salcianu 1.1         List/*<Option>*/ opts = new LinkedList/*<Option>*/();
 55 salcianu 1.1         
 56 salcianu 1.1         opts.add(new Option("stack-alloc", "<policy>", "<inlining-depth>",
 57 salcianu 1.1                             "Stack allocation policy: 1 (not in loops) | 2 (whenever it's possible); the optional argument <inlining-depth> specifies the maximul level of inlining for improving the stack allocation opportunities (no inlining by default)") {
 58 salcianu 1.1             public void action() {
 59 salcianu 1.1                 int policy = Integer.parseInt(getArg(0));
 60 salcianu 1.1                 switch(policy) {
 61 salcianu 1.1                 case MAInfoOptions.STACK_ALLOCATE_NOT_IN_LOOPS:
 62 salcianu 1.1                 case MAInfoOptions.STACK_ALLOCATE_ALWAYS:
 63 salcianu 1.1                     maio.DO_STACK_ALLOCATION = true;
 64 salcianu 1.1                     maio.STACK_ALLOCATION_POLICY = policy;
 65 salcianu 1.1                     // see if any inlining depth is specified
 66 salcianu 1.1                     if(getOptionalArg(0) != null) {
 67 salcianu 1.1                         int depth = Integer.parseInt(getOptionalArg(0));
 68 salcianu 1.1                         assert depth >= 0 : "Invalid inlining depth " + depth;
 69 salcianu 1.1                         maio.DO_INLINING_FOR_SA = true;
 70 salcianu 1.1                         maio.MAX_INLINING_LEVEL = depth;
 71 salcianu 1.1                     }
 72 salcianu 1.1                     break;
 73 salcianu 1.1                 default:
 74 salcianu 1.1                     System.err.println("Unknown stack allocation policy " +
 75 salcianu 1.1                                        policy);
 76 salcianu 1.1                     System.exit(1);
 77 salcianu 1.1                 }
 78 salcianu 1.1             }
 79 salcianu 1.1         });
 80 salcianu 1.1         
 81 salcianu 1.1         opts.add(new Option("thread-alloc", "", "<inlining-depth>",
 82 salcianu 1.1                             "Thread allocation; the optional argument <inlining-depth> specifies the maximul level of inlining for improving the thread allocation opportunities (no inlining by default)") {
 83 salcianu 1.1             public void action() { 
 84 salcianu 1.1                 maio.DO_THREAD_ALLOCATION = true;
 85 salcianu 1.1                 if(getOptionalArg(0) != null) {
 86 salcianu 1.1                     int depth = Integer.parseInt(getOptionalArg(0));
 87 salcianu 1.1                     assert depth >= 0 : "Invalid inlining depth " + depth;
 88 salcianu 1.1                     maio.DO_INLINING_FOR_TA = true;
 89 salcianu 1.1                     // TODO: currently, we have the same
 90 salcianu 1.1                     // MAX_INLINING_LEVEL for both SA and TA; they
 91 salcianu 1.1                     // should be either condensed in a single option;
 92 salcianu 1.1                     // or separated.
 93 salcianu 1.1                     maio.MAX_INLINING_LEVEL = depth;
 94 salcianu 1.1                 }
 95 salcianu 1.1             }
 96 salcianu 1.1         });
 97 salcianu 1.1 
 98 salcianu 1.1         opts.add(new Option("thread-arg-prealloc",
 99 salcianu 1.1                             "Preallocate thread parameters in thread local heap; DISCOURAGED!  Makes sense only in the context of thread allocation.") {
100 salcianu 1.1             public void action() { maio.DO_PREALLOCATION = true; }
101 salcianu 1.1         });
102 salcianu 1.1         
103 salcianu 1.1         opts.add(new Option("sync-removal", "", "wit",
104 salcianu 1.2                             "Synchronization removal optimization; if optional argument \"wit\" is present, use the inter-thread pointer analysis (unrecommended).") {
105 salcianu 1.1             public void action() {
106 salcianu 1.1                 maio.GEN_SYNC_FLAG = true;
107 salcianu 1.1                 if(getOptionalArg(0) != null) {
108 salcianu 1.1                     assert getOptionalArg(0).equals("wit") :
109 salcianu 1.1                         "Unknown optional arg for sync-removal" +
110 salcianu 1.1                         getOptionalArg(0);
111 salcianu 1.1                     maio.USE_INTER_THREAD = true;
112 salcianu 1.1                 }
113 salcianu 1.1                 // make sure we use Runtime2 - Runtime1 disconsiders
114 salcianu 1.1                 // the noSync flags
115 salcianu 1.1                 System.setProperty("harpoon.runtime", "2");
116 salcianu 1.1             }
117 salcianu 1.1         });
118 salcianu 1.1         
119 salcianu 1.1         opts.add(new Option("show-ap", "Show alocation properties") {
120 salcianu 1.1             public void action() { SHOW_ALLOC_PROPERTIES = true; }
121 salcianu 1.1         });
122 salcianu 1.2 
123 salcianu 1.2         opts.add(new Option("pa-optimize-all", "Optimize all code, including the static initializers (by default, optimize only code reachable from the main method)") {
124 salcianu 1.2             public void action() { OPTIMIZE_ALL = true; }
125 salcianu 1.2         });
126 salcianu 1.1         
127 salcianu 1.1         return opts;
128 salcianu 1.1     }
129 salcianu 1.1     
130 salcianu 1.2     /** Controls whether we optimize all the code or not.  By default,
131 salcianu 1.2         do not optimize the static initializers - some of them are
132 salcianu 1.2         really big (ex: jaca.util.Locale) and there is little interest
133 salcianu 1.2         in optimizing them anyway: they are executed only once.*/
134 salcianu 1.2     private boolean OPTIMIZE_ALL = false;
135 salcianu 1.1     
136 salcianu 1.1     public boolean enabled() {
137 salcianu 1.1         return
138 salcianu 1.1             maio.DO_STACK_ALLOCATION ||
139 salcianu 1.1             maio.DO_THREAD_ALLOCATION ||
140 salcianu 1.1             maio.GEN_SYNC_FLAG;
141 salcianu 1.1     }
142 salcianu 1.1     
143 salcianu 1.1     protected void real_action() {
144 salcianu 1.1         PointerAnalysis pa = 
145 salcianu 1.1             (PointerAnalysis) attribs.get("PointerAnalysis");
146 salcianu 1.1         
147 salcianu 1.1         MetaCallGraph mcg = pa.getMetaCallGraph();
148 salcianu 1.2 
149 salcianu 1.2         Set/*<MetaMethod>*/ mms = 
150 salcianu 1.2             OPTIMIZE_ALL ? mcg.getAllMetaMethods() : 
151 salcianu 1.3             mcg.transitiveSucc(mainAndRuns(mcg));
152 salcianu 1.2 
153 salcianu 1.2         time_analysis(pa, mms);
154 salcianu 1.1         
155 salcianu 1.2         System.out.println("MAInfo options: ");
156 salcianu 1.2         maio.print("\t");
157 salcianu 1.2         
158 salcianu 1.2         long g_tstart = time();
159 salcianu 1.2         MAInfo mainfo = new MAInfo(pa, hcf, linker, mms, maio);
160 salcianu 1.2         System.out.println("GENERATION OF MA INFO TIME  : " +
161 salcianu 1.2                            (time() - g_tstart) + "ms");
162 salcianu 1.2         System.out.println("===================================\n");
163 salcianu 1.2         
164 salcianu 1.2         if(SHOW_ALLOC_PROPERTIES) // show allocation policies
165 salcianu 1.2             mainfo.print();
166 salcianu 1.3     }
167 salcianu 1.3 
168 salcianu 1.3     private Set/*<MetaMethod>*/ mainAndRuns(MetaCallGraph mcg) {
169 salcianu 1.3         Set roots = new HashSet();
170 salcianu 1.3         roots.add(new MetaMethod(mainM, true));
171 salcianu 1.3         roots.addAll(mcg.getRunMetaMethods());
172 salcianu 1.3 
173 salcianu 1.3         System.out.println("MAINANDRUNS: " + roots);
174 salcianu 1.3 
175 salcianu 1.3         return roots;
176 salcianu 1.2     }
177 salcianu 1.2 
178 salcianu 1.2     // time the pointer analysis over all (meta)methods from mms. 
179 salcianu 1.2     private void time_analysis(PointerAnalysis pa, Set/*<MetaMethod>*/ mms) {
180 salcianu 1.2         // The following loop times the analysis of the relevant part
181 salcianu 1.2         // of the program (i.e., methods from mms).  Doing it here,
182 salcianu 1.2         // before any optimization, allows us to time it accurately.
183 salcianu 1.1         long g_tstart = time();
184 salcianu 1.2         if(OPTIMIZE_ALL) {
185 cananian 1.4             for(Object mmO : mms) {
186 cananian 1.4                 MetaMethod mm = (MetaMethod) mmO;
187 salcianu 1.2                 if(!analyzable(mm)) continue;
188 salcianu 1.2                 pa.getIntParIntGraph(mm);
189 salcianu 1.2             }
190 salcianu 1.1         }
191 salcianu 1.2         else pa.getIntParIntGraph(new MetaMethod(mainM, true));
192 salcianu 1.1         System.out.println("Intrathread Analysis time: " +
193 salcianu 1.1                            (time() - g_tstart) + "ms");
194 salcianu 1.1         System.out.println("===================================\n");
195 salcianu 1.1         
196 salcianu 1.1         if (maio.USE_INTER_THREAD) {
197 salcianu 1.1             g_tstart = System.currentTimeMillis();
198 cananian 1.4             for(Object mmO : mms) {
199 cananian 1.4                 MetaMethod mm = (MetaMethod) mmO;
200 salcianu 1.1                 if(!analyzable(mm)) continue;
201 salcianu 1.1                     pa.getIntThreadInteraction(mm);
202 salcianu 1.1             }
203 salcianu 1.1             System.out.println("Interthread Analysis time: " +
204 salcianu 1.1                                (time() - g_tstart) + "ms");
205 salcianu 1.1             System.out.println("===================================\n");
206 salcianu 1.1         }
207 salcianu 1.1     }
208 salcianu 1.2 
209 salcianu 1.1 
210 salcianu 1.1     // TODO: change this to invoke hcf.convert and check result against null
211 salcianu 1.1     private static boolean analyzable(MetaMethod mm) {
212 salcianu 1.1         HMethod hm = mm.getHMethod();
213 salcianu 1.1         if(java.lang.reflect.Modifier.isNative(hm.getModifiers()))
214 salcianu 1.1             return false;
215 salcianu 1.1         if(java.lang.reflect.Modifier.isAbstract(hm.getModifiers()))
216 salcianu 1.1             return false;
217 salcianu 1.1         return true;
218 salcianu 1.1     }
219 salcianu 1.1 
220 salcianu 1.1     private static long time() {
221 salcianu 1.1         return System.currentTimeMillis();
222 salcianu 1.1     }    
223 salcianu 1.1 }