Home | History | Annotate | Download | only in dex
      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