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_ME_H_
     18 #define ART_COMPILER_DEX_PASS_DRIVER_ME_H_
     19 
     20 #include "bb_optimizations.h"
     21 #include "dataflow_iterator.h"
     22 #include "dataflow_iterator-inl.h"
     23 #include "pass_driver.h"
     24 #include "pass_me.h"
     25 
     26 namespace art {
     27 
     28 template <typename PassDriverType>
     29 class PassDriverME: public PassDriver<PassDriverType> {
     30  public:
     31   explicit PassDriverME(CompilationUnit* cu)
     32       : pass_me_data_holder_(), dump_cfg_folder_("/sdcard/") {
     33         pass_me_data_holder_.bb = nullptr;
     34         pass_me_data_holder_.c_unit = cu;
     35   }
     36 
     37   ~PassDriverME() {
     38   }
     39 
     40   void DispatchPass(const Pass* pass) {
     41     VLOG(compiler) << "Dispatching " << pass->GetName();
     42     const PassME* me_pass = down_cast<const PassME*>(pass);
     43 
     44     DataFlowAnalysisMode mode = me_pass->GetTraversal();
     45 
     46     switch (mode) {
     47       case kPreOrderDFSTraversal:
     48         DoWalkBasicBlocks<PreOrderDfsIterator>(&pass_me_data_holder_, me_pass);
     49         break;
     50       case kRepeatingPreOrderDFSTraversal:
     51         DoWalkBasicBlocks<RepeatingPreOrderDfsIterator>(&pass_me_data_holder_, me_pass);
     52         break;
     53       case kRepeatingPostOrderDFSTraversal:
     54         DoWalkBasicBlocks<RepeatingPostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
     55         break;
     56       case kReversePostOrderDFSTraversal:
     57         DoWalkBasicBlocks<ReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
     58         break;
     59       case kRepeatingReversePostOrderDFSTraversal:
     60         DoWalkBasicBlocks<RepeatingReversePostOrderDfsIterator>(&pass_me_data_holder_, me_pass);
     61         break;
     62       case kPostOrderDOMTraversal:
     63         DoWalkBasicBlocks<PostOrderDOMIterator>(&pass_me_data_holder_, me_pass);
     64         break;
     65       case kTopologicalSortTraversal:
     66         DoWalkBasicBlocks<TopologicalSortIterator>(&pass_me_data_holder_, me_pass);
     67         break;
     68       case kRepeatingTopologicalSortTraversal:
     69         DoWalkBasicBlocks<RepeatingTopologicalSortIterator>(&pass_me_data_holder_, me_pass);
     70         break;
     71       case kLoopRepeatingTopologicalSortTraversal:
     72         DoWalkBasicBlocks<LoopRepeatingTopologicalSortIterator>(&pass_me_data_holder_, me_pass);
     73         break;
     74       case kAllNodes:
     75         DoWalkBasicBlocks<AllNodesIterator>(&pass_me_data_holder_, me_pass);
     76         break;
     77       case kNoNodes:
     78         break;
     79       default:
     80         LOG(FATAL) << "Iterator mode not handled in dispatcher: " << mode;
     81         break;
     82     }
     83   }
     84 
     85   bool RunPass(const Pass* pass, bool time_split) {
     86     // Paranoid: c_unit and pass cannot be nullptr, and the pass should have a name
     87     DCHECK(pass != nullptr);
     88     DCHECK(pass->GetName() != nullptr && pass->GetName()[0] != 0);
     89     CompilationUnit* c_unit = pass_me_data_holder_.c_unit;
     90     DCHECK(c_unit != nullptr);
     91 
     92     // Do we perform a time split
     93     if (time_split) {
     94       c_unit->NewTimingSplit(pass->GetName());
     95     }
     96 
     97     // Check the pass gate first.
     98     bool should_apply_pass = pass->Gate(&pass_me_data_holder_);
     99     if (should_apply_pass) {
    100       bool old_print_pass = c_unit->print_pass;
    101 
    102       c_unit->print_pass = PassDriver<PassDriverType>::default_print_passes_;
    103 
    104       const char* print_pass_list = PassDriver<PassDriverType>::print_pass_list_.c_str();
    105 
    106       if (print_pass_list != nullptr && strstr(print_pass_list, pass->GetName()) != nullptr) {
    107         c_unit->print_pass = true;
    108       }
    109 
    110       // Applying the pass: first start, doWork, and end calls.
    111       this->ApplyPass(&pass_me_data_holder_, pass);
    112 
    113       bool should_dump = ((c_unit->enable_debug & (1 << kDebugDumpCFG)) != 0);
    114 
    115       const char* dump_pass_list = PassDriver<PassDriverType>::dump_pass_list_.c_str();
    116 
    117       if (dump_pass_list != nullptr) {
    118         bool found = strstr(dump_pass_list, pass->GetName());
    119         should_dump = (should_dump || found);
    120       }
    121 
    122       if (should_dump) {
    123         // Do we want to log it?
    124         if ((c_unit->enable_debug&  (1 << kDebugDumpCFG)) != 0) {
    125           // Do we have a pass folder?
    126           const PassME* me_pass = (down_cast<const PassME*>(pass));
    127           const char* passFolder = me_pass->GetDumpCFGFolder();
    128           DCHECK(passFolder != nullptr);
    129 
    130           if (passFolder[0] != 0) {
    131             // Create directory prefix.
    132             std::string prefix = GetDumpCFGFolder();
    133             prefix += passFolder;
    134             prefix += "/";
    135 
    136             c_unit->mir_graph->DumpCFG(prefix.c_str(), false);
    137           }
    138         }
    139       }
    140 
    141       c_unit->print_pass = old_print_pass;
    142     }
    143 
    144     // If the pass gate passed, we can declare success.
    145     return should_apply_pass;
    146   }
    147 
    148   const char* GetDumpCFGFolder() const {
    149     return dump_cfg_folder_;
    150   }
    151 
    152  protected:
    153   /** @brief The data holder that contains data needed for the PassDriverME. */
    154   PassMEDataHolder pass_me_data_holder_;
    155 
    156   /** @brief Dump CFG base folder: where is the base folder for dumping CFGs. */
    157   const char* dump_cfg_folder_;
    158 
    159   static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass,
    160                                 DataflowIterator* iterator) {
    161     // Paranoid: Check the iterator before walking the BasicBlocks.
    162     DCHECK(iterator != nullptr);
    163     bool change = false;
    164     for (BasicBlock* bb = iterator->Next(change); bb != nullptr; bb = iterator->Next(change)) {
    165       data->bb = bb;
    166       change = pass->Worker(data);
    167     }
    168   }
    169 
    170   template <typename Iterator>
    171   inline static void DoWalkBasicBlocks(PassMEDataHolder* data, const PassME* pass) {
    172       DCHECK(data != nullptr);
    173       CompilationUnit* c_unit = data->c_unit;
    174       DCHECK(c_unit != nullptr);
    175       Iterator iterator(c_unit->mir_graph.get());
    176       DoWalkBasicBlocks(data, pass, &iterator);
    177     }
    178 };
    179 }  // namespace art
    180 #endif  // ART_COMPILER_DEX_PASS_DRIVER_ME_H_
    181 
    182