1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_COMPILER_DEX_PASS_DRIVER_H_ 18 #define ART_COMPILER_DEX_PASS_DRIVER_H_ 19 20 #include <vector> 21 #include "pass.h" 22 #include "safe_map.h" 23 24 // Forward Declarations. 25 class Pass; 26 class PassDriver; 27 namespace art { 28 /** 29 * @brief Helper function to create a single instance of a given Pass and can be shared across 30 * the threads. 31 */ 32 template <typename PassType> 33 const Pass* GetPassInstance() { 34 static const PassType pass; 35 return &pass; 36 } 37 38 // Empty holder for the constructor. 39 class PassDriverDataHolder { 40 }; 41 42 /** 43 * @class PassDriver 44 * @brief PassDriver is the wrapper around all Pass instances in order to execute them 45 */ 46 template <typename PassDriverType> 47 class PassDriver { 48 public: 49 explicit PassDriver() { 50 InitializePasses(); 51 } 52 53 virtual ~PassDriver() { 54 } 55 56 /** 57 * @brief Insert a Pass: can warn if multiple passes have the same name. 58 */ 59 void InsertPass(const Pass* new_pass) { 60 DCHECK(new_pass != nullptr); 61 DCHECK(new_pass->GetName() != nullptr && new_pass->GetName()[0] != 0); 62 63 // It is an error to override an existing pass. 64 DCHECK(GetPass(new_pass->GetName()) == nullptr) 65 << "Pass name " << new_pass->GetName() << " already used."; 66 67 // Now add to the list. 68 pass_list_.push_back(new_pass); 69 } 70 71 /** 72 * @brief Run a pass using the name as key. 73 * @return whether the pass was applied. 74 */ 75 virtual bool RunPass(const char* pass_name) { 76 // Paranoid: c_unit cannot be nullptr and we need a pass name. 77 DCHECK(pass_name != nullptr && pass_name[0] != 0); 78 79 const Pass* cur_pass = GetPass(pass_name); 80 81 if (cur_pass != nullptr) { 82 return RunPass(cur_pass); 83 } 84 85 // Return false, we did not find the pass. 86 return false; 87 } 88 89 /** 90 * @brief Runs all the passes with the pass_list_. 91 */ 92 void Launch() { 93 for (const Pass* cur_pass : pass_list_) { 94 RunPass(cur_pass); 95 } 96 } 97 98 /** 99 * @brief Searches for a particular pass. 100 * @param the name of the pass to be searched for. 101 */ 102 const Pass* GetPass(const char* name) const { 103 for (const Pass* cur_pass : pass_list_) { 104 if (strcmp(name, cur_pass->GetName()) == 0) { 105 return cur_pass; 106 } 107 } 108 return nullptr; 109 } 110 111 static void CreateDefaultPassList(const std::string& disable_passes) { 112 // Insert each pass from g_passes into g_default_pass_list. 113 PassDriverType::g_default_pass_list.clear(); 114 PassDriverType::g_default_pass_list.reserve(PassDriver<PassDriverType>::g_passes_size); 115 for (uint16_t i = 0; i < PassDriver<PassDriverType>::g_passes_size; ++i) { 116 const Pass* pass = PassDriver<PassDriverType>::g_passes[i]; 117 // Check if we should disable this pass. 118 if (disable_passes.find(pass->GetName()) != std::string::npos) { 119 LOG(INFO) << "Skipping " << pass->GetName(); 120 } else { 121 PassDriver<PassDriverType>::g_default_pass_list.push_back(pass); 122 } 123 } 124 } 125 126 /** 127 * @brief Run a pass using the Pass itself. 128 * @param time_split do we want a time split request(default: false)? 129 * @return whether the pass was applied. 130 */ 131 virtual bool RunPass(const Pass* pass, bool time_split = false) = 0; 132 133 /** 134 * @brief Print the pass names of all the passes available. 135 */ 136 static void PrintPassNames() { 137 LOG(INFO) << "Loop Passes are:"; 138 139 for (const Pass* cur_pass : PassDriver<PassDriverType>::g_default_pass_list) { 140 LOG(INFO) << "\t-" << cur_pass->GetName(); 141 } 142 } 143 144 /** 145 * @brief Gets the list of passes currently schedule to execute. 146 * @return pass_list_ 147 */ 148 std::vector<const Pass*>& GetPasses() { 149 return pass_list_; 150 } 151 152 static void SetPrintAllPasses() { 153 default_print_passes_ = true; 154 } 155 156 static void SetDumpPassList(const std::string& list) { 157 dump_pass_list_ = list; 158 } 159 160 static void SetPrintPassList(const std::string& list) { 161 print_pass_list_ = list; 162 } 163 164 void SetDefaultPasses() { 165 pass_list_ = PassDriver<PassDriverType>::g_default_pass_list; 166 } 167 168 protected: 169 virtual void InitializePasses() { 170 SetDefaultPasses(); 171 } 172 173 /** 174 * @brief Apply a patch: perform start/work/end functions. 175 */ 176 virtual void ApplyPass(PassDataHolder* data, const Pass* pass) { 177 pass->Start(data); 178 DispatchPass(pass); 179 pass->End(data); 180 } 181 /** 182 * @brief Dispatch a patch. 183 * Gives the ability to add logic when running the patch. 184 */ 185 virtual void DispatchPass(const Pass* pass) { 186 UNUSED(pass); 187 } 188 189 /** @brief List of passes: provides the order to execute the passes. */ 190 std::vector<const Pass*> pass_list_; 191 192 /** @brief The number of passes within g_passes. */ 193 static const uint16_t g_passes_size; 194 195 /** @brief The number of passes within g_passes. */ 196 static const Pass* const g_passes[]; 197 198 /** @brief The default pass list is used to initialize pass_list_. */ 199 static std::vector<const Pass*> g_default_pass_list; 200 201 /** @brief Do we, by default, want to be printing the log messages? */ 202 static bool default_print_passes_; 203 204 /** @brief What are the passes we want to be printing the log messages? */ 205 static std::string print_pass_list_; 206 207 /** @brief What are the passes we want to be dumping the CFG? */ 208 static std::string dump_pass_list_; 209 }; 210 211 } // namespace art 212 #endif // ART_COMPILER_DEX_PASS_DRIVER_H_ 213