diff options
Diffstat (limited to 'compiler/dex/verification_results.cc')
-rw-r--r-- | compiler/dex/verification_results.cc | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc new file mode 100644 index 0000000..8b4fa1a --- /dev/null +++ b/compiler/dex/verification_results.cc @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2013 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. + */ + +#include "verification_results.h" + +#include "base/stl_util.h" +#include "base/mutex.h" +#include "base/mutex-inl.h" +#include "thread.h" +#include "thread-inl.h" +#include "verified_method.h" +#include "verifier/method_verifier.h" +#include "verifier/method_verifier-inl.h" + +namespace art { + +VerificationResults::VerificationResults() + : verified_methods_lock_("compiler verified methods lock"), + verified_methods_(), + rejected_classes_lock_("compiler rejected classes lock"), + rejected_classes_() { +} + +VerificationResults::~VerificationResults() { + Thread* self = Thread::Current(); + { + WriterMutexLock mu(self, verified_methods_lock_); + STLDeleteValues(&verified_methods_); + } +} + +bool VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) { + 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. + if (!compile && !method_verifier->HasCheckCasts()) { + return true; + } + + const VerifiedMethod* verified_method = VerifiedMethod::Create(method_verifier, compile); + if (verified_method == nullptr) { + DCHECK(method_verifier->HasFailures()); + return false; + } + + WriterMutexLock mu(Thread::Current(), verified_methods_lock_); + auto it = verified_methods_.find(ref); + if (it != verified_methods_.end()) { + // TODO: Investigate why are we doing the work again for this method and try to avoid it. + LOG(WARNING) << "Method processed more than once: " + << PrettyMethod(ref.dex_method_index, *ref.dex_file); + DCHECK_EQ(it->second->GetDevirtMap().size(), verified_method->GetDevirtMap().size()); + DCHECK_EQ(it->second->GetSafeCastSet().size(), verified_method->GetSafeCastSet().size()); + DCHECK_EQ(it->second->GetDexGcMap().size(), verified_method->GetDexGcMap().size()); + delete it->second; + verified_methods_.erase(it); + } + verified_methods_.Put(ref, verified_method); + DCHECK(verified_methods_.find(ref) != verified_methods_.end()); + return true; +} + +const VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) { + ReaderMutexLock mu(Thread::Current(), verified_methods_lock_); + auto it = verified_methods_.find(ref); + return (it != verified_methods_.end()) ? it->second : nullptr; +} + +const std::vector<uint8_t>* VerificationResults::GetDexGcMap(MethodReference ref) { + const VerifiedMethod* verified_method = GetVerifiedMethod(ref); + CHECK(verified_method != nullptr) + << "Didn't find GC map for: " << PrettyMethod(ref.dex_method_index, *ref.dex_file); + return &verified_method->GetDexGcMap(); +} + +const MethodReference* VerificationResults::GetDevirtMap(const MethodReference& ref, + uint32_t dex_pc) { + const VerifiedMethod* verified_method = GetVerifiedMethod(ref); + return (verified_method != nullptr) ? verified_method->GetDevirtTarget(dex_pc) : nullptr; +} + +bool VerificationResults::IsSafeCast(MethodReference ref, uint32_t pc) { + const VerifiedMethod* verified_method = GetVerifiedMethod(ref); + return (verified_method != nullptr) && (verified_method->IsSafeCast(pc)); +} + +void VerificationResults::AddRejectedClass(ClassReference ref) { + { + WriterMutexLock mu(Thread::Current(), rejected_classes_lock_); + rejected_classes_.insert(ref); + } + DCHECK(IsClassRejected(ref)); +} + +bool VerificationResults::IsClassRejected(ClassReference ref) { + ReaderMutexLock mu(Thread::Current(), rejected_classes_lock_); + return (rejected_classes_.find(ref) != rejected_classes_.end()); +} + +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; +#endif + // Don't compile class initializers, ever. + if (((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) { + return false; + } + return (Runtime::Current()->GetCompilerFilter() != Runtime::kInterpretOnly); +} + +} // namespace art |