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.controller;
014    
015    import org.jikesrvm.adaptive.recompilation.CompilerDNA;
016    import org.jikesrvm.compilers.common.CompiledMethod;
017    
018    /**
019     * Implements the multi-level adaptive strategy using an analytic
020     * model, as described in the OOPSLA 2000 paper.  Most behavior
021     * inherited from AnalyticModel.  This class defines the the specific
022     * recompilation choices that should be considered by the analytic model.
023     */
024    class MultiLevelAdaptiveModel extends AnalyticModel {
025    
026      /**
027       * List of all opt-level choices that can be considered by the
028       * cost-benefit model
029       */
030      protected RecompileOptChoice[] allOptLevelChoices;
031    
032      /**
033       * Keep a map from previous compiler to a set of recompilation
034       * choices.  After initialization, viableChoices[x][y] means that if
035       * x is the previous compiler, y makes sense as a possible
036       * recompilation choice.
037       */
038      protected RecompilationChoice[][] viableChoices;
039    
040      /**
041       * Normally, we will be profiling call edges to build a dynamic call graph.
042       * When this is enabled in the system, we want to block the adaptive system
043       * from choosing to compile at a level higher than O0 (only does trivial inlining)
044       * until the system has built up at least a little knowledge of the call graph.
045       * This the cached early-in-the-run viableChoices to be used until the call graph
046       * is ready and we can enable all the opt compiler optimization levels.
047       */
048      protected RecompilationChoice[] earlyViableChoices = { new RecompileOptChoice(0) };
049    
050      /**
051       * Initialize the set of "optimization choices" that the
052       * cost-benefit model will consider.
053       *
054       * This method is conceptually simply, but becomes more complex
055       * because sets of choices are precomputed and stored in a table so
056       * they do not need to be recomputed to answer queries.
057       */
058      @Override
059      void populateRecompilationChoices() {
060        int maxOptLevel = Controller.options.DERIVED_MAX_OPT_LEVEL;
061        int maxCompiler = CompilerDNA.getCompilerConstant(maxOptLevel);
062        allOptLevelChoices = new RecompileOptChoice[maxOptLevel + 1];
063    
064        // Create one main list of all possible recompilation choices that
065        // will be considered.  For each opt-level, create a recompilation
066        // choice for that opt-level and record it indexed by opt-level
067        for (int optLevel = 0; optLevel <= maxOptLevel; optLevel++) {
068          allOptLevelChoices[optLevel] = new RecompileOptChoice(optLevel);
069        }
070    
071        // Given the above choices, create lookup table so that the
072        // controller's calls to
073        // getViableRecompilationChoices(prevCompiler) are answered as
074        // efficiently as possible.
075        createViableOptionLookupTable(maxCompiler);
076      }
077    
078      @Override
079      RecompilationChoice[] getViableRecompilationChoices(int prevCompiler, CompiledMethod cmpMethod) {
080        if (Controller.controllerThread.earlyRestrictOptLevels()) {
081          return earlyViableChoices;
082        } else {
083          return viableChoices[prevCompiler];
084        }
085      }
086    
087      /**
088       * Setup a lookup table that maps a "previous compiler" to a set
089       * of viable recompilation choices.  In this case, a viable choice
090       * is any compiler > prevCompiler.
091       */
092      protected void createViableOptionLookupTable(int maxCompiler) {
093        viableChoices = new RecompilationChoice[maxCompiler][];
094    
095        // A temp place to store the list of viable choices
096        RecompilationChoice[] temp = new RecompilationChoice[maxCompiler];
097    
098        // For each potential value of the previous compiler
099        for (int prevCompiler = CompilerDNA.BASELINE; prevCompiler < maxCompiler; prevCompiler++) {
100    
101          // Consider each choice in the list of all choices.
102          // If it is greater than cur compiler, add it.
103          int curSlot = 0;
104          for (RecompileOptChoice choice : allOptLevelChoices) {
105            if (choice.getCompiler() > prevCompiler) {
106              // Add the current opt-level as a choice to consider when
107              // the previous compiler is prevCompiler
108              temp[curSlot++] = choice;
109            }
110          }
111    
112          // Now that you know how many choices there are, create an array
113          // of them and copy the choices in.
114          viableChoices[prevCompiler] = new RecompilationChoice[curSlot];
115          for (int i = 0; i < curSlot; i++) {
116            viableChoices[prevCompiler][i] = temp[i];
117            temp[i] = null;
118          }
119        }
120      }
121    }