Home | History | Annotate | Download | only in driver
      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_DRIVER_COMPILER_OPTIONS_H_
     18 #define ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
     19 
     20 #include <ostream>
     21 #include <string>
     22 #include <vector>
     23 
     24 #include "base/macros.h"
     25 #include "base/utils.h"
     26 #include "compiler_filter.h"
     27 #include "globals.h"
     28 #include "optimizing/register_allocator.h"
     29 
     30 namespace art {
     31 
     32 namespace verifier {
     33 class VerifierDepsTest;
     34 }  // namespace verifier
     35 
     36 class DexFile;
     37 
     38 class CompilerOptions FINAL {
     39  public:
     40   // Guide heuristics to determine whether to compile method if profile data not available.
     41   static const size_t kDefaultHugeMethodThreshold = 10000;
     42   static const size_t kDefaultLargeMethodThreshold = 600;
     43   static const size_t kDefaultSmallMethodThreshold = 60;
     44   static const size_t kDefaultTinyMethodThreshold = 20;
     45   static const size_t kDefaultNumDexMethodsThreshold = 900;
     46   static constexpr double kDefaultTopKProfileThreshold = 90.0;
     47   static const bool kDefaultGenerateDebugInfo = false;
     48   static const bool kDefaultGenerateMiniDebugInfo = false;
     49   static const size_t kDefaultInlineMaxCodeUnits = 32;
     50   static constexpr size_t kUnsetInlineMaxCodeUnits = -1;
     51 
     52   CompilerOptions();
     53   ~CompilerOptions();
     54 
     55   CompilerFilter::Filter GetCompilerFilter() const {
     56     return compiler_filter_;
     57   }
     58 
     59   void SetCompilerFilter(CompilerFilter::Filter compiler_filter) {
     60     compiler_filter_ = compiler_filter;
     61   }
     62 
     63   bool IsAotCompilationEnabled() const {
     64     return CompilerFilter::IsAotCompilationEnabled(compiler_filter_);
     65   }
     66 
     67   bool IsJniCompilationEnabled() const {
     68     return CompilerFilter::IsJniCompilationEnabled(compiler_filter_);
     69   }
     70 
     71   bool IsQuickeningCompilationEnabled() const {
     72     return CompilerFilter::IsQuickeningCompilationEnabled(compiler_filter_);
     73   }
     74 
     75   bool IsVerificationEnabled() const {
     76     return CompilerFilter::IsVerificationEnabled(compiler_filter_);
     77   }
     78 
     79   bool AssumeClassesAreVerified() const {
     80     return compiler_filter_ == CompilerFilter::kAssumeVerified;
     81   }
     82 
     83   bool VerifyAtRuntime() const {
     84     return compiler_filter_ == CompilerFilter::kExtract;
     85   }
     86 
     87   bool IsAnyCompilationEnabled() const {
     88     return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_);
     89   }
     90 
     91   size_t GetHugeMethodThreshold() const {
     92     return huge_method_threshold_;
     93   }
     94 
     95   size_t GetLargeMethodThreshold() const {
     96     return large_method_threshold_;
     97   }
     98 
     99   size_t GetSmallMethodThreshold() const {
    100     return small_method_threshold_;
    101   }
    102 
    103   size_t GetTinyMethodThreshold() const {
    104     return tiny_method_threshold_;
    105   }
    106 
    107   bool IsHugeMethod(size_t num_dalvik_instructions) const {
    108     return num_dalvik_instructions > huge_method_threshold_;
    109   }
    110 
    111   bool IsLargeMethod(size_t num_dalvik_instructions) const {
    112     return num_dalvik_instructions > large_method_threshold_;
    113   }
    114 
    115   bool IsSmallMethod(size_t num_dalvik_instructions) const {
    116     return num_dalvik_instructions > small_method_threshold_;
    117   }
    118 
    119   bool IsTinyMethod(size_t num_dalvik_instructions) const {
    120     return num_dalvik_instructions > tiny_method_threshold_;
    121   }
    122 
    123   size_t GetNumDexMethodsThreshold() const {
    124     return num_dex_methods_threshold_;
    125   }
    126 
    127   size_t GetInlineMaxCodeUnits() const {
    128     return inline_max_code_units_;
    129   }
    130   void SetInlineMaxCodeUnits(size_t units) {
    131     inline_max_code_units_ = units;
    132   }
    133 
    134   double GetTopKProfileThreshold() const {
    135     return top_k_profile_threshold_;
    136   }
    137 
    138   bool GetDebuggable() const {
    139     return debuggable_;
    140   }
    141 
    142   void SetDebuggable(bool value) {
    143     debuggable_ = value;
    144   }
    145 
    146   bool GetNativeDebuggable() const {
    147     return GetDebuggable() && GetGenerateDebugInfo();
    148   }
    149 
    150   // This flag controls whether the compiler collects debugging information.
    151   // The other flags control how the information is written to disk.
    152   bool GenerateAnyDebugInfo() const {
    153     return GetGenerateDebugInfo() || GetGenerateMiniDebugInfo();
    154   }
    155 
    156   bool GetGenerateDebugInfo() const {
    157     return generate_debug_info_;
    158   }
    159 
    160   bool GetGenerateMiniDebugInfo() const {
    161     return generate_mini_debug_info_;
    162   }
    163 
    164   // Should run-time checks be emitted in debug mode?
    165   bool EmitRunTimeChecksInDebugMode() const;
    166 
    167   bool GetGenerateBuildId() const {
    168     return generate_build_id_;
    169   }
    170 
    171   bool GetImplicitNullChecks() const {
    172     return implicit_null_checks_;
    173   }
    174 
    175   bool GetImplicitStackOverflowChecks() const {
    176     return implicit_so_checks_;
    177   }
    178 
    179   bool GetImplicitSuspendChecks() const {
    180     return implicit_suspend_checks_;
    181   }
    182 
    183   // Are we compiling a boot image?
    184   bool IsBootImage() const {
    185     return boot_image_;
    186   }
    187 
    188   // Are we compiling a core image (small boot image only used for ART testing)?
    189   bool IsCoreImage() const {
    190     // Ensure that `core_image_` => `boot_image_`.
    191     DCHECK(!core_image_ || boot_image_);
    192     return core_image_;
    193   }
    194 
    195   // Are we compiling an app image?
    196   bool IsAppImage() const {
    197     return app_image_;
    198   }
    199 
    200   void DisableAppImage() {
    201     app_image_ = false;
    202   }
    203 
    204   // Should the code be compiled as position independent?
    205   bool GetCompilePic() const {
    206     return compile_pic_;
    207   }
    208 
    209   bool HasVerboseMethods() const {
    210     return !verbose_methods_.empty();
    211   }
    212 
    213   bool IsVerboseMethod(const std::string& pretty_method) const {
    214     for (const std::string& cur_method : verbose_methods_) {
    215       if (pretty_method.find(cur_method) != std::string::npos) {
    216         return true;
    217       }
    218     }
    219     return false;
    220   }
    221 
    222   std::ostream* GetInitFailureOutput() const {
    223     return init_failure_output_.get();
    224   }
    225 
    226   bool AbortOnHardVerifierFailure() const {
    227     return abort_on_hard_verifier_failure_;
    228   }
    229   bool AbortOnSoftVerifierFailure() const {
    230     return abort_on_soft_verifier_failure_;
    231   }
    232 
    233   const std::vector<const DexFile*>* GetNoInlineFromDexFile() const {
    234     return no_inline_from_;
    235   }
    236 
    237   bool ParseCompilerOptions(const std::vector<std::string>& options,
    238                             bool ignore_unrecognized,
    239                             std::string* error_msg);
    240 
    241   void SetNonPic() {
    242     compile_pic_ = false;
    243   }
    244 
    245   const std::string& GetDumpCfgFileName() const {
    246     return dump_cfg_file_name_;
    247   }
    248 
    249   bool GetDumpCfgAppend() const {
    250     return dump_cfg_append_;
    251   }
    252 
    253   bool IsForceDeterminism() const {
    254     return force_determinism_;
    255   }
    256 
    257   bool DeduplicateCode() const {
    258     return deduplicate_code_;
    259   }
    260 
    261   RegisterAllocator::Strategy GetRegisterAllocationStrategy() const {
    262     return register_allocation_strategy_;
    263   }
    264 
    265   const std::vector<std::string>* GetPassesToRun() const {
    266     return passes_to_run_;
    267   }
    268 
    269   bool GetDumpTimings() const {
    270     return dump_timings_;
    271   }
    272 
    273   bool GetDumpStats() const {
    274     return dump_stats_;
    275   }
    276 
    277   bool CountHotnessInCompiledCode() const {
    278     return count_hotness_in_compiled_code_;
    279   }
    280 
    281  private:
    282   bool ParseDumpInitFailures(const std::string& option, std::string* error_msg);
    283   void ParseDumpCfgPasses(const StringPiece& option, UsageFn Usage);
    284   void ParseInlineMaxCodeUnits(const StringPiece& option, UsageFn Usage);
    285   void ParseNumDexMethods(const StringPiece& option, UsageFn Usage);
    286   void ParseTinyMethodMax(const StringPiece& option, UsageFn Usage);
    287   void ParseSmallMethodMax(const StringPiece& option, UsageFn Usage);
    288   void ParseLargeMethodMax(const StringPiece& option, UsageFn Usage);
    289   void ParseHugeMethodMax(const StringPiece& option, UsageFn Usage);
    290   bool ParseRegisterAllocationStrategy(const std::string& option, std::string* error_msg);
    291 
    292   CompilerFilter::Filter compiler_filter_;
    293   size_t huge_method_threshold_;
    294   size_t large_method_threshold_;
    295   size_t small_method_threshold_;
    296   size_t tiny_method_threshold_;
    297   size_t num_dex_methods_threshold_;
    298   size_t inline_max_code_units_;
    299 
    300   // Dex files from which we should not inline code.
    301   // This is usually a very short list (i.e. a single dex file), so we
    302   // prefer vector<> over a lookup-oriented container, such as set<>.
    303   const std::vector<const DexFile*>* no_inline_from_;
    304 
    305   bool boot_image_;
    306   bool core_image_;
    307   bool app_image_;
    308   // When using a profile file only the top K% of the profiled samples will be compiled.
    309   double top_k_profile_threshold_;
    310   bool debuggable_;
    311   bool generate_debug_info_;
    312   bool generate_mini_debug_info_;
    313   bool generate_build_id_;
    314   bool implicit_null_checks_;
    315   bool implicit_so_checks_;
    316   bool implicit_suspend_checks_;
    317   bool compile_pic_;
    318   bool dump_timings_;
    319   bool dump_stats_;
    320 
    321   // Vector of methods to have verbose output enabled for.
    322   std::vector<std::string> verbose_methods_;
    323 
    324   // Abort compilation with an error if we find a class that fails verification with a hard
    325   // failure.
    326   bool abort_on_hard_verifier_failure_;
    327   // Same for soft failures.
    328   bool abort_on_soft_verifier_failure_;
    329 
    330   // Log initialization of initialization failures to this stream if not null.
    331   std::unique_ptr<std::ostream> init_failure_output_;
    332 
    333   std::string dump_cfg_file_name_;
    334   bool dump_cfg_append_;
    335 
    336   // Whether the compiler should trade performance for determinism to guarantee exactly reproducible
    337   // outcomes.
    338   bool force_determinism_;
    339 
    340   // Whether code should be deduplicated.
    341   bool deduplicate_code_;
    342 
    343   // Whether compiled code should increment the hotness count of ArtMethod. Note that the increments
    344   // won't be atomic for performance reasons, so we accept races, just like in interpreter.
    345   bool count_hotness_in_compiled_code_;
    346 
    347   RegisterAllocator::Strategy register_allocation_strategy_;
    348 
    349   // If not null, specifies optimization passes which will be run instead of defaults.
    350   // Note that passes_to_run_ is not checked for correctness and providing an incorrect
    351   // list of passes can lead to unexpected compiler behaviour. This is caused by dependencies
    352   // between passes. Failing to satisfy them can for example lead to compiler crashes.
    353   // Passing pass names which are not recognized by the compiler will result in
    354   // compiler-dependant behavior.
    355   const std::vector<std::string>* passes_to_run_;
    356 
    357   friend class Dex2Oat;
    358   friend class DexToDexDecompilerTest;
    359   friend class CommonCompilerTest;
    360   friend class verifier::VerifierDepsTest;
    361 
    362   template <class Base>
    363   friend bool ReadCompilerOptions(Base& map, CompilerOptions* options, std::string* error_msg);
    364 
    365   DISALLOW_COPY_AND_ASSIGN(CompilerOptions);
    366 };
    367 
    368 }  // namespace art
    369 
    370 #endif  // ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
    371