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 "compiler_filter.h"
26 #include "globals.h"
27 #include "utils.h"
28 
29 namespace art {
30 
31 class CompilerOptions FINAL {
32  public:
33   // Guide heuristics to determine whether to compile method if profile data not available.
34   static const CompilerFilter::Filter kDefaultCompilerFilter = CompilerFilter::kSpeed;
35   static const size_t kDefaultHugeMethodThreshold = 10000;
36   static const size_t kDefaultLargeMethodThreshold = 600;
37   static const size_t kDefaultSmallMethodThreshold = 60;
38   static const size_t kDefaultTinyMethodThreshold = 20;
39   static const size_t kDefaultNumDexMethodsThreshold = 900;
40   static constexpr double kDefaultTopKProfileThreshold = 90.0;
41   static const bool kDefaultGenerateDebugInfo = false;
42   static const bool kDefaultGenerateMiniDebugInfo = false;
43   static const bool kDefaultIncludePatchInformation = false;
44   static const size_t kDefaultInlineDepthLimit = 3;
45   static const size_t kDefaultInlineMaxCodeUnits = 32;
46   static constexpr size_t kUnsetInlineDepthLimit = -1;
47   static constexpr size_t kUnsetInlineMaxCodeUnits = -1;
48 
49   // Default inlining settings when the space filter is used.
50   static constexpr size_t kSpaceFilterInlineDepthLimit = 3;
51   static constexpr size_t kSpaceFilterInlineMaxCodeUnits = 10;
52 
53   CompilerOptions();
54   ~CompilerOptions();
55 
56   CompilerOptions(CompilerFilter::Filter compiler_filter,
57                   size_t huge_method_threshold,
58                   size_t large_method_threshold,
59                   size_t small_method_threshold,
60                   size_t tiny_method_threshold,
61                   size_t num_dex_methods_threshold,
62                   size_t inline_depth_limit,
63                   size_t inline_max_code_units,
64                   const std::vector<const DexFile*>* no_inline_from,
65                   bool include_patch_information,
66                   double top_k_profile_threshold,
67                   bool debuggable,
68                   bool generate_debug_info,
69                   bool implicit_null_checks,
70                   bool implicit_so_checks,
71                   bool implicit_suspend_checks,
72                   bool compile_pic,
73                   const std::vector<std::string>* verbose_methods,
74                   std::ostream* init_failure_output,
75                   bool abort_on_hard_verifier_failure,
76                   const std::string& dump_cfg_file_name,
77                   bool dump_cfg_append,
78                   bool force_determinism);
79 
GetCompilerFilter()80   CompilerFilter::Filter GetCompilerFilter() const {
81     return compiler_filter_;
82   }
83 
SetCompilerFilter(CompilerFilter::Filter compiler_filter)84   void SetCompilerFilter(CompilerFilter::Filter compiler_filter) {
85     compiler_filter_ = compiler_filter;
86   }
87 
VerifyAtRuntime()88   bool VerifyAtRuntime() const {
89     return compiler_filter_ == CompilerFilter::kVerifyAtRuntime;
90   }
91 
IsBytecodeCompilationEnabled()92   bool IsBytecodeCompilationEnabled() const {
93     return CompilerFilter::IsBytecodeCompilationEnabled(compiler_filter_);
94   }
95 
IsJniCompilationEnabled()96   bool IsJniCompilationEnabled() const {
97     return CompilerFilter::IsJniCompilationEnabled(compiler_filter_);
98   }
99 
IsVerificationEnabled()100   bool IsVerificationEnabled() const {
101     return CompilerFilter::IsVerificationEnabled(compiler_filter_);
102   }
103 
NeverVerify()104   bool NeverVerify() const {
105     return compiler_filter_ == CompilerFilter::kVerifyNone;
106   }
107 
VerifyOnlyProfile()108   bool VerifyOnlyProfile() const {
109     return compiler_filter_ == CompilerFilter::kVerifyProfile;
110   }
111 
GetHugeMethodThreshold()112   size_t GetHugeMethodThreshold() const {
113     return huge_method_threshold_;
114   }
115 
GetLargeMethodThreshold()116   size_t GetLargeMethodThreshold() const {
117     return large_method_threshold_;
118   }
119 
GetSmallMethodThreshold()120   size_t GetSmallMethodThreshold() const {
121     return small_method_threshold_;
122   }
123 
GetTinyMethodThreshold()124   size_t GetTinyMethodThreshold() const {
125     return tiny_method_threshold_;
126   }
127 
IsHugeMethod(size_t num_dalvik_instructions)128   bool IsHugeMethod(size_t num_dalvik_instructions) const {
129     return num_dalvik_instructions > huge_method_threshold_;
130   }
131 
IsLargeMethod(size_t num_dalvik_instructions)132   bool IsLargeMethod(size_t num_dalvik_instructions) const {
133     return num_dalvik_instructions > large_method_threshold_;
134   }
135 
IsSmallMethod(size_t num_dalvik_instructions)136   bool IsSmallMethod(size_t num_dalvik_instructions) const {
137     return num_dalvik_instructions > small_method_threshold_;
138   }
139 
IsTinyMethod(size_t num_dalvik_instructions)140   bool IsTinyMethod(size_t num_dalvik_instructions) const {
141     return num_dalvik_instructions > tiny_method_threshold_;
142   }
143 
GetNumDexMethodsThreshold()144   size_t GetNumDexMethodsThreshold() const {
145     return num_dex_methods_threshold_;
146   }
147 
GetInlineDepthLimit()148   size_t GetInlineDepthLimit() const {
149     return inline_depth_limit_;
150   }
SetInlineDepthLimit(size_t limit)151   void SetInlineDepthLimit(size_t limit) {
152     inline_depth_limit_ = limit;
153   }
154 
GetInlineMaxCodeUnits()155   size_t GetInlineMaxCodeUnits() const {
156     return inline_max_code_units_;
157   }
SetInlineMaxCodeUnits(size_t units)158   void SetInlineMaxCodeUnits(size_t units) {
159     inline_max_code_units_ = units;
160   }
161 
GetTopKProfileThreshold()162   double GetTopKProfileThreshold() const {
163     return top_k_profile_threshold_;
164   }
165 
GetDebuggable()166   bool GetDebuggable() const {
167     return debuggable_;
168   }
169 
GetNativeDebuggable()170   bool GetNativeDebuggable() const {
171     return GetDebuggable() && GetGenerateDebugInfo();
172   }
173 
174   // This flag controls whether the compiler collects debugging information.
175   // The other flags control how the information is written to disk.
GenerateAnyDebugInfo()176   bool GenerateAnyDebugInfo() const {
177     return GetGenerateDebugInfo() || GetGenerateMiniDebugInfo();
178   }
179 
GetGenerateDebugInfo()180   bool GetGenerateDebugInfo() const {
181     return generate_debug_info_;
182   }
183 
GetGenerateMiniDebugInfo()184   bool GetGenerateMiniDebugInfo() const {
185     return generate_mini_debug_info_;
186   }
187 
GetImplicitNullChecks()188   bool GetImplicitNullChecks() const {
189     return implicit_null_checks_;
190   }
191 
GetImplicitStackOverflowChecks()192   bool GetImplicitStackOverflowChecks() const {
193     return implicit_so_checks_;
194   }
195 
GetImplicitSuspendChecks()196   bool GetImplicitSuspendChecks() const {
197     return implicit_suspend_checks_;
198   }
199 
GetIncludePatchInformation()200   bool GetIncludePatchInformation() const {
201     return include_patch_information_;
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_ != nullptr && !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   }
229 
GetNoInlineFromDexFile()230   const std::vector<const DexFile*>* GetNoInlineFromDexFile() const {
231     return no_inline_from_;
232   }
233 
234   bool ParseCompilerOption(const StringPiece& option, UsageFn Usage);
235 
GetDumpCfgFileName()236   const std::string& GetDumpCfgFileName() const {
237     return dump_cfg_file_name_;
238   }
239 
GetDumpCfgAppend()240   bool GetDumpCfgAppend() const {
241     return dump_cfg_append_;
242   }
243 
IsForceDeterminism()244   bool IsForceDeterminism() const {
245     return force_determinism_;
246   }
247 
248  private:
249   void ParseDumpInitFailures(const StringPiece& option, UsageFn Usage);
250   void ParseDumpCfgPasses(const StringPiece& option, UsageFn Usage);
251   void ParseInlineMaxCodeUnits(const StringPiece& option, UsageFn Usage);
252   void ParseInlineDepthLimit(const StringPiece& option, UsageFn Usage);
253   void ParseNumDexMethods(const StringPiece& option, UsageFn Usage);
254   void ParseTinyMethodMax(const StringPiece& option, UsageFn Usage);
255   void ParseSmallMethodMax(const StringPiece& option, UsageFn Usage);
256   void ParseLargeMethodMax(const StringPiece& option, UsageFn Usage);
257   void ParseHugeMethodMax(const StringPiece& option, UsageFn Usage);
258 
259   CompilerFilter::Filter compiler_filter_;
260   size_t huge_method_threshold_;
261   size_t large_method_threshold_;
262   size_t small_method_threshold_;
263   size_t tiny_method_threshold_;
264   size_t num_dex_methods_threshold_;
265   size_t inline_depth_limit_;
266   size_t inline_max_code_units_;
267 
268   // Dex files from which we should not inline code.
269   // This is usually a very short list (i.e. a single dex file), so we
270   // prefer vector<> over a lookup-oriented container, such as set<>.
271   const std::vector<const DexFile*>* no_inline_from_;
272 
273   bool include_patch_information_;
274   // When using a profile file only the top K% of the profiled samples will be compiled.
275   double top_k_profile_threshold_;
276   bool debuggable_;
277   bool generate_debug_info_;
278   bool generate_mini_debug_info_;
279   bool implicit_null_checks_;
280   bool implicit_so_checks_;
281   bool implicit_suspend_checks_;
282   bool compile_pic_;
283 
284   // Vector of methods to have verbose output enabled for.
285   const std::vector<std::string>* verbose_methods_;
286 
287   // Abort compilation with an error if we find a class that fails verification with a hard
288   // failure.
289   bool abort_on_hard_verifier_failure_;
290 
291   // Log initialization of initialization failures to this stream if not null.
292   std::unique_ptr<std::ostream> init_failure_output_;
293 
294   std::string dump_cfg_file_name_;
295   bool dump_cfg_append_;
296 
297   // Whether the compiler should trade performance for determinism to guarantee exactly reproducable
298   // outcomes.
299   bool force_determinism_;
300 
301   friend class Dex2Oat;
302 
303   DISALLOW_COPY_AND_ASSIGN(CompilerOptions);
304 };
305 
306 }  // namespace art
307 
308 #endif  // ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
309