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 */ 013package org.jikesrvm.adaptive.controller; 014 015import org.jikesrvm.adaptive.recompilation.CompilerDNA; 016import 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 */ 024class 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 * @param maxCompiler the maximum compiler that we want to consider 093 * (e.g. the highest optimization level). 094 */ 095 protected void createViableOptionLookupTable(int maxCompiler) { 096 viableChoices = new RecompilationChoice[maxCompiler][]; 097 098 // A temp place to store the list of viable choices 099 RecompilationChoice[] temp = new RecompilationChoice[maxCompiler]; 100 101 // For each potential value of the previous compiler 102 for (int prevCompiler = CompilerDNA.BASELINE; prevCompiler < maxCompiler; prevCompiler++) { 103 104 // Consider each choice in the list of all choices. 105 // If it is greater than cur compiler, add it. 106 int curSlot = 0; 107 for (RecompileOptChoice choice : allOptLevelChoices) { 108 if (choice.getCompiler() > prevCompiler) { 109 // Add the current opt-level as a choice to consider when 110 // the previous compiler is prevCompiler 111 temp[curSlot++] = choice; 112 } 113 } 114 115 // Now that you know how many choices there are, create an array 116 // of them and copy the choices in. 117 viableChoices[prevCompiler] = new RecompilationChoice[curSlot]; 118 for (int i = 0; i < curSlot; i++) { 119 viableChoices[prevCompiler][i] = temp[i]; 120 temp[i] = null; 121 } 122 } 123 } 124}