diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/dex/frontend.cc | 2 | ||||
-rw-r--r-- | compiler/dex/mir_analysis.cc | 39 | ||||
-rw-r--r-- | compiler/dex/mir_graph.h | 2 | ||||
-rw-r--r-- | compiler/dex/verification_results.cc | 20 | ||||
-rw-r--r-- | compiler/dex/verification_results.h | 12 | ||||
-rw-r--r-- | compiler/driver/compiler_callbacks_impl.h | 59 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 11 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 10 | ||||
-rw-r--r-- | compiler/driver/compiler_options.h | 136 | ||||
-rw-r--r-- | compiler/oat_test.cc | 9 |
10 files changed, 262 insertions, 38 deletions
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc index 591d92a73d..6800f7b2a4 100644 --- a/compiler/dex/frontend.cc +++ b/compiler/dex/frontend.cc @@ -211,7 +211,7 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler, class_loader, dex_file); cu.NewTimingSplit("MIROpt:CheckFilters"); - if (cu.mir_graph->SkipCompilation(Runtime::Current()->GetCompilerFilter())) { + if (cu.mir_graph->SkipCompilation()) { return NULL; } diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc index ab55333fa7..7ce8f696be 100644 --- a/compiler/dex/mir_analysis.cc +++ b/compiler/dex/mir_analysis.cc @@ -18,6 +18,7 @@ #include "dataflow_iterator-inl.h" #include "dex/quick/dex_file_method_inliner.h" #include "dex/quick/dex_file_to_method_inliner_map.h" +#include "driver/compiler_options.h" namespace art { @@ -958,7 +959,7 @@ bool MIRGraph::ComputeSkipCompilation(MethodStats* stats, bool skip_default) { } // Complex, logic-intensive? - if ((GetNumDalvikInsns() > Runtime::Current()->GetSmallMethodThreshold()) && + if (cu_->compiler_driver->GetCompilerOptions().IsSmallMethod(GetNumDalvikInsns()) && stats->branch_ratio > 0.3) { return false; } @@ -984,7 +985,7 @@ bool MIRGraph::ComputeSkipCompilation(MethodStats* stats, bool skip_default) { } // If significant in size and high proportion of expensive operations, skip. - if ((GetNumDalvikInsns() > Runtime::Current()->GetSmallMethodThreshold()) && + if (cu_->compiler_driver->GetCompilerOptions().IsSmallMethod(GetNumDalvikInsns()) && (stats->heavyweight_ratio > 0.3)) { return true; } @@ -996,12 +997,14 @@ bool MIRGraph::ComputeSkipCompilation(MethodStats* stats, bool skip_default) { * Will eventually want this to be a bit more sophisticated and happen at verification time. * Ultimate goal is to drive with profile data. */ -bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) { - if (compiler_filter == Runtime::kEverything) { +bool MIRGraph::SkipCompilation() { + const CompilerOptions& compiler_options = cu_->compiler_driver->GetCompilerOptions(); + CompilerOptions::CompilerFilter compiler_filter = compiler_options.GetCompilerFilter(); + if (compiler_filter == CompilerOptions::kEverything) { return false; } - if (compiler_filter == Runtime::kInterpretOnly) { + if (compiler_filter == CompilerOptions::kInterpretOnly) { LOG(WARNING) << "InterpretOnly should ideally be filtered out prior to parsing."; return true; } @@ -1010,17 +1013,17 @@ bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) { size_t small_cutoff = 0; size_t default_cutoff = 0; switch (compiler_filter) { - case Runtime::kBalanced: - small_cutoff = Runtime::Current()->GetSmallMethodThreshold(); - default_cutoff = Runtime::Current()->GetLargeMethodThreshold(); + case CompilerOptions::kBalanced: + small_cutoff = compiler_options.GetSmallMethodThreshold(); + default_cutoff = compiler_options.GetLargeMethodThreshold(); break; - case Runtime::kSpace: - small_cutoff = Runtime::Current()->GetTinyMethodThreshold(); - default_cutoff = Runtime::Current()->GetSmallMethodThreshold(); + case CompilerOptions::kSpace: + small_cutoff = compiler_options.GetTinyMethodThreshold(); + default_cutoff = compiler_options.GetSmallMethodThreshold(); break; - case Runtime::kSpeed: - small_cutoff = Runtime::Current()->GetHugeMethodThreshold(); - default_cutoff = Runtime::Current()->GetHugeMethodThreshold(); + case CompilerOptions::kSpeed: + small_cutoff = compiler_options.GetHugeMethodThreshold(); + default_cutoff = compiler_options.GetHugeMethodThreshold(); break; default: LOG(FATAL) << "Unexpected compiler_filter_: " << compiler_filter; @@ -1033,17 +1036,17 @@ bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) { * Filter 1: Huge methods are likely to be machine generated, but some aren't. * If huge, assume we won't compile, but allow futher analysis to turn it back on. */ - if (GetNumDalvikInsns() > Runtime::Current()->GetHugeMethodThreshold()) { + if (compiler_options.IsHugeMethod(GetNumDalvikInsns())) { skip_compilation = true; // If we're got a huge number of basic blocks, don't bother with further analysis. - if (static_cast<size_t>(num_blocks_) > (Runtime::Current()->GetHugeMethodThreshold() / 2)) { + if (static_cast<size_t>(num_blocks_) > (compiler_options.GetHugeMethodThreshold() / 2)) { return true; } - } else if (GetNumDalvikInsns() > Runtime::Current()->GetLargeMethodThreshold() && + } else if (compiler_options.IsLargeMethod(GetNumDalvikInsns()) && /* If it's large and contains no branches, it's likely to be machine generated initialization */ (GetBranchCount() == 0)) { return true; - } else if (compiler_filter == Runtime::kSpeed) { + } else if (compiler_filter == CompilerOptions::kSpeed) { // If not huge, compile. return false; } diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index d844aac10b..2174f679bf 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -372,7 +372,7 @@ class MIRGraph { * Examine the graph to determine whether it's worthwile to spend the time compiling * this method. */ - bool SkipCompilation(Runtime::CompilerFilter compiler_filter); + bool SkipCompilation(); /* * Parse dex method and add MIR at current insert point. Returns id (which is diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc index edccec55ba..947c22d668 100644 --- a/compiler/dex/verification_results.cc +++ b/compiler/dex/verification_results.cc @@ -19,6 +19,8 @@ #include "base/stl_util.h" #include "base/mutex.h" #include "base/mutex-inl.h" +#include "driver/compiler_driver.h" +#include "driver/compiler_options.h" #include "thread.h" #include "thread-inl.h" #include "verified_method.h" @@ -27,8 +29,9 @@ namespace art { -VerificationResults::VerificationResults() - : verified_methods_lock_("compiler verified methods lock"), +VerificationResults::VerificationResults(const CompilerOptions* compiler_options) + : compiler_options_(compiler_options), + verified_methods_lock_("compiler verified methods lock"), verified_methods_(), rejected_classes_lock_("compiler rejected classes lock"), rejected_classes_() { @@ -43,6 +46,7 @@ VerificationResults::~VerificationResults() { } bool VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) { + DCHECK(method_verifier != NULL); MethodReference ref = method_verifier->GetMethodReference(); bool compile = IsCandidateForCompilation(ref, method_verifier->GetAccessFlags()); // TODO: Check also for virtual/interface invokes when DEX-to-DEX supports devirtualization. @@ -95,16 +99,18 @@ bool VerificationResults::IsClassRejected(ClassReference ref) { bool VerificationResults::IsCandidateForCompilation(MethodReference& method_ref, const uint32_t access_flags) { #ifdef ART_SEA_IR_MODE - bool use_sea = Runtime::Current()->IsSeaIRMode(); - use_sea = use_sea && (std::string::npos != PrettyMethod( - method_ref.dex_method_index, *(method_ref.dex_file)).find("fibonacci")); - if (use_sea) return true; + bool use_sea = compiler_options_->GetSeaIrMode(); + use_sea = use_sea && (std::string::npos != PrettyMethod( + method_ref.dex_method_index, *(method_ref.dex_file)).find("fibonacci")); + if (use_sea) { + return true; + } #endif // Don't compile class initializers, ever. if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) { return false; } - return (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly); + return (compiler_options_->GetCompilerFilter() != CompilerOptions::kInterpretOnly); } } // namespace art diff --git a/compiler/dex/verification_results.h b/compiler/dex/verification_results.h index 2eb07131ce..278182f2aa 100644 --- a/compiler/dex/verification_results.h +++ b/compiler/dex/verification_results.h @@ -33,11 +33,13 @@ namespace verifier { class MethodVerifier; } // namespace verifier +class CompilerOptions; class VerifiedMethod; +// Used by CompilerCallbacks to track verification information from the Runtime. class VerificationResults { public: - VerificationResults(); + explicit VerificationResults(const CompilerOptions* compiler_options); ~VerificationResults(); bool ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) @@ -50,15 +52,17 @@ class VerificationResults { void AddRejectedClass(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_); bool IsClassRejected(ClassReference ref) LOCKS_EXCLUDED(rejected_classes_lock_); - static bool IsCandidateForCompilation(MethodReference& method_ref, - const uint32_t access_flags); + bool IsCandidateForCompilation(MethodReference& method_ref, + const uint32_t access_flags); private: + const CompilerOptions* compiler_options_; + // Verified methods. typedef SafeMap<MethodReference, const VerifiedMethod*, MethodReferenceComparator> VerifiedMethodMap; ReaderWriterMutex verified_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - VerifiedMethodMap verified_methods_; + VerifiedMethodMap verified_methods_ GUARDED_BY(verified_methods_lock_); // Rejected classes. ReaderWriterMutex rejected_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; diff --git a/compiler/driver/compiler_callbacks_impl.h b/compiler/driver/compiler_callbacks_impl.h new file mode 100644 index 0000000000..ab57832961 --- /dev/null +++ b/compiler/driver/compiler_callbacks_impl.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_ +#define ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_ + +#include "compiler_callbacks.h" +#include "dex/quick/dex_file_to_method_inliner_map.h" +#include "verifier/method_verifier-inl.h" + +namespace art { + +class CompilerCallbacksImpl : public CompilerCallbacks { + public: + CompilerCallbacksImpl(VerificationResults* verification_results, + DexFileToMethodInlinerMap* method_inliner_map) + : verification_results_(verification_results), + method_inliner_map_(method_inliner_map) { + CHECK(verification_results != nullptr); + CHECK(method_inliner_map != nullptr); + } + + virtual ~CompilerCallbacksImpl() { } + + virtual bool MethodVerified(verifier::MethodVerifier* verifier) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + bool result = verification_results_->ProcessVerifiedMethod(verifier); + if (result) { + MethodReference ref = verifier->GetMethodReference(); + method_inliner_map_->GetMethodInliner(ref.dex_file) + ->AnalyseMethodCode(verifier); + } + return result; + } + virtual void ClassRejected(ClassReference ref) { + verification_results_->AddRejectedClass(ref); + } + + private: + VerificationResults* verification_results_; + DexFileToMethodInlinerMap* method_inliner_map_; +}; + +} // namespace art + +#endif // ART_COMPILER_DRIVER_COMPILER_CALLBACKS_IMPL_H_ diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 54397f5e31..1b284de9cc 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -293,14 +293,16 @@ extern "C" art::CompiledMethod* ArtCompileDEX(art::CompilerDriver& compiler, jobject class_loader, const art::DexFile& dex_file); -CompilerDriver::CompilerDriver(VerificationResults* verification_results, +CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options, + VerificationResults* verification_results, DexFileToMethodInlinerMap* method_inliner_map, CompilerBackend::Kind compiler_backend_kind, InstructionSet instruction_set, InstructionSetFeatures instruction_set_features, bool image, DescriptorSet* image_classes, size_t thread_count, bool dump_stats, bool dump_passes, CumulativeLogger* timer) - : verification_results_(verification_results), + : compiler_options_(compiler_options), + verification_results_(verification_results), method_inliner_map_(method_inliner_map), compiler_backend_(CompilerBackend::Create(compiler_backend_kind)), instruction_set_(instruction_set), @@ -325,6 +327,9 @@ CompilerDriver::CompilerDriver(VerificationResults* verification_results, dedupe_mapping_table_("dedupe mapping table"), dedupe_vmap_table_("dedupe vmap table"), dedupe_gc_map_("dedupe gc map") { + DCHECK(compiler_options_ != nullptr); + DCHECK(verification_results_ != nullptr); + DCHECK(method_inliner_map_ != nullptr); CHECK_PTHREAD_CALL(pthread_key_create, (&tls_key_, NULL), "compiler tls key"); @@ -1932,7 +1937,7 @@ void CompilerDriver::CompileMethod(const DexFile::CodeItem* code_item, uint32_t } else if ((access_flags & kAccAbstract) != 0) { } else { MethodReference method_ref(&dex_file, method_idx); - bool compile = VerificationResults::IsCandidateForCompilation(method_ref, access_flags); + bool compile = verification_results_->IsCandidateForCompilation(method_ref, access_flags); if (compile) { // NOTE: if compiler declines to compile this method, it will return NULL. diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 092fe52b24..5009779bed 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -45,6 +45,7 @@ class MethodVerifier; } // namespace verifier class AOTCompilationStats; +class CompilerOptions; class DexCompilationUnit; class DexFileToMethodInlinerMap; class InlineIGetIPutData; @@ -94,7 +95,8 @@ class CompilerDriver { // enabled. "image_classes" lets the compiler know what classes it // can assume will be in the image, with NULL implying all available // classes. - explicit CompilerDriver(VerificationResults* verification_results, + explicit CompilerDriver(const CompilerOptions* compiler_options, + VerificationResults* verification_results, DexFileToMethodInlinerMap* method_inliner_map, CompilerBackend::Kind compiler_backend_kind, InstructionSet instruction_set, @@ -129,6 +131,11 @@ class CompilerDriver { return instruction_set_features_; } + const CompilerOptions& GetCompilerOptions() const { + DCHECK(compiler_options_ != nullptr); + return *compiler_options_; + } + CompilerBackend* GetCompilerBackend() const { return compiler_backend_.get(); } @@ -551,6 +558,7 @@ class CompilerDriver { std::vector<const CallPatchInformation*> methods_to_patch_; std::vector<const TypePatchInformation*> classes_to_patch_; + const CompilerOptions* compiler_options_; VerificationResults* verification_results_; DexFileToMethodInlinerMap* method_inliner_map_; diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h new file mode 100644 index 0000000000..9f6745b015 --- /dev/null +++ b/compiler/driver/compiler_options.h @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_ +#define ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_ + +namespace art { + +class CompilerOptions { + public: + enum CompilerFilter { + kInterpretOnly, // Compile nothing. + kSpace, // Maximize space savings. + kBalanced, // Try to get the best performance return on compilation investment. + kSpeed, // Maximize runtime performance. + kEverything // Force compilation (Note: excludes compilaton of class initializers). + }; + + // Guide heuristics to determine whether to compile method if profile data not available. + static const CompilerFilter kDefaultCompilerFilter = kSpeed; + static const size_t kDefaultHugeMethodThreshold = 10000; + static const size_t kDefaultLargeMethodThreshold = 600; + static const size_t kDefaultSmallMethodThreshold = 60; + static const size_t kDefaultTinyMethodThreshold = 20; + static const size_t kDefaultNumDexMethodsThreshold = 900; + + CompilerOptions() : + compiler_filter_(kDefaultCompilerFilter), + huge_method_threshold_(kDefaultHugeMethodThreshold), + large_method_threshold_(kDefaultLargeMethodThreshold), + small_method_threshold_(kDefaultSmallMethodThreshold), + tiny_method_threshold_(kDefaultTinyMethodThreshold), + num_dex_methods_threshold_(kDefaultNumDexMethodsThreshold) +#ifdef ART_SEA_IR_MODE + , sea_ir_mode_(false) +#endif + {} + + CompilerOptions(CompilerFilter compiler_filter, + size_t huge_method_threshold, + size_t large_method_threshold, + size_t small_method_threshold, + size_t tiny_method_threshold, + size_t num_dex_methods_threshold +#ifdef ART_SEA_IR_MODE + , bool sea_ir_mode +#endif + ) : // NOLINT(whitespace/parens) + compiler_filter_(compiler_filter), + huge_method_threshold_(huge_method_threshold), + large_method_threshold_(large_method_threshold), + small_method_threshold_(small_method_threshold), + tiny_method_threshold_(tiny_method_threshold), + num_dex_methods_threshold_(num_dex_methods_threshold) +#ifdef ART_SEA_IR_MODE + , sea_ir_mode_(sea_ir_mode) +#endif + {} + + CompilerFilter GetCompilerFilter() const { + return compiler_filter_; + } + + void SetCompilerFilter(CompilerFilter compiler_filter) { + compiler_filter_ = compiler_filter; + } + + size_t GetHugeMethodThreshold() const { + return huge_method_threshold_; + } + + size_t GetLargeMethodThreshold() const { + return large_method_threshold_; + } + + size_t GetSmallMethodThreshold() const { + return small_method_threshold_; + } + + size_t GetTinyMethodThreshold() const { + return tiny_method_threshold_; + } + + bool IsHugeMethod(size_t num_dalvik_instructions) const { + return num_dalvik_instructions > huge_method_threshold_; + } + + bool IsLargeMethod(size_t num_dalvik_instructions) const { + return num_dalvik_instructions > large_method_threshold_; + } + + bool IsSmallMethod(size_t num_dalvik_instructions) const { + return num_dalvik_instructions > small_method_threshold_; + } + + bool IsTinyMethod(size_t num_dalvik_instructions) const { + return num_dalvik_instructions > tiny_method_threshold_; + } + + size_t GetNumDexMethodsThreshold() const { + return num_dex_methods_threshold_; + } + +#ifdef ART_SEA_IR_MODE + bool GetSeaIrMode(); +#endif + + private: + CompilerFilter compiler_filter_; + size_t huge_method_threshold_; + size_t large_method_threshold_; + size_t small_method_threshold_; + size_t tiny_method_threshold_; + size_t num_dex_methods_threshold_; + +#ifdef ART_SEA_IR_MODE + bool sea_ir_mode_; +#endif +}; + +} // namespace art + +#endif // ART_COMPILER_DRIVER_COMPILER_OPTIONS_H_ diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index e9c77d1a02..e91ffcb519 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -91,11 +91,14 @@ TEST_F(OatTest, WriteRead) { InstructionSet insn_set = kIsTargetBuild ? kThumb2 : kX86; InstructionSetFeatures insn_features; - verification_results_.reset(new VerificationResults); + compiler_options_.reset(new CompilerOptions); + verification_results_.reset(new VerificationResults(compiler_options_.get())); method_inliner_map_.reset(new DexFileToMethodInlinerMap); - callbacks_.Reset(verification_results_.get(), method_inliner_map_.get()); + callbacks_.reset(new CompilerCallbacksImpl(verification_results_.get(), + method_inliner_map_.get())); timer_.reset(new CumulativeLogger("Compilation times")); - compiler_driver_.reset(new CompilerDriver(verification_results_.get(), + compiler_driver_.reset(new CompilerDriver(compiler_options_.get(), + verification_results_.get(), method_inliner_map_.get(), compiler_backend, insn_set, insn_features, false, NULL, 2, true, true, |