001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.adaptive.recompilation;
014    
015    import org.jikesrvm.VM;
016    import org.jikesrvm.Callbacks;
017    import org.jikesrvm.adaptive.controller.Controller;
018    import org.jikesrvm.adaptive.util.AOSLogging;
019    import org.jikesrvm.adaptive.util.CompilerAdviceAttribute;
020    import org.jikesrvm.classloader.RVMClass;
021    import org.jikesrvm.classloader.RVMClassLoader;
022    import org.jikesrvm.classloader.RVMMethod;
023    import org.jikesrvm.classloader.NormalMethod;
024    import org.jikesrvm.classloader.TypeReference;
025    import org.jikesrvm.compilers.common.RuntimeCompiler;
026    import org.jikesrvm.compilers.opt.driver.CompilationPlan;
027    
028    /**
029     * Utilities for providing compiler advice.  Advice files provided
030     * at run time allow compilers to be specified for particular methods
031     * <p>
032     * <i>Run time</i> advice is given by identifying an advice file
033     * through a command line option:
034     * <code>-X:aos:compiler_advice_file=path-to-advice-file</code>.
035     *
036     *
037     * @see org.jikesrvm.adaptive.util.CompilerAdviceAttribute
038     * @see org.jikesrvm.adaptive.util.CompilerAdviceInfoReader
039     * @see org.jikesrvm.compilers.common.RuntimeCompiler
040     */
041    public class PreCompile implements Callbacks.StartupMonitor {
042    
043      public static void init() {
044        Callbacks.addStartupMonitor(new PreCompile());
045      }
046    
047      public void notifyStartup() {
048        if (Controller.options.ENABLE_PRECOMPILE) {
049          VM.sysWrite("Start precompiling");
050          // precompile the methods
051          compileAllMethods();
052          VM.sysWrite("Finish precompiling");
053        }
054      }
055    
056      /**
057       * Compile all methods in the advice file
058       */
059      public static void compileAllMethods() {
060        //Collection allMethodsSet = attribMap.values();
061        VM.sysWriteln("Start precompile");
062        for (CompilerAdviceAttribute value : CompilerAdviceAttribute.values()) {
063          //while (allMethods.hasNext()) {
064          //VM.sysWriteln("checking one");
065    
066          TypeReference tRef =
067              TypeReference.findOrCreate(RVMClassLoader.getApplicationClassLoader(), value.getClassName());
068          RVMClass cls = (RVMClass) tRef.peekType();
069          if (cls == null) {
070            try {
071              cls = tRef.resolve().asClass();
072              cls.resolve();
073              cls.instantiate();
074              cls.initialize();
075            } catch (NoClassDefFoundError cnf) {
076              VM.sysWriteln("Bad entry in the advice file");
077            }
078          }
079    
080          if (cls != null) {
081            // Find the method
082            RVMMethod method = cls.findDeclaredMethod(value.getMethodName(), value.getMethodSig());
083    
084            // If found, compile it
085            if ((method != null) &&
086                !method.hasNoOptCompileAnnotation() &&
087                (method instanceof org.jikesrvm.classloader.NormalMethod)) {
088              // if user's requirement is higher than advice
089              if ((((org.jikesrvm.compilers.opt.OptOptions) RuntimeCompiler.options).getOptLevel() >
090                   value.getOptLevel()) || (Controller.options.DERIVED_MAX_OPT_LEVEL < value.getOptLevel())) {
091                method.compile();
092              } else {
093                // otherwise, follow the advice...
094                // VM.sysWrite("Compiler advice for ");
095                // VM.sysWriteln(value.methodName);
096                CompilationPlan compPlan;
097                if (Controller.options.counters()) {
098                  // for invocation counter, we only use one optimization level
099                  compPlan = InvocationCounts.createCompilationPlan((NormalMethod) method);
100                  AOSLogging.logger.recompilationStarted(compPlan);
101                  RuntimeCompiler.recompileWithOpt(compPlan);
102                  AOSLogging.logger.recompilationCompleted(compPlan);
103                } else if (Controller.options.sampling()) {
104                  // Create our set of standard optimization plans.
105                  compPlan =
106                      Controller.recompilationStrategy.createCompilationPlan((NormalMethod) method,
107                                                                                value.getOptLevel(),
108                                                                                null);
109                  AOSLogging.logger.recompilationStarted(compPlan);
110                  RuntimeCompiler.recompileWithOpt(compPlan);
111                  AOSLogging.logger.recompilationCompleted(compPlan);
112                } else {
113                  VM.sysWriteln("Compiler advice file is not followed  ");
114                  method.compile();
115                }
116              }
117            }
118          }
119        }
120        AOSLogging.logger.compileAllMethodsCompleted();
121      }
122    }