1c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko/* 2c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * Copyright (C) 2013 The Android Open Source Project 3c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * 4c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * Licensed under the Apache License, Version 2.0 (the "License"); 5c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * you may not use this file except in compliance with the License. 6c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * You may obtain a copy of the License at 7c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * 8c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * http://www.apache.org/licenses/LICENSE-2.0 9c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * 10c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * Unless required by applicable law or agreed to in writing, software 11c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * distributed under the License is distributed on an "AS IS" BASIS, 12c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * See the License for the specific language governing permissions and 14c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * limitations under the License. 15c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko */ 16c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 17c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "verification_results.h" 18c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 190b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h" 20c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "base/stl_util.h" 21c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "base/mutex-inl.h" 226449c62e40ef3a9bb75f664f922555affb532ee4Brian Carlstrom#include "driver/compiler_driver.h" 236449c62e40ef3a9bb75f664f922555affb532ee4Brian Carlstrom#include "driver/compiler_options.h" 24c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "thread.h" 25c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "thread-inl.h" 26c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "verified_method.h" 27c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "verifier/method_verifier-inl.h" 28c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 29c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markonamespace art { 30c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 316449c62e40ef3a9bb75f664f922555affb532ee4Brian CarlstromVerificationResults::VerificationResults(const CompilerOptions* compiler_options) 321ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers : compiler_options_(compiler_options), 331ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers verified_methods_lock_("compiler verified methods lock"), 34c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko verified_methods_(), 35c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko rejected_classes_lock_("compiler rejected classes lock"), 36c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko rejected_classes_() { 37c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko} 38c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 39c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir MarkoVerificationResults::~VerificationResults() { 40c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko Thread* self = Thread::Current(); 41c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko { 42c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko WriterMutexLock mu(self, verified_methods_lock_); 43c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko STLDeleteValues(&verified_methods_); 44c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko } 45c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko} 46c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 4753e32d14d7a51198c6ef09120c15bafdd1d055c2Andreas Gampevoid VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) { 482cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier DCHECK(method_verifier != nullptr); 49c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko MethodReference ref = method_verifier->GetMethodReference(); 50c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko bool compile = IsCandidateForCompilation(ref, method_verifier->GetAccessFlags()); 51c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko const VerifiedMethod* verified_method = VerifiedMethod::Create(method_verifier, compile); 52c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko if (verified_method == nullptr) { 5353e32d14d7a51198c6ef09120c15bafdd1d055c2Andreas Gampe // We'll punt this later. 5453e32d14d7a51198c6ef09120c15bafdd1d055c2Andreas Gampe return; 55c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko } 56c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 57c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko WriterMutexLock mu(Thread::Current(), verified_methods_lock_); 58c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko auto it = verified_methods_.find(ref); 59c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko if (it != verified_methods_.end()) { 60c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko // TODO: Investigate why are we doing the work again for this method and try to avoid it. 61c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko LOG(WARNING) << "Method processed more than once: " 62c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko << PrettyMethod(ref.dex_method_index, *ref.dex_file); 63e5de54cfab5f14ba0b8ff25d8d60901c7021943fCalin Juravle if (!Runtime::Current()->UseJitCompilation()) { 64e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier DCHECK_EQ(it->second->GetDevirtMap().size(), verified_method->GetDevirtMap().size()); 65e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier DCHECK_EQ(it->second->GetSafeCastSet().size(), verified_method->GetSafeCastSet().size()); 66e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier } 67c0d5f89d99c55ab63d6757fbd71dbfe95d347c1fMathieu Chartier // Delete the new verified method since there was already an existing one registered. It 68c0d5f89d99c55ab63d6757fbd71dbfe95d347c1fMathieu Chartier // is unsafe to replace the existing one since the JIT may be using it to generate a 69c0d5f89d99c55ab63d6757fbd71dbfe95d347c1fMathieu Chartier // native GC map. 70c0d5f89d99c55ab63d6757fbd71dbfe95d347c1fMathieu Chartier delete verified_method; 7153e32d14d7a51198c6ef09120c15bafdd1d055c2Andreas Gampe return; 72c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko } 73c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko verified_methods_.Put(ref, verified_method); 74c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko DCHECK(verified_methods_.find(ref) != verified_methods_.end()); 75c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko} 76c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 77c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markoconst VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) { 78c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko ReaderMutexLock mu(Thread::Current(), verified_methods_lock_); 79c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko auto it = verified_methods_.find(ref); 80c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko return (it != verified_methods_.end()) ? it->second : nullptr; 81c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko} 82c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 83c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markovoid VerificationResults::AddRejectedClass(ClassReference ref) { 84c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko { 85c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko WriterMutexLock mu(Thread::Current(), rejected_classes_lock_); 86c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko rejected_classes_.insert(ref); 87c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko } 88c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko DCHECK(IsClassRejected(ref)); 89c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko} 90c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 91c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markobool VerificationResults::IsClassRejected(ClassReference ref) { 92c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko ReaderMutexLock mu(Thread::Current(), rejected_classes_lock_); 93c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko return (rejected_classes_.find(ref) != rejected_classes_.end()); 94c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko} 95c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 96956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughesbool VerificationResults::IsCandidateForCompilation(MethodReference&, 97c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko const uint32_t access_flags) { 988c185bf0c6f18a5349bc87a7e3751ba06d90f461Vladimir Marko if (!compiler_options_->IsBytecodeCompilationEnabled()) { 991ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers return false; 1001ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers } 101c83329952b4a313e747c8835a73699e2cae5a6e2buzbee // Don't compile class initializers unless kEverything. 10229d38e77c553c6cf71fc4dafe2d22b4e3f814872Andreas Gampe if ((compiler_options_->GetCompilerFilter() != CompilerFilter::kEverything) && 103c83329952b4a313e747c8835a73699e2cae5a6e2buzbee ((access_flags & kAccConstructor) != 0) && ((access_flags & kAccStatic) != 0)) { 104c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko return false; 105c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko } 10639c3bfbd03d85c63cfbe69f17ce5800ccc7d6c13Dave Allison return true; 107c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko} 108c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko 109c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko} // namespace art 110