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