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 
GetCompilerFilter()55   CompilerFilter::Filter GetCompilerFilter() const {
56     return compiler_filter_;
57   }
58 
SetCompilerFilter(CompilerFilter::Filter compiler_filter)59   void SetCompilerFilter(CompilerFilter::Filter compiler_filter) {
60     compiler_filter_ = compiler_filter;
61   }
62 
IsAotCompilationEnabled()63   bool IsAotCompilationEnabled() const {
64     return CompilerFilter::IsAotCompilationEnabled(compiler_filter_);
65   }
66 
IsJniCompilationEnabled()67   bool IsJniCompilationEnabled() const {
68     return CompilerFilter::IsJniCompilationEnabled(compiler_filter_);
69   }
70 
IsQuickeningCompilationEnabled()71   bool IsQuickeningCompilationEnabled() const {
72     return CompilerFilter::IsQuickeningCompilationEnabled(compiler_filter_);
73   }
74 
IsVerificationEnabled()75   bool IsVerificationEnabled() const {
76     return CompilerFilter::IsVerificationEnabled(compiler_filter_);
77   }
78 
AssumeClassesAreVerified()79   bool AssumeClassesAreVerified() const {
80     return compiler_filter_ == CompilerFilter::kAssumeVerified;
81   }
82 
VerifyAtRuntime()83   bool VerifyAtRuntime() const {
84     return compiler_filter_ == CompilerFilter::kExtract;
85   }
86 
IsAnyCompilationEnabled()87   bool IsAnyCompilationEnabled() const {
88     return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_);
89   }
90 
GetHugeMethodThreshold()91   size_t GetHugeMethodThreshold() const {
92     return huge_method_threshold_;
93   }
94 
GetLargeMethodThreshold()95   size_t GetLargeMethodThreshold() const {
96     return large_method_threshold_;
97   }
98 
GetSmallMethodThreshold()99   size_t GetSmallMethodThreshold() const {
100     return small_method_threshold_;
101   }
102 
GetTinyMethodThreshold()103   size_t GetTinyMethodThreshold() const {
104     return tiny_method_threshold_;
105   }
106 
IsHugeMethod(size_t num_dalvik_instructions)107   bool IsHugeMethod(size_t num_dalvik_instructions) const {
108     return num_dalvik_instructions > huge_method_threshold_;
109   }
110 
IsLargeMethod(size_t num_dalvik_instructions)111   bool IsLargeMethod(size_t num_dalvik_instructions) const {
112     return num_dalvik_instructions > large_method_threshold_;
113   }
114 
IsSmallMethod(size_t num_dalvik_instructions)115   bool IsSmallMethod(size_t num_dalvik_instructions) const {
116     return num_dalvik_instructions > small_method_threshold_;
117   }
118 
IsTinyMethod(size_t num_dalvik_instructions)119   bool IsTinyMethod(size_t num_dalvik_instructions) const {
120     return num_dalvik_instructions > tiny_method_threshold_;
121   }
122 
GetNumDexMethodsThreshold()123   size_t GetNumDexMethodsThreshold() const {
124     return num_dex_methods_threshold_;
125   }
126 
GetInlineMaxCodeUnits()127   size_t GetInlineMaxCodeUnits() const {
128     return inline_max_code_units_;
129   }
SetInlineMaxCodeUnits(size_t units)130   void SetInlineMaxCodeUnits(size_t units) {
131     inline_max_code_units_ = units;
132   }
133 
GetTopKProfileThreshold()134   double GetTopKProfileThreshold() const {
135     return top_k_profile_threshold_;
136   }
137 
GetDebuggable()138   bool GetDebuggable() const {
139     return debuggable_;
140   }
141 
SetDebuggable(bool value)142   void SetDebuggable(bool value) {
143     debuggable_ = value;
144   }
145 
GetNativeDebuggable()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.
GenerateAnyDebugInfo()152   bool GenerateAnyDebugInfo() const {
153     return GetGenerateDebugInfo() || GetGenerateMiniDebugInfo();
154   }
155 
GetGenerateDebugInfo()156   bool GetGenerateDebugInfo() const {
157     return generate_debug_info_;
158   }
159 
GetGenerateMiniDebugInfo()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 
GetGenerateBuildId()167   bool GetGenerateBuildId() const {
168     return generate_build_id_;
169   }
170 
GetImplicitNullChecks()171   bool GetImplicitNullChecks() const {
172     return implicit_null_checks_;
173   }
174 
GetImplicitStackOverflowChecks()175   bool GetImplicitStackOverflowChecks() const {
176     return implicit_so_checks_;
177   }
178 
GetImplicitSuspendChecks()179   bool GetImplicitSuspendChecks() const {
180     return implicit_suspend_checks_;
181   }
182 
183   // Are we compiling a boot image?
IsBootImage()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)?
IsCoreImage()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?
IsAppImage()196   bool IsAppImage() const {
197     return app_image_;
198   }
199 
DisableAppImage()200   void DisableAppImage() {
201     app_image_ = false;
202   }
203 
204   // Should the code be compiled as position independent?
GetCompilePic()205   bool GetCompilePic() const {
206     return compile_pic_;
207   }
208 
HasVerboseMethods()209   bool HasVerboseMethods() const {
210     return !verbose_methods_.empty();
211   }
212 
IsVerboseMethod(const std::string & pretty_method)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 
GetInitFailureOutput()222   std::ostream* GetInitFailureOutput() const {
223     return init_failure_output_.get();
224   }
225 
AbortOnHardVerifierFailure()226   bool AbortOnHardVerifierFailure() const {
227     return abort_on_hard_verifier_failure_;
228   }
AbortOnSoftVerifierFailure()229   bool AbortOnSoftVerifierFailure() const {
230     return abort_on_soft_verifier_failure_;
231   }
232 
GetNoInlineFromDexFile()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 
SetNonPic()241   void SetNonPic() {
242     compile_pic_ = false;
243   }
244 
GetDumpCfgFileName()245   const std::string& GetDumpCfgFileName() const {
246     return dump_cfg_file_name_;
247   }
248 
GetDumpCfgAppend()249   bool GetDumpCfgAppend() const {
250     return dump_cfg_append_;
251   }
252 
IsForceDeterminism()253   bool IsForceDeterminism() const {
254     return force_determinism_;
255   }
256 
DeduplicateCode()257   bool DeduplicateCode() const {
258     return deduplicate_code_;
259   }
260 
GetRegisterAllocationStrategy()261   RegisterAllocator::Strategy GetRegisterAllocationStrategy() const {
262     return register_allocation_strategy_;
263   }
264 
GetPassesToRun()265   const std::vector<std::string>* GetPassesToRun() const {
266     return passes_to_run_;
267   }
268 
GetDumpTimings()269   bool GetDumpTimings() const {
270     return dump_timings_;
271   }
272 
GetDumpStats()273   bool GetDumpStats() const {
274     return dump_stats_;
275   }
276 
CountHotnessInCompiledCode()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