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 <memory>
21 #include <ostream>
22 #include <string>
23 #include <vector>
24 
25 #include "base/globals.h"
26 #include "base/hash_set.h"
27 #include "base/macros.h"
28 #include "base/utils.h"
29 #include "compiler_filter.h"
30 #include "optimizing/register_allocator.h"
31 
32 namespace art {
33 
34 namespace jit {
35 class JitCompiler;
36 }  // namespace jit
37 
38 namespace verifier {
39 class VerifierDepsTest;
40 }  // namespace verifier
41 
42 namespace linker {
43 class Arm64RelativePatcherTest;
44 }  // namespace linker
45 
46 class DexFile;
47 enum class InstructionSet;
48 class InstructionSetFeatures;
49 class ProfileCompilationInfo;
50 class VerificationResults;
51 class VerifiedMethod;
52 
53 // Enum for CheckProfileMethodsCompiled. Outside CompilerOptions so it can be forward-declared.
54 enum class ProfileMethodsCheck : uint8_t {
55   kNone,
56   kLog,
57   kAbort,
58 };
59 
60 class CompilerOptions final {
61  public:
62   // Guide heuristics to determine whether to compile method if profile data not available.
63   static const size_t kDefaultHugeMethodThreshold = 10000;
64   static const size_t kDefaultLargeMethodThreshold = 600;
65   static const size_t kDefaultSmallMethodThreshold = 60;
66   static const size_t kDefaultTinyMethodThreshold = 20;
67   static const size_t kDefaultNumDexMethodsThreshold = 900;
68   static constexpr double kDefaultTopKProfileThreshold = 90.0;
69   static const bool kDefaultGenerateDebugInfo = false;
70   static const bool kDefaultGenerateMiniDebugInfo = false;
71   static const size_t kDefaultInlineMaxCodeUnits = 32;
72   static constexpr size_t kUnsetInlineMaxCodeUnits = -1;
73 
74   enum class ImageType : uint8_t {
75     kNone,                // JIT or AOT app compilation producing only an oat file but no image.
76     kBootImage,           // Creating boot image.
77     kAppImage,            // Creating app image.
78     kApexBootImage,       // Creating the apex image for jit/zygote experiment b/119800099.
79   };
80 
81   CompilerOptions();
82   ~CompilerOptions();
83 
GetCompilerFilter()84   CompilerFilter::Filter GetCompilerFilter() const {
85     return compiler_filter_;
86   }
87 
SetCompilerFilter(CompilerFilter::Filter compiler_filter)88   void SetCompilerFilter(CompilerFilter::Filter compiler_filter) {
89     compiler_filter_ = compiler_filter;
90   }
91 
IsAotCompilationEnabled()92   bool IsAotCompilationEnabled() const {
93     return CompilerFilter::IsAotCompilationEnabled(compiler_filter_);
94   }
95 
IsJniCompilationEnabled()96   bool IsJniCompilationEnabled() const {
97     return CompilerFilter::IsJniCompilationEnabled(compiler_filter_);
98   }
99 
IsQuickeningCompilationEnabled()100   bool IsQuickeningCompilationEnabled() const {
101     return CompilerFilter::IsQuickeningCompilationEnabled(compiler_filter_);
102   }
103 
IsVerificationEnabled()104   bool IsVerificationEnabled() const {
105     return CompilerFilter::IsVerificationEnabled(compiler_filter_);
106   }
107 
AssumeClassesAreVerified()108   bool AssumeClassesAreVerified() const {
109     return compiler_filter_ == CompilerFilter::kAssumeVerified;
110   }
111 
VerifyAtRuntime()112   bool VerifyAtRuntime() const {
113     return compiler_filter_ == CompilerFilter::kExtract;
114   }
115 
IsAnyCompilationEnabled()116   bool IsAnyCompilationEnabled() const {
117     return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_);
118   }
119 
GetHugeMethodThreshold()120   size_t GetHugeMethodThreshold() const {
121     return huge_method_threshold_;
122   }
123 
GetLargeMethodThreshold()124   size_t GetLargeMethodThreshold() const {
125     return large_method_threshold_;
126   }
127 
GetSmallMethodThreshold()128   size_t GetSmallMethodThreshold() const {
129     return small_method_threshold_;
130   }
131 
GetTinyMethodThreshold()132   size_t GetTinyMethodThreshold() const {
133     return tiny_method_threshold_;
134   }
135 
IsHugeMethod(size_t num_dalvik_instructions)136   bool IsHugeMethod(size_t num_dalvik_instructions) const {
137     return num_dalvik_instructions > huge_method_threshold_;
138   }
139 
IsLargeMethod(size_t num_dalvik_instructions)140   bool IsLargeMethod(size_t num_dalvik_instructions) const {
141     return num_dalvik_instructions > large_method_threshold_;
142   }
143 
IsSmallMethod(size_t num_dalvik_instructions)144   bool IsSmallMethod(size_t num_dalvik_instructions) const {
145     return num_dalvik_instructions > small_method_threshold_;
146   }
147 
IsTinyMethod(size_t num_dalvik_instructions)148   bool IsTinyMethod(size_t num_dalvik_instructions) const {
149     return num_dalvik_instructions > tiny_method_threshold_;
150   }
151 
GetNumDexMethodsThreshold()152   size_t GetNumDexMethodsThreshold() const {
153     return num_dex_methods_threshold_;
154   }
155 
GetInlineMaxCodeUnits()156   size_t GetInlineMaxCodeUnits() const {
157     return inline_max_code_units_;
158   }
SetInlineMaxCodeUnits(size_t units)159   void SetInlineMaxCodeUnits(size_t units) {
160     inline_max_code_units_ = units;
161   }
162 
GetTopKProfileThreshold()163   double GetTopKProfileThreshold() const {
164     return top_k_profile_threshold_;
165   }
166 
GetDebuggable()167   bool GetDebuggable() const {
168     return debuggable_;
169   }
170 
SetDebuggable(bool value)171   void SetDebuggable(bool value) {
172     debuggable_ = value;
173   }
174 
GetNativeDebuggable()175   bool GetNativeDebuggable() const {
176     return GetDebuggable() && GetGenerateDebugInfo();
177   }
178 
179   // This flag controls whether the compiler collects debugging information.
180   // The other flags control how the information is written to disk.
GenerateAnyDebugInfo()181   bool GenerateAnyDebugInfo() const {
182     return GetGenerateDebugInfo() || GetGenerateMiniDebugInfo();
183   }
184 
GetGenerateDebugInfo()185   bool GetGenerateDebugInfo() const {
186     return generate_debug_info_;
187   }
188 
GetGenerateMiniDebugInfo()189   bool GetGenerateMiniDebugInfo() const {
190     return generate_mini_debug_info_;
191   }
192 
193   // Should run-time checks be emitted in debug mode?
194   bool EmitRunTimeChecksInDebugMode() const;
195 
GetGenerateBuildId()196   bool GetGenerateBuildId() const {
197     return generate_build_id_;
198   }
199 
GetImplicitNullChecks()200   bool GetImplicitNullChecks() const {
201     return implicit_null_checks_;
202   }
203 
GetImplicitStackOverflowChecks()204   bool GetImplicitStackOverflowChecks() const {
205     return implicit_so_checks_;
206   }
207 
GetImplicitSuspendChecks()208   bool GetImplicitSuspendChecks() const {
209     return implicit_suspend_checks_;
210   }
211 
212   // Are we compiling a boot image?
IsBootImage()213   bool IsBootImage() const {
214     return image_type_ == ImageType::kBootImage || image_type_ == ImageType::kApexBootImage;
215   }
216 
IsApexBootImage()217   bool IsApexBootImage() const {
218     return image_type_ == ImageType::kApexBootImage;
219   }
220 
IsBaseline()221   bool IsBaseline() const {
222     return baseline_;
223   }
224 
225   // Are we compiling an app image?
IsAppImage()226   bool IsAppImage() const {
227     return image_type_ == ImageType::kAppImage;
228   }
229 
230   // Returns whether we are compiling against a "core" image, which
231   // is an indicative we are running tests. The compiler will use that
232   // information for checking invariants.
CompilingWithCoreImage()233   bool CompilingWithCoreImage() const {
234     return compiling_with_core_image_;
235   }
236 
237   // Should the code be compiled as position independent?
GetCompilePic()238   bool GetCompilePic() const {
239     return compile_pic_;
240   }
241 
GetProfileCompilationInfo()242   const ProfileCompilationInfo* GetProfileCompilationInfo() const {
243     return profile_compilation_info_;
244   }
245 
HasVerboseMethods()246   bool HasVerboseMethods() const {
247     return !verbose_methods_.empty();
248   }
249 
IsVerboseMethod(const std::string & pretty_method)250   bool IsVerboseMethod(const std::string& pretty_method) const {
251     for (const std::string& cur_method : verbose_methods_) {
252       if (pretty_method.find(cur_method) != std::string::npos) {
253         return true;
254       }
255     }
256     return false;
257   }
258 
GetInitFailureOutput()259   std::ostream* GetInitFailureOutput() const {
260     return init_failure_output_.get();
261   }
262 
AbortOnHardVerifierFailure()263   bool AbortOnHardVerifierFailure() const {
264     return abort_on_hard_verifier_failure_;
265   }
AbortOnSoftVerifierFailure()266   bool AbortOnSoftVerifierFailure() const {
267     return abort_on_soft_verifier_failure_;
268   }
269 
GetInstructionSet()270   InstructionSet GetInstructionSet() const {
271     return instruction_set_;
272   }
273 
GetInstructionSetFeatures()274   const InstructionSetFeatures* GetInstructionSetFeatures() const {
275     return instruction_set_features_.get();
276   }
277 
278 
GetNoInlineFromDexFile()279   const std::vector<const DexFile*>& GetNoInlineFromDexFile() const {
280     return no_inline_from_;
281   }
282 
GetDexFilesForOatFile()283   const std::vector<const DexFile*>& GetDexFilesForOatFile() const {
284     return dex_files_for_oat_file_;
285   }
286 
GetImageClasses()287   const HashSet<std::string>& GetImageClasses() const {
288     return image_classes_;
289   }
290 
291   bool IsImageClass(const char* descriptor) const;
292 
293   const VerificationResults* GetVerificationResults() const;
294 
295   const VerifiedMethod* GetVerifiedMethod(const DexFile* dex_file, uint32_t method_idx) const;
296 
297   // Checks if the specified method has been verified without failures. Returns
298   // false if the method is not in the verification results (GetVerificationResults).
299   bool IsMethodVerifiedWithoutFailures(uint32_t method_idx,
300                                        uint16_t class_def_idx,
301                                        const DexFile& dex_file) const;
302 
303   bool ParseCompilerOptions(const std::vector<std::string>& options,
304                             bool ignore_unrecognized,
305                             std::string* error_msg);
306 
SetNonPic()307   void SetNonPic() {
308     compile_pic_ = false;
309   }
310 
GetDumpCfgFileName()311   const std::string& GetDumpCfgFileName() const {
312     return dump_cfg_file_name_;
313   }
314 
GetDumpCfgAppend()315   bool GetDumpCfgAppend() const {
316     return dump_cfg_append_;
317   }
318 
IsForceDeterminism()319   bool IsForceDeterminism() const {
320     return force_determinism_;
321   }
322 
DeduplicateCode()323   bool DeduplicateCode() const {
324     return deduplicate_code_;
325   }
326 
GetRegisterAllocationStrategy()327   RegisterAllocator::Strategy GetRegisterAllocationStrategy() const {
328     return register_allocation_strategy_;
329   }
330 
GetPassesToRun()331   const std::vector<std::string>* GetPassesToRun() const {
332     return passes_to_run_;
333   }
334 
GetDumpTimings()335   bool GetDumpTimings() const {
336     return dump_timings_;
337   }
338 
GetDumpPassTimings()339   bool GetDumpPassTimings() const {
340     return dump_pass_timings_;
341   }
342 
GetDumpStats()343   bool GetDumpStats() const {
344     return dump_stats_;
345   }
346 
CountHotnessInCompiledCode()347   bool CountHotnessInCompiledCode() const {
348     return count_hotness_in_compiled_code_;
349   }
350 
ResolveStartupConstStrings()351   bool ResolveStartupConstStrings() const {
352     return resolve_startup_const_strings_;
353   }
354 
CheckProfiledMethodsCompiled()355   ProfileMethodsCheck CheckProfiledMethodsCompiled() const {
356     return check_profiled_methods_;
357   }
358 
MaxImageBlockSize()359   uint32_t MaxImageBlockSize() const {
360     return max_image_block_size_;
361   }
362 
SetMaxImageBlockSize(uint32_t size)363   void SetMaxImageBlockSize(uint32_t size) {
364     max_image_block_size_ = size;
365   }
366 
367   // Is `boot_image_filename` the name of a core image (small boot
368   // image used for ART testing only)?
369   static bool IsCoreImageFilename(const std::string& boot_image_filename);
370 
371  private:
372   bool ParseDumpInitFailures(const std::string& option, std::string* error_msg);
373   bool ParseRegisterAllocationStrategy(const std::string& option, std::string* error_msg);
374 
375   CompilerFilter::Filter compiler_filter_;
376   size_t huge_method_threshold_;
377   size_t large_method_threshold_;
378   size_t small_method_threshold_;
379   size_t tiny_method_threshold_;
380   size_t num_dex_methods_threshold_;
381   size_t inline_max_code_units_;
382 
383   InstructionSet instruction_set_;
384   std::unique_ptr<const InstructionSetFeatures> instruction_set_features_;
385 
386   // Dex files from which we should not inline code. Does not own the dex files.
387   // This is usually a very short list (i.e. a single dex file), so we
388   // prefer vector<> over a lookup-oriented container, such as set<>.
389   std::vector<const DexFile*> no_inline_from_;
390 
391   // List of dex files associated with the oat file, empty for JIT.
392   std::vector<const DexFile*> dex_files_for_oat_file_;
393 
394   // Image classes, specifies the classes that will be included in the image if creating an image.
395   // Must not be empty for real boot image, only for tests pretending to compile boot image.
396   HashSet<std::string> image_classes_;
397 
398   // Results of AOT verification.
399   const VerificationResults* verification_results_;
400 
401   ImageType image_type_;
402   bool compiling_with_core_image_;
403   bool baseline_;
404   bool debuggable_;
405   bool generate_debug_info_;
406   bool generate_mini_debug_info_;
407   bool generate_build_id_;
408   bool implicit_null_checks_;
409   bool implicit_so_checks_;
410   bool implicit_suspend_checks_;
411   bool compile_pic_;
412   bool dump_timings_;
413   bool dump_pass_timings_;
414   bool dump_stats_;
415 
416   // When using a profile file only the top K% of the profiled samples will be compiled.
417   double top_k_profile_threshold_;
418 
419   // Info for profile guided compilation.
420   const ProfileCompilationInfo* profile_compilation_info_;
421 
422   // Vector of methods to have verbose output enabled for.
423   std::vector<std::string> verbose_methods_;
424 
425   // Abort compilation with an error if we find a class that fails verification with a hard
426   // failure.
427   bool abort_on_hard_verifier_failure_;
428   // Same for soft failures.
429   bool abort_on_soft_verifier_failure_;
430 
431   // Log initialization of initialization failures to this stream if not null.
432   std::unique_ptr<std::ostream> init_failure_output_;
433 
434   std::string dump_cfg_file_name_;
435   bool dump_cfg_append_;
436 
437   // Whether the compiler should trade performance for determinism to guarantee exactly reproducible
438   // outcomes.
439   bool force_determinism_;
440 
441   // Whether code should be deduplicated.
442   bool deduplicate_code_;
443 
444   // Whether compiled code should increment the hotness count of ArtMethod. Note that the increments
445   // won't be atomic for performance reasons, so we accept races, just like in interpreter.
446   bool count_hotness_in_compiled_code_;
447 
448   // Whether we eagerly resolve all of the const strings that are loaded from startup methods in the
449   // profile.
450   bool resolve_startup_const_strings_;
451 
452   // When running profile-guided compilation, check that methods intended to be compiled end
453   // up compiled and are not punted.
454   ProfileMethodsCheck check_profiled_methods_;
455 
456   // Maximum solid block size in the generated image.
457   uint32_t max_image_block_size_;
458 
459   RegisterAllocator::Strategy register_allocation_strategy_;
460 
461   // If not null, specifies optimization passes which will be run instead of defaults.
462   // Note that passes_to_run_ is not checked for correctness and providing an incorrect
463   // list of passes can lead to unexpected compiler behaviour. This is caused by dependencies
464   // between passes. Failing to satisfy them can for example lead to compiler crashes.
465   // Passing pass names which are not recognized by the compiler will result in
466   // compiler-dependant behavior.
467   const std::vector<std::string>* passes_to_run_;
468 
469   friend class Dex2Oat;
470   friend class DexToDexDecompilerTest;
471   friend class CommonCompilerDriverTest;
472   friend class CommonCompilerTest;
473   friend class jit::JitCompiler;
474   friend class verifier::VerifierDepsTest;
475   friend class linker::Arm64RelativePatcherTest;
476 
477   template <class Base>
478   friend bool ReadCompilerOptions(Base& map, CompilerOptions* options, std::string* error_msg);
479 
480   DISALLOW_COPY_AND_ASSIGN(CompilerOptions);
481 };
482 
483 }  // namespace art
484 
485 #endif  // ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_
486