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 void populateRecompilationChoices() {
059 int maxOptLevel = Controller.options.DERIVED_MAX_OPT_LEVEL;
060 int maxCompiler = CompilerDNA.getCompilerConstant(maxOptLevel);
061 allOptLevelChoices = new RecompileOptChoice[maxOptLevel + 1];
062
063 // Create one main list of all possible recompilation choices that
064 // will be considered. For each opt-level, create a recompilation
065 // choice for that opt-level and record it indexed by opt-level
066 for (int optLevel = 0; optLevel <= maxOptLevel; optLevel++) {
067 allOptLevelChoices[optLevel] = new RecompileOptChoice(optLevel);
068 }
069
070 // Given the above choices, create lookup table so that the
071 // controller's calls to
072 // getViableRecompilationChoices(prevCompiler) are answered as
073 // efficiently as possible.
074 createViableOptionLookupTable(maxCompiler);
075 }
076
077 /**
078 * Compute the set of optimization choices that should be
079 * considered by the cost-benefit model.
080 *
081 * @param prevCompiler The compiler compiler that was used to
082 * compile cmpMethod
083 * @param cmpMethod The compiled method being considered
084 */
085 RecompilationChoice[] getViableRecompilationChoices(int prevCompiler, CompiledMethod cmpMethod) {
086 if (Controller.controllerThread.earlyRestrictOptLevels()) {
087 return earlyViableChoices;
088 } else {
089 return viableChoices[prevCompiler];
090 }
091 }
092
093 /**
094 * Setup a lookup table that maps a "previous compiler" to a set
095 * of viable recompilation choices. In this case, a viable choice
096 * is any compiler > prevCompiler.
097 */
098 protected void createViableOptionLookupTable(int maxCompiler) {
099 viableChoices = new RecompilationChoice[maxCompiler][];
100
101 // A temp place to store the list of viable choices
102 RecompilationChoice[] temp = new RecompilationChoice[maxCompiler];
103
104 // For each potential value of the previous compiler
105 for (int prevCompiler = CompilerDNA.BASELINE; prevCompiler < maxCompiler; prevCompiler++) {
106
107 // Consider each choice in the list of all choices.
108 // If it is greater than cur compiler, add it.
109 int curSlot = 0;
110 for (RecompileOptChoice choice : allOptLevelChoices) {
111 if (choice.getCompiler() > prevCompiler) {
112 // Add the current opt-level as a choice to consider when
113 // the previous compiler is prevCompiler
114 temp[curSlot++] = choice;
115 }
116 }
117
118 // Now that you know how many choices there are, create an array
119 // of them and copy the choices in.
120 viableChoices[prevCompiler] = new RecompilationChoice[curSlot];
121 for (int i = 0; i < curSlot; i++) {
122 viableChoices[prevCompiler][i] = temp[i];
123 temp[i] = null;
124 }
125 }
126 }
127 }