1 pnkfelix 1.1.2.1   // SAMain.java, created Mon Aug  2 19:41:06 1999 by pnkfelix
  2 pnkfelix 1.1.2.1   // Copyright (C) 1999 Felix S. Klock II <pnkfelix@mit.edu>
  3 pnkfelix 1.1.2.1   // Licensed under the terms of the GNU GPL; see COPYING for details.
  4 pnkfelix 1.1.2.1   package harpoon.Main;
  5 pnkfelix 1.1.2.1   
  6 cananian 1.12      import harpoon.Analysis.AbstractClassFixupRelinker;
  7 pnkfelix 1.1.2.1   import harpoon.ClassFile.CachingCodeFactory;
  8 pnkfelix 1.1.2.1   import harpoon.ClassFile.HClass;
  9 pnkfelix 1.1.2.1   import harpoon.ClassFile.HCodeFactory;
 10 pnkfelix 1.1.2.1   import harpoon.ClassFile.HMethod;
 11 cananian 1.1.2.54  import harpoon.ClassFile.Linker;
 12 cananian 1.1.2.54  import harpoon.ClassFile.Loader;
 13 cananian 1.1.2.96  import harpoon.ClassFile.NoSuchClassException;
 14 cananian 1.1.2.101 import harpoon.ClassFile.Relinker;
 15 salcianu 1.45      import harpoon.IR.Quads.QuadWithTry;
 16 salcianu 1.31      import harpoon.IR.Quads.QuadNoSSA;
 17 salcianu 1.45      import harpoon.IR.Quads.QuadSSI;
 18 salcianu 1.38      import harpoon.Backend.Backend;
 19 witchel  1.1.2.81  import harpoon.Backend.Generic.Frame;
 20 cananian 1.1.2.21  import harpoon.Analysis.ClassHierarchy;
 21 cananian 1.1.2.92  import harpoon.Analysis.CallGraph;
 22 salcianu 1.1.2.70  import harpoon.Analysis.Quads.CallGraphImpl;
 23 cananian 1.1.2.93  import harpoon.Analysis.Quads.CallGraphImpl2;
 24 cananian 1.1.2.29  import harpoon.Analysis.Quads.QuadClassHierarchy;
 25 bdemsky  1.1.2.121 
 26 cananian 1.61      import net.cscott.jutil.CombineIterator;
 27 cananian 1.61      import net.cscott.jutil.Default;
 28 cananian 1.1.2.119 import harpoon.Util.ParseUtil;
 29 pnkfelix 1.1.2.4   import harpoon.Util.Util;
 30 pnkfelix 1.1.2.1   
 31 salcianu 1.33      import harpoon.Backend.Runtime1.AllocationStrategy;
 32 salcianu 1.33      import harpoon.Backend.Runtime1.AllocationStrategyFactory;
 33 salcianu 1.33      
 34 salcianu 1.23      import harpoon.IR.Quads.Quad;
 35 salcianu 1.47      
 36 salcianu 1.48      import harpoon.Instrumentation.AllocationStatistics.AllocationInstrCompStage;
 37 wbeebee  1.1.2.113 import harpoon.Analysis.Realtime.Realtime;
 38 salcianu 1.47      import harpoon.Analysis.MemOpt.PreallocOpt;
 39 salcianu 1.51      import harpoon.Analysis.PointerAnalysis.PointerAnalysisCompStage;
 40 salcianu 1.54      import harpoon.Analysis.PointerAnalysis.AllocSyncOptCompStage;
 41 salcianu 1.47      
 42 salcianu 1.49      import harpoon.Util.Options.Option;
 43 salcianu 1.49      
 44 cananian 1.1.2.25  import java.lang.reflect.Modifier;
 45 cananian 1.1.2.55  import java.util.Arrays;
 46 cananian 1.1.2.55  import java.util.Collections;
 47 bdemsky  1.1.2.121 import java.util.Collection;
 48 salcianu 1.49      import java.util.Iterator;
 49 salcianu 1.49      import java.util.Set;
 50 cananian 1.1.2.55  import java.util.HashSet;
 51 cananian 1.1.2.55  import java.util.List;
 52 salcianu 1.48      import java.util.LinkedList;
 53 salcianu 1.19      import java.util.Map;
 54 salcianu 1.21      import java.util.HashMap;
 55 salcianu 1.49      
 56 cananian 1.1.2.55  import java.io.File;
 57 cananian 1.1.2.55  import java.io.FileInputStream;
 58 cananian 1.1.2.55  import java.io.FileOutputStream;
 59 cananian 1.1.2.55  import java.io.IOException;
 60 pnkfelix 1.1.2.5   import java.io.ObjectInputStream;
 61 pnkfelix 1.1.2.5   import java.io.ObjectOutputStream;
 62 cananian 1.1.2.55  import java.io.PrintStream;
 63 salcianu 1.48      
 64 pnkfelix 1.1.2.1   /**
 65 pnkfelix 1.1.2.1    * <code>SAMain</code> is a program to compile java classes to some
 66 pnkfelix 1.1.2.1    * approximation of StrongARM assembly.  It is for development testing
 67 pnkfelix 1.1.2.1    * purposes, not production use.
 68 pnkfelix 1.1.2.1    * 
 69 pnkfelix 1.1.2.1    * @author  Felix S. Klock II <pnkfelix@mit.edu>
 70 cananian 1.62       * @version $Id: SAMain.java,v 1.62 2004/02/08 03:21:38 cananian Exp $
 71 pnkfelix 1.1.2.1    */
 72 pnkfelix 1.1.2.1   public class SAMain extends harpoon.IR.Registration {
 73 pnkfelix 1.1.2.1    
 74 jwhaley  1.1.2.86      static boolean OPTIMIZE = false;
 75 jwhaley  1.1.2.86      static boolean LOOPOPTIMIZE = false;
 76 salcianu 1.43          static boolean QUIET = false;
 77 salcianu 1.38      
 78 salcianu 1.38          /** Backend kind.  Has to be one of the constants defined in
 79 salcianu 1.38              <code>harpoon.Backend.Backend</code>;
 80 salcianu 1.38              <code>Backend.PRECISEC</code> by default.  */
 81 salcianu 1.38          static String BACKEND = Backend.PRECISEC;
 82 salcianu 1.23      
 83 jwhaley  1.1.2.86      static String className;
 84 cananian 1.1.2.96      static String rootSetFilename;
 85 cananian 1.1.2.96  
 86 kkz      1.1.2.163     // Support for precise garbage collection
 87 kkz      1.1.2.163     static boolean PRECISEGC = false;
 88 kkz      1.1.2.138     static boolean MULTITHREADED = false;
 89 salcianu 1.43      
 90 cananian 1.58          private static List<CompilerStage> stages;
 91 bdemsky  1.1.2.73  
 92 pnkfelix 1.1.2.1       public static void main(String[] args) {
 93 salcianu 1.48              buildCompilerPipeline();
 94 salcianu 1.53              
 95 cananian 1.58              List<Option> allOptions = getAllOptions();
 96 salcianu 1.52              parseOpts(args, allOptions);
 97 salcianu 1.53              
 98 salcianu 1.39              if(className == null) {
 99 salcianu 1.39                  System.err.println("must pass a class to be compiled");
100 salcianu 1.53                  System.err.println("Use option \"-h\" to find all options");
101 salcianu 1.39                  System.exit(1);
102 salcianu 1.39              }
103 salcianu 1.53              
104 salcianu 1.39              checkOptionConsistency();
105 salcianu 1.53              
106 salcianu 1.52              CompilerState cs = CompilerState.EMPTY_STATE;
107 salcianu 1.48      
108 cananian 1.62              for(CompilerStage stage : stages) {
109 salcianu 1.53                  if(stage.enabled()) {
110 salcianu 1.53                      System.out.println("Execute stage " + stage.name());
111 salcianu 1.53                      cs = stage.action(cs);
112 salcianu 1.53                  }
113 salcianu 1.48              }
114 salcianu 1.48          }
115 salcianu 1.48      
116 salcianu 1.48      
117 salcianu 1.48          private static void addStage(CompilerStage cs) { stages.add(cs); }
118 salcianu 1.48          
119 salcianu 1.48          private static void buildCompilerPipeline() {
120 cananian 1.58              stages = new LinkedList<CompilerStage>();
121 salcianu 1.48      
122 salcianu 1.54              // build a "nascent" compiler state: 
123 salcianu 1.54              // main method, root set, linker and frame
124 salcianu 1.52              addStage(new BuildInitialCompState());
125 salcianu 1.52      
126 salcianu 1.54              // add code factory, i.e., parse the code into QuadWithTry IR;
127 salcianu 1.54              // also build class hierarchy
128 salcianu 1.48              addStage(new BuildQuadForm());
129 salcianu 1.50              // At this point in the pipeline, we have a full compiler
130 salcianu 1.50              // state (including class hierarchy). Let it roll!
131 salcianu 1.48      
132 salcianu 1.50              // quad-form analyses
133 salcianu 1.50              buildQuadFormPipeline();
134 salcianu 1.48      
135 salcianu 1.54              // convert quad IR -> tree IR
136 salcianu 1.50              addStage(new LowQuadToTree()); 
137 salcianu 1.48      
138 salcianu 1.50              // tree-form analyses
139 salcianu 1.48              buildTreeFormPipeline();
140 salcianu 1.48      
141 salcianu 1.50              // final compilation stage
142 salcianu 1.48              addStage(new CodeGenerator());
143 salcianu 1.48          }
144 salcianu 1.48      
145 salcianu 1.48      
146 salcianu 1.48          private static void buildQuadFormPipeline() {
147 salcianu 1.54              // adds a stage that does pointer analysis and uses its
148 salcianu 1.54              // results for memory allocation, sync removal, and/or RTJ
149 salcianu 1.54              // programs debug and optimization
150 salcianu 1.54              addStage(PointerAnalysisCompStage.getPAAndAppsStage());
151 salcianu 1.51      
152 salcianu 1.54              // allocation instrumentation stage
153 salcianu 1.48              AllocationInstrCompStage aics = new AllocationInstrCompStage();
154 salcianu 1.48              addStage(aics);
155 cananian 1.58              // memory preallocation via incompatibility analysis
156 salcianu 1.48              addStage(new PreallocOpt.QuadPass(aics));
157 salcianu 1.51      
158 salcianu 1.48              addStage(new EventDrivenTransformation.QuadPass1());
159 salcianu 1.48              addStage(new RoleInference());
160 cananian 1.59              addStage(new DynamicSyncRemoval.QuadPass());
161 salcianu 1.48              addStage(new Transactions.QuadPass());
162 salcianu 1.48              addStage(new Realtime.QuadPass());
163 salcianu 1.48              addStage(new MZFCompilerStage());
164 salcianu 1.48              addStage(new MIPSOptimizations.QuadPass());
165 salcianu 1.54      
166 salcianu 1.54              // general quad optimizations (disabled by default)
167 salcianu 1.48              addStage(new GeneralQuadOptimizations());
168 salcianu 1.54      
169 salcianu 1.48              addStage(new EventDrivenTransformation.QuadPass2());
170 salcianu 1.48              addStage(new WriteBarriers.WBQuadPass());
171 salcianu 1.48              addStage(new WriteBarriers.DynamicWBQuadPass());
172 salcianu 1.48      
173 salcianu 1.54              // common processing and small optimizations
174 salcianu 1.48              addStage(new RegularQuadPass());
175 salcianu 1.48          }
176 salcianu 1.48      
177 salcianu 1.48      
178 salcianu 1.48          private static void buildTreeFormPipeline() {
179 salcianu 1.48              addStage(new WriteBarriers.WBDynamicWBTreePass());
180 salcianu 1.48              addStage(new PreallocOpt.TreePass());
181 salcianu 1.48              addStage(new Realtime.TreePass());
182 cananian 1.59              addStage(new DynamicSyncRemoval.TreePass());
183 salcianu 1.48              addStage(new Transactions.TreePass());
184 salcianu 1.48      
185 salcianu 1.48              addStage(new RegularTreePass());
186 salcianu 1.48      
187 salcianu 1.48              // special case: the DACache MIPS optimizations allocated
188 salcianu 1.48              // special DACache registers during this phase; I *think* that
189 salcianu 1.48              // we shouldn't touch the tree form after this allocation has
190 salcianu 1.48              // been done, which means it must be the very last thing we
191 salcianu 1.48              // do.  In general, your tree form passes shouldn't be this
192 salcianu 1.48              // fragile!  [CSA 08-apr-2003]
193 salcianu 1.48              addStage(new MIPSOptimizations.TreePass());
194 salcianu 1.48      
195 salcianu 1.54              // perform basic sanity checks on the produced tree form
196 salcianu 1.48              addStage(new RegularCompilerStageEZ("sanity-check-tree") {
197 salcianu 1.48                  protected void real_action() {
198 salcianu 1.48                      hcf = harpoon.Analysis.Tree.DerivationChecker.codeFactory(hcf);
199 salcianu 1.48                      hcf = new CachingCodeFactory(hcf);
200 salcianu 1.48                  }
201 salcianu 1.48              });
202 salcianu 1.48          }
203 salcianu 1.48      
204 salcianu 1.48          
205 jwhaley  1.1.2.86  
206 salcianu 1.48          // ADD YOUR OPTION CONSISTENCY TESTS HERE
207 salcianu 1.48          private static void checkOptionConsistency() {
208 salcianu 1.48              // Check for compatibility of precise gc options.
209 salcianu 1.48              if (PRECISEGC)
210 salcianu 1.48                  assert (BACKEND == Backend.PRECISEC) : 
211 salcianu 1.48                  "Precise gc is only implemented for the precise C backend.";
212 salcianu 1.48              if (MULTITHREADED) {
213 salcianu 1.48                  assert PRECISEGC || Realtime.REALTIME_JAVA :
214 salcianu 1.48                      "Multi-threaded option is valid only for precise gc.";
215 salcianu 1.48                  assert WriteBarriers.wbOptLevel == 0 : 
216 salcianu 1.48                      "Write barrier removal not supported " +
217 salcianu 1.48                      "for multi-threaded programs.";
218 salcianu 1.48              }
219 salcianu 1.48              if (WriteBarriers.WRITEBARRIERS || WriteBarriers.DYNAMICWBS)
220 salcianu 1.48                  assert PRECISEGC : 
221 salcianu 1.48                  "Write barrier options are valid only for precise gc.";
222 salcianu 1.40          }
223 salcianu 1.40      
224 salcianu 1.40      
225 salcianu 1.52          private static void parseOpts(String[] args,
226 cananian 1.58                                        List<Option> allOptions) {
227 salcianu 1.48              PRECISEGC = System.getProperty("harpoon.alloc.strategy", 
228 salcianu 1.48                                             "malloc").equalsIgnoreCase("precise");
229 salcianu 1.48              args = Option.parseOptions(allOptions, args);
230 salcianu 1.48              if(args.length != 0) {
231 salcianu 1.53                  System.err.println("Don't know what to do with " + args[0]);
232 salcianu 1.53                  System.err.println("Use option \"-h\" to find all options");
233 salcianu 1.48                  System.exit(1);
234 salcianu 1.42              }
235 salcianu 1.42          }
236 salcianu 1.42      
237 salcianu 1.42      
238 cananian 1.58          private static List<Option> getAllOptions() {
239 cananian 1.58              List<Option> opts = new LinkedList<Option>();
240 cananian 1.58              Map<String,String> opt2stage = new HashMap<String,String>();
241 cananian 1.62              for(CompilerStage stage : stages){
242 salcianu 1.52                  addOptions(stage, opts, opt2stage);
243 salcianu 1.48              }
244 salcianu 1.48              return opts;
245 salcianu 1.48          }
246 salcianu 1.48      
247 salcianu 1.52      
248 salcianu 1.52          private static void addOptions(CompilerStage stage,
249 cananian 1.58                                         List<Option> allOpts,
250 cananian 1.58                                         Map<String,String> opt2stage) {
251 cananian 1.62              for(Option option : stage.getOptions()) {
252 salcianu 1.48                  String old_stage = 
253 cananian 1.58                      opt2stage.put(option.optionName(), stage.name());
254 salcianu 1.48                  if(old_stage != null) {
255 salcianu 1.48                      System.err.println
256 salcianu 1.48                          ("Ambiguity: Option " + option +
257 salcianu 1.48                           " is defined in two compiler stages: " + 
258 salcianu 1.52                           old_stage + " and " + stage.name());
259 salcianu 1.48                      System.exit(1);
260 salcianu 1.48                  }
261 salcianu 1.48                  allOpts.add(option);
262 salcianu 1.42              }
263 salcianu 1.42          }
264 salcianu 1.42      
265 salcianu 1.42      
266 salcianu 1.48          // construct list of top level compiler options
267 cananian 1.58          private static List<Option> getTopLevelOptions() {
268 cananian 1.58              return Arrays.asList
269 cananian 1.58                  (new Option[] {
270 cananian 1.58                      new Option("c", "<class>", "Compile <class> (required)") {
271 cananian 1.58                          public void action() { className = getArg(0); }
272 cananian 1.58                      },
273 cananian 1.58                      new Option("r", "<rootSetFileName>",
274 salcianu 1.60                                 "Read additional roots (classes and/or methods) from file") {
275 cananian 1.58                          public void action() { rootSetFilename = getArg(0); }
276 cananian 1.58                      },
277 cananian 1.58                      new Option("b", "<backendName>",
278 cananian 1.58                                 "Supported backends are StrongARM (default), MIPS, Sparc, or PreciseC") {
279 cananian 1.58                          public void action() {
280 cananian 1.58                              BACKEND = Options.getBackendID(getArg(0));
281 cananian 1.58                          }
282 cananian 1.58                      },
283 cananian 1.58                      new Option("F", "Enable standard optimizations") {
284 cananian 1.58                          public void action() { OPTIMIZE = true; }
285 cananian 1.58                      },
286 cananian 1.58                      new Option("l", "Loop Optimizations") {
287 cananian 1.58                          public void action() { LOOPOPTIMIZE = true; }
288 cananian 1.58                      },
289 cananian 1.58                      new Option("q", "Quiet mode (status messages not output)") {
290 cananian 1.58                          public void action() { QUIET = true; }
291 cananian 1.58                      },
292 cananian 1.58                      new Option("h", "Print help") {
293 cananian 1.58                          public void action() {
294 cananian 1.58                              SAMain.printHelp(System.out);
295 cananian 1.58                              System.exit(1);
296 cananian 1.58                          }
297 cananian 1.58                      },
298 cananian 1.58                      new Option("m", "Multi-threading support for PreciseGC") {
299 cananian 1.58                          public void action() {
300 cananian 1.58                              MULTITHREADED = true;
301 cananian 1.58                              System.out.println
302 cananian 1.58                                  ("Compiling with precise gc for multiple threads.");
303 cananian 1.58                          }
304 cananian 1.58                      },
305 cananian 1.58                  });
306 salcianu 1.23          }
307 salcianu 1.23      
308 salcianu 1.48          private static void printHelp(PrintStream ps) {
309 cananian 1.58              ps.println("Usage:\n\tjava "+SAMain.class.getName()+" <options>*");
310 salcianu 1.52              ps.println("Options:");
311 cananian 1.58              for(Iterator<CompilerStage> it = stages.iterator(); it.hasNext(); ) {
312 cananian 1.58                  printStageOptions(it.next());
313 salcianu 1.52              }
314 salcianu 1.52          }
315 salcianu 1.52      
316 salcianu 1.52          private static void printStageOptions(CompilerStage stage) {
317 cananian 1.62              for(Option option : stage.getOptions()) {
318 salcianu 1.52                  option.printHelp(System.out);
319 salcianu 1.48              }
320 pnkfelix 1.1.2.10      }
321 pnkfelix 1.1.2.10  
322 salcianu 1.36          protected static void printHelp() {
323 salcianu 1.48              printHelp(System.out);
324 pnkfelix 1.1.2.13      }
325 pnkfelix 1.1.2.13  
326 salcianu 1.48          protected static void message(String msg) {
327 salcianu 1.48              if(!QUIET) System.out.print(msg);
328 salcianu 1.48          }
329 salcianu 1.47      
330 salcianu 1.48          protected static void messageln(String msg) {
331 salcianu 1.48              if(!QUIET) System.out.println(msg);
332 salcianu 1.46          }
333 salcianu 1.52      
334 salcianu 1.52      
335 salcianu 1.52      
336 salcianu 1.53          private static class BuildInitialCompState extends RegularCompilerStageEZ {
337 salcianu 1.52              public BuildInitialCompState() { super("compiler-initialization"); }
338 cananian 1.58              public List<Option> getOptions() { return getTopLevelOptions(); }
339 salcianu 1.52              
340 salcianu 1.52              protected void real_action() { 
341 salcianu 1.52                  // create an initial compiler state
342 salcianu 1.55                  linker = new AbstractClassFixupRelinker(Loader.systemLinker);
343 salcianu 1.55                  mainM  = getMainMethod(linker);          // main method
344 salcianu 1.55                  frame  = construct_frame(mainM);         // target frame
345 salcianu 1.55                  roots  = getRoots(linker, mainM, frame); // set of roots
346 salcianu 1.52              }
347 salcianu 1.52      
348 salcianu 1.52              // returns the main method of the program to compile
349 salcianu 1.52              private static HMethod getMainMethod(Linker linker) {
350 salcianu 1.52                  // find main method
351 salcianu 1.52                  HClass hcl = linker.forName(className);
352 salcianu 1.52                  HMethod mainM;
353 salcianu 1.52                  try {
354 salcianu 1.52                      mainM = hcl.getDeclaredMethod("main","([Ljava/lang/String;)V");
355 salcianu 1.52                  } catch (NoSuchMethodError e) {
356 salcianu 1.52                      throw new Error("Class " + className + " has no main method");
357 salcianu 1.52                  }
358 salcianu 1.52                  assert mainM != null;
359 salcianu 1.52                  assert Modifier.isStatic(mainM.getModifiers()) : 
360 salcianu 1.52                      "main is not static";
361 salcianu 1.52                  assert Modifier.isPublic(mainM.getModifiers()) : 
362 salcianu 1.52                      "main is not public";
363 salcianu 1.52                  
364 salcianu 1.52                  return mainM;
365 salcianu 1.52              }
366 salcianu 1.52              
367 salcianu 1.52      
368 salcianu 1.52              // constructs and returns the target Frame
369 salcianu 1.52              // the frame specifies the combination of target architecture,
370 salcianu 1.52              // runtime, and allocation strategy we want to use.
371 salcianu 1.52              // ADD YOUR FRAME SETTING CODE HERE
372 salcianu 1.52              private static Frame construct_frame(HMethod mainM) {
373 salcianu 1.52                  Frame frame = Backend.getFrame(BACKEND, mainM,
374 salcianu 1.52                                                 getAllocationStrategyFactory());
375 salcianu 1.52              
376 salcianu 1.52                  // check the configuration of the runtime.
377 salcianu 1.52                  // (in particular, the --with-precise-c option)
378 salcianu 1.52                  if (BACKEND == Backend.PRECISEC)
379 salcianu 1.52                      frame.getRuntime().configurationSet.add
380 salcianu 1.52                          ("check_with_precise_c_needed");
381 salcianu 1.52                  else
382 salcianu 1.52                      frame.getRuntime().configurationSet.add
383 salcianu 1.52                          ("check_with_precise_c_not_needed");
384 salcianu 1.52                  
385 salcianu 1.52                  return frame;
386 salcianu 1.52              }
387 salcianu 1.52      
388 salcianu 1.52      
389 salcianu 1.52              // construct the set of roots for the program we compile
390 salcianu 1.52              static Set getRoots(Linker linker, HMethod mainM, Frame frame) {
391 salcianu 1.52                  // ask the runtime which roots it requires.
392 salcianu 1.52                  Set roots = new java.util.HashSet
393 salcianu 1.52                      (frame.getRuntime().runtimeCallableMethods());
394 salcianu 1.52                  
395 salcianu 1.52                  // and our main method is a root, too...
396 salcianu 1.52                  roots.add(mainM);
397 salcianu 1.52                  
398 salcianu 1.52                  // load roots from file (if any)
399 salcianu 1.52                  if (rootSetFilename!=null)
400 salcianu 1.52                      addToRootSet(roots, rootSetFilename, linker);
401 salcianu 1.52                  
402 salcianu 1.52                  // other optimization specific roots
403 salcianu 1.52                  if (EventDrivenTransformation.EVENTDRIVEN) {
404 salcianu 1.52                      roots.add(linker.forName
405 salcianu 1.52                                ("harpoon.Analysis.ContBuilder.Scheduler")
406 salcianu 1.52                                .getMethod("loop",new HClass[0]));
407 salcianu 1.52                  }
408 salcianu 1.52                  
409 salcianu 1.52                  if (Realtime.REALTIME_JAVA)
410 salcianu 1.52                      roots.addAll(Realtime.getRoots(linker));
411 salcianu 1.52                  
412 salcianu 1.52                  return roots;
413 salcianu 1.52              }
414 salcianu 1.52      
415 salcianu 1.52              private static void addToRootSet(final Set roots,
416 salcianu 1.52                                               final String fileName,
417 salcianu 1.52                                               final Linker linker) {
418 salcianu 1.52                  try {
419 salcianu 1.52                      ParseUtil.readResource(fileName, new ParseUtil.StringParser() {
420 salcianu 1.52                          public void parseString(String s)
421 salcianu 1.52                              throws ParseUtil.BadLineException {
422 salcianu 1.52                              if (s.indexOf('(') < 0) // parse as class name.
423 salcianu 1.52                                  roots.add(ParseUtil.parseClass(linker, s));
424 salcianu 1.52                              else // parse as method name.
425 salcianu 1.52                                  roots.add(ParseUtil.parseMethod(linker, s));
426 salcianu 1.52                          }
427 salcianu 1.52                      });
428 salcianu 1.52                  } catch(IOException ex) {
429 salcianu 1.52                      System.err.println("Error reading " + fileName + ": " + ex);
430 salcianu 1.52                      ex.printStackTrace();
431 salcianu 1.52                      System.exit(1);
432 salcianu 1.52                  }
433 salcianu 1.52              }
434 salcianu 1.52          }
435 salcianu 1.52      
436 salcianu 1.52      
437 salcianu 1.52          private static AllocationStrategyFactory getAllocationStrategyFactory() {
438 salcianu 1.52              
439 salcianu 1.52              return new AllocationStrategyFactory() {
440 salcianu 1.52                  public AllocationStrategy getAllocationStrategy(Frame frame) {
441 salcianu 1.52                      
442 salcianu 1.52                      System.out.print("Allocation strategy: ");
443 salcianu 1.52                      
444 salcianu 1.52                      if(AllocationInstrCompStage.INSTRUMENT_ALLOCS && 
445 salcianu 1.52                         (AllocationInstrCompStage.INSTRUMENT_ALLOCS_TYPE == 2)) {
446 salcianu 1.52                          System.out.println("InstrumentedAllocationStrategy");
447 salcianu 1.52                          return new harpoon.Instrumentation.AllocationStatistics.
448 salcianu 1.52                              InstrumentedAllocationStrategy(frame);
449 salcianu 1.52                      }
450 salcianu 1.52                      
451 salcianu 1.52                      if(PreallocOpt.PREALLOC_OPT) {
452 salcianu 1.52                          System.out.println("PreallocAllocationStrategy");
453 salcianu 1.52                          return new harpoon.Analysis.MemOpt.
454 salcianu 1.52                              PreallocAllocationStrategy(frame);
455 salcianu 1.52                      }
456 salcianu 1.52                      
457 salcianu 1.52                      if(Realtime.REALTIME_JAVA) {
458 salcianu 1.52                          System.out.println("RTJ");
459 salcianu 1.52                          return new harpoon.Analysis.Realtime.
460 salcianu 1.52                              RealtimeAllocationStrategy(frame);
461 salcianu 1.52                      }
462 salcianu 1.52      
463 salcianu 1.52                      String alloc_strategy = 
464 cananian 1.56                          System.getProperty("harpoon.alloc.strategy", "bdw");
465 salcianu 1.52      
466 salcianu 1.52                      System.out.println(alloc_strategy);
467 salcianu 1.52      
468 cananian 1.57                      if (frame instanceof harpoon.Backend.PreciseC.Frame) {
469 cananian 1.57                          // these strategies only work with the PreciseC backend
470 cananian 1.57                          if(alloc_strategy.equalsIgnoreCase("nifty"))
471 cananian 1.57                              return new harpoon.Backend.PreciseC.
472 cananian 1.57                                  PGCNiftyAllocationStrategy(frame);
473 cananian 1.57                          
474 cananian 1.57                          if(alloc_strategy.equalsIgnoreCase("niftystats"))
475 cananian 1.57                              return new harpoon.Backend.PreciseC.        
476 cananian 1.57                                  PGCNiftyAllocationStrategyWithStats(frame);
477 cananian 1.57                      } else {
478 cananian 1.57                          // non-precisec version of the 'nifty' alloc strategy
479 cananian 1.57                          if(alloc_strategy.equalsIgnoreCase("nifty"))
480 cananian 1.57                              return new harpoon.Backend.Runtime1.
481 cananian 1.57                                  NiftyAllocationStrategy(frame);
482 cananian 1.57                      }
483 salcianu 1.52                      
484 salcianu 1.52                      if(alloc_strategy.equalsIgnoreCase("bdw"))
485 salcianu 1.52                          return new harpoon.Backend.Runtime1.
486 salcianu 1.52                              BDWAllocationStrategy(frame);
487 salcianu 1.52      
488 salcianu 1.52                      if(alloc_strategy.equalsIgnoreCase("sp"))
489 salcianu 1.52                          return new harpoon.Backend.Runtime1.
490 salcianu 1.52                              SPAllocationStrategy(frame);
491 salcianu 1.52      
492 salcianu 1.52                      if(alloc_strategy.equalsIgnoreCase("precise"))
493 salcianu 1.52                          return new harpoon.Backend.Runtime1.
494 salcianu 1.52                              MallocAllocationStrategy(frame, "precise_malloc");
495 salcianu 1.52      
496 salcianu 1.52                      if(alloc_strategy.equalsIgnoreCase("heapstats"))
497 salcianu 1.52                          return new harpoon.Backend.Runtime1.
498 salcianu 1.52                              HeapStatsAllocationStrategy(frame);
499 salcianu 1.52      
500 salcianu 1.54                      assert alloc_strategy.equalsIgnoreCase("malloc") :
501 salcianu 1.54                          "unknown allocation strategy " + alloc_strategy;
502 salcianu 1.52      
503 salcianu 1.52                      // default, "malloc" strategy.
504 salcianu 1.52                      return
505 salcianu 1.52                          new harpoon.Backend.Runtime1.MallocAllocationStrategy
506 salcianu 1.52                          (frame,
507 salcianu 1.52                           System.getProperty("harpoon.alloc.func", "malloc"));
508 salcianu 1.52                  }
509 salcianu 1.52              };
510 salcianu 1.52          };
511 salcianu 1.52      
512 salcianu 1.52      
513 salcianu 1.40      
514 salcianu 1.48          private static class BuildQuadForm extends RegularCompilerStageEZ {
515 salcianu 1.48              public BuildQuadForm() { super("build-quad-form"); }
516 salcianu 1.53      
517 salcianu 1.48              protected void real_action() {
518 salcianu 1.48                  // default code factory.
519 salcianu 1.48                  hcf = new CachingCodeFactory
520 salcianu 1.48                      (harpoon.IR.Quads.QuadWithTry.codeFactory());
521 salcianu 1.48              
522 salcianu 1.48                  // the new mover will try to put NEWs closer to their
523 salcianu 1.48                  // constructors.  in the words of a PLDI paper, this
524 salcianu 1.48                  // reduces "drag time".  it also improves some analysis
525 salcianu 1.48                  // results. =)
526 salcianu 1.48                  hcf = new harpoon.Analysis.Quads.NewMover(hcf).codeFactory();
527 salcianu 1.48      
528 salcianu 1.48                  if (Realtime.REALTIME_JAVA)
529 salcianu 1.48                      Realtime.setupObject(linker); 
530 salcianu 1.48                  
531 salcianu 1.48                  if(PreallocOpt.PREALLOC_OPT) {
532 salcianu 1.48                      PreallocOpt.updateRoots(roots, linker);
533 salcianu 1.48                      hcf = PreallocOpt.getHCFWithEmptyInitCode(hcf);
534 salcianu 1.48                  }
535 salcianu 1.48                  
536 salcianu 1.48                  // make a rough class hierarchy.
537 salcianu 1.40                  hcf = new CachingCodeFactory(hcf);
538 salcianu 1.40                  classHierarchy = new QuadClassHierarchy(linker, roots, hcf);
539 salcianu 1.48                  
540 salcianu 1.48                  // use the rough class hierarchy to devirtualize as many call
541 salcianu 1.48                  // sites as possible.
542 salcianu 1.48                  hcf = new harpoon.Analysis.Quads.Nonvirtualize
543 salcianu 1.48                      (hcf, new harpoon.Backend.Maps.CHFinalMap(classHierarchy),
544 salcianu 1.48                       classHierarchy).codeFactory();
545 salcianu 1.48                  
546 salcianu 1.48                  handle_class_initializers();
547 salcianu 1.48              }
548 salcianu 1.48      
549 salcianu 1.48              // Class initialization is delicate in an ahead of time compiler.
550 salcianu 1.48              // The JVM deals with it by explicitly testing before each each
551 salcianu 1.48              // class member access whether the class is initialized or not; we
552 salcianu 1.48              // try to be more effcient: we run the initializers of all the
553 salcianu 1.48              // classes from the program before the main method.  Only the code
554 salcianu 1.48              // of the static initializers checks for un-initialized classes;
555 salcianu 1.48              // when the main method is called, all the relevant classes have
556 salcianu 1.48              // been initialized.
557 salcianu 1.48              private void handle_class_initializers() {
558 salcianu 1.55                  // transform the class initializers using the class hierarchy.
559 salcianu 1.55                  String resource = frame.getRuntime().resourcePath
560 salcianu 1.55                      ("init-safe.properties");
561 salcianu 1.55                  hcf = new harpoon.Analysis.Quads.InitializerTransform
562 salcianu 1.55                      (hcf, classHierarchy, linker, resource).codeFactory();
563 salcianu 1.55                  // recompute the hierarchy after transformation.
564 salcianu 1.55                  hcf = new CachingCodeFactory(hcf);
565 salcianu 1.55                  classHierarchy = new QuadClassHierarchy(linker, roots, hcf);
566 salcianu 1.55                  // config checking
567 salcianu 1.55                  frame.getRuntime().configurationSet.add
568 salcianu 1.55                      ("check_with_init_check_needed");
569 salcianu 1.40              }
570 salcianu 1.40          }
571 salcianu 1.40      
572 salcianu 1.40      
573 salcianu 1.48          private static class RegularQuadPass extends RegularCompilerStageEZ {
574 salcianu 1.48              public RegularQuadPass() { super("regular-quad-pass"); }
575 salcianu 1.48      
576 salcianu 1.48              protected void real_action() {
577 salcianu 1.48                  // now we can finally set the (final?) classHierarchy and
578 salcianu 1.48                  // callGraph which the frame will use (among other things,
579 salcianu 1.48                  // for vtable numbering)
580 salcianu 1.48                  frame.setClassHierarchy(classHierarchy);
581 salcianu 1.51      
582 salcianu 1.48                  // virtualize any uncallable methods using the final classhierarchy
583 salcianu 1.48                  // (this keeps us from later getting link errors)
584 salcianu 1.48                  hcf = new harpoon.Analysis.Quads.Virtualize(hcf, classHierarchy)
585 salcianu 1.48                      .codeFactory();
586 salcianu 1.48                  // non-virtualize any final methods -- this used to be done
587 salcianu 1.48                  // in the low-quad translation, but doing so is unsafe unless
588 salcianu 1.48                  // you've got a classHierarchy handy -- you could inadventently
589 salcianu 1.48                  // create a new dangling reference to an uncallable method.
590 salcianu 1.48                  hcf = new harpoon.Analysis.Quads.Nonvirtualize
591 salcianu 1.48                      (hcf, new harpoon.Backend.Maps.CHFinalMap(classHierarchy),
592 salcianu 1.48                       classHierarchy).codeFactory();
593 salcianu 1.48                  
594 salcianu 1.48                  if (LOOPOPTIMIZE)
595 salcianu 1.48                      loop_optimizations();
596 salcianu 1.48                  
597 salcianu 1.48                  hcf = harpoon.IR.LowQuad.LowQuadSSA.codeFactory(hcf);
598 salcianu 1.48              }
599 salcianu 1.48      
600 salcianu 1.48              private void loop_optimizations() {
601 salcianu 1.48                  // XXX: you might have to add a TypeSwitchRemover here, if
602 salcianu 1.48                  //      LoopOptimize doesn't handle TYPESWITCHes. --CSA
603 salcianu 1.48                  System.out.println("Loop Optimizations On");
604 salcianu 1.48                  hcf = harpoon.IR.LowQuad.LowQuadSSI.codeFactory(hcf);
605 salcianu 1.48                  hcf = harpoon.Analysis.LowQuad.Loop.LoopOptimize.codeFactory(hcf);
606 salcianu 1.48                  hcf = harpoon.Analysis.LowQuad.DerivationChecker.codeFactory(hcf);
607 salcianu 1.40              }
608 salcianu 1.40          }
609 salcianu 1.40      
610 salcianu 1.40      
611 salcianu 1.48          // 1. sparse (i.e., SSI) conditional constant propagation
612 salcianu 1.48          // 2. represent native method arraycopy into quad IR (such that
613 salcianu 1.48          // we can optimize it)
614 salcianu 1.48          // 3. inline small methods
615 salcianu 1.48          private static class GeneralQuadOptimizations extends CompilerStageEZ {
616 salcianu 1.48              public GeneralQuadOptimizations() { 
617 salcianu 1.48                  super("general-quad-optimizations");
618 salcianu 1.48              }
619 salcianu 1.48      
620 salcianu 1.53              public boolean enabled() { return OPTIMIZE; }
621 salcianu 1.48      
622 salcianu 1.48              public void real_action() {
623 salcianu 1.48                  // COMMENTED UNTIL BUG DISCOVERED
624 salcianu 1.48                  /*
625 salcianu 1.48                    hcf = new harpoon.Analysis.Quads.DispatchTreeTransformation
626 salcianu 1.48                    (hcf, classHierarchy).codeFactory();
627 salcianu 1.48                  */
628 salcianu 1.48                  hcf = harpoon.IR.Quads.QuadSSI.codeFactory(hcf);
629 salcianu 1.48                  hcf = harpoon.Analysis.Quads.SCC.SCCOptimize.codeFactory(hcf);
630 salcianu 1.48                  hcf = harpoon.IR.Quads.QuadSSA.codeFactory(hcf);
631 salcianu 1.48                  if (Boolean.getBoolean("harpoon.inline.arraycopy")) {
632 salcianu 1.48                      // inline System.arraycopy in particular.
633 salcianu 1.48                      hcf = new harpoon.Analysis.Transactions.ArrayCopyImplementer
634 salcianu 1.48                          (hcf, linker);
635 salcianu 1.48                      hcf = new CachingCodeFactory(hcf);
636 salcianu 1.48                      classHierarchy = new QuadClassHierarchy(linker, roots, hcf);
637 salcianu 1.48                      hcf = new harpoon.Analysis.Quads.ArrayCopyInliner
638 salcianu 1.48                          (hcf, classHierarchy);
639 salcianu 1.48                  } else {
640 salcianu 1.48                      // TODO: why is there a XOR between these two optimizations?
641 salcianu 1.48                      // just inline small methods.
642 salcianu 1.48                      hcf = new harpoon.Analysis.Quads.SmallMethodInliner
643 salcianu 1.48                          (hcf, classHierarchy);
644 salcianu 1.48                  }
645 salcianu 1.48                  hcf = harpoon.IR.Quads.QuadSSI.codeFactory(hcf);
646 salcianu 1.48                  hcf = harpoon.Analysis.Quads.SCC.SCCOptimize.codeFactory(hcf);
647 salcianu 1.48                  hcf = new harpoon.ClassFile.CachingCodeFactory(hcf);
648 salcianu 1.40              }
649 salcianu 1.40          }
650 salcianu 1.40      
651 salcianu 1.48          
652 salcianu 1.48          private static class LowQuadToTree extends RegularCompilerStageEZ {
653 salcianu 1.48              public LowQuadToTree() { super("lowquad-to-tree"); }
654 salcianu 1.40      
655 salcianu 1.48              protected void real_action() {
656 salcianu 1.48                  // low quad -> tree form
657 salcianu 1.48                  // XXX: ToTree doesn't handle TYPESWITCHes right now.
658 salcianu 1.48                  hcf =
659 salcianu 1.48                      new harpoon.Analysis.Quads.TypeSwitchRemover(hcf).
660 salcianu 1.48                      codeFactory();
661 salcianu 1.48                  hcf = harpoon.IR.Tree.TreeCode.codeFactory(hcf, frame);
662 salcianu 1.48                  // Implement the native method call interface. (JNI)
663 salcianu 1.48                  hcf = frame.getRuntime().nativeTreeCodeFactory(hcf);
664 salcianu 1.48                  // put it in canonical form
665 salcianu 1.48                  hcf = harpoon.IR.Tree.CanonicalTreeCode.codeFactory(hcf, frame);
666 salcianu 1.48                  // sanity check
667 salcianu 1.48                  hcf = harpoon.Analysis.Tree.DerivationChecker.codeFactory(hcf);
668 salcianu 1.47              }
669 salcianu 1.47          }
670 salcianu 1.47      
671 salcianu 1.48      
672 salcianu 1.48          private static class RegularTreePass extends RegularCompilerStageEZ {
673 salcianu 1.48              public RegularTreePass() { super("regular-tree-pass"); }
674 salcianu 1.48      
675 salcianu 1.48              protected void real_action() {
676 salcianu 1.48                  if (MULTITHREADED) /* pass to insert GC polling calls */
677 salcianu 1.48                      hcf = harpoon.Backend.Analysis.MakeGCThreadSafe.
678 salcianu 1.48                          codeFactory(hcf, frame);
679 salcianu 1.48                  
680 salcianu 1.48                  // -- general tree form optimizations --
681 salcianu 1.48      
682 salcianu 1.48                  hcf = 
683 salcianu 1.48                      harpoon.Analysis.Tree.AlgebraicSimplification.codeFactory(hcf);
684 salcianu 1.48                  
685 salcianu 1.48                  // CSA 08-apr-2003: this code was turned off in feb 17, 2000 with
686 salcianu 1.48                  //  the comment: "Turn off DeadCodeElimination, as it seems to be
687 salcianu 1.48                  //  generating bogus code --- removing too many moves?"
688 salcianu 1.48                  // Hopefully this bug will be fixed soon and this pass re-enabled.
689 salcianu 1.48                  //hcf = harpoon.Analysis.Tree.DeadCodeElimination.codeFactory(hcf);
690 salcianu 1.48                  
691 salcianu 1.48                  // CSA 07-11-2002: Temporarily turn off JumpOptimization.  It
692 salcianu 1.48                  // has a bug but I can't get the assertion to fail anymore.
693 salcianu 1.48                  // demo.grid.Server from the JacORB 1.3.30 distribution
694 salcianu 1.48                  // compiles to an infinite loop with JumpOptimization enabled,
695 salcianu 1.48                  // however.
696 salcianu 1.48                  //hcf = harpoon.Analysis.Tree.JumpOptimization.codeFactory(hcf);
697 salcianu 1.40              }
698 salcianu 1.43          }
699 cananian 1.2       }