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 # include "mir_method_info.h" 18 19 #include "driver/compiler_driver.h" 20 #include "driver/dex_compilation_unit.h" 21 #include "driver/compiler_driver-inl.h" 22 #include "mirror/class_loader.h" // Only to allow casts in Handle<ClassLoader>. 23 #include "mirror/dex_cache.h" // Only to allow casts in Handle<DexCache>. 24 #include "scoped_thread_state_change.h" 25 #include "handle_scope-inl.h" 26 27 namespace art { 28 29 void MirMethodLoweringInfo::Resolve(CompilerDriver* compiler_driver, 30 const DexCompilationUnit* mUnit, 31 MirMethodLoweringInfo* method_infos, size_t count) { 32 if (kIsDebugBuild) { 33 DCHECK(method_infos != nullptr); 34 DCHECK_NE(count, 0u); 35 for (auto it = method_infos, end = method_infos + count; it != end; ++it) { 36 MirMethodLoweringInfo unresolved(it->MethodIndex(), it->GetInvokeType()); 37 if (it->target_dex_file_ != nullptr) { 38 unresolved.target_dex_file_ = it->target_dex_file_; 39 unresolved.target_method_idx_ = it->target_method_idx_; 40 } 41 DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0); 42 } 43 } 44 45 // We're going to resolve methods and check access in a tight loop. It's better to hold 46 // the lock and needed references once than re-acquiring them again and again. 47 ScopedObjectAccess soa(Thread::Current()); 48 StackHandleScope<3> hs(soa.Self()); 49 Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit))); 50 Handle<mirror::ClassLoader> class_loader( 51 hs.NewHandle(compiler_driver->GetClassLoader(soa, mUnit))); 52 Handle<mirror::Class> referrer_class(hs.NewHandle( 53 compiler_driver->ResolveCompilingMethodsClass(soa, dex_cache, class_loader, mUnit))); 54 // Even if the referrer class is unresolved (i.e. we're compiling a method without class 55 // definition) we still want to resolve methods and record all available info. 56 57 for (auto it = method_infos, end = method_infos + count; it != end; ++it) { 58 // Remember devirtualized invoke target and set the called method to the default. 59 MethodReference devirt_ref(it->target_dex_file_, it->target_method_idx_); 60 MethodReference* devirt_target = (it->target_dex_file_ != nullptr) ? &devirt_ref : nullptr; 61 it->target_dex_file_ = mUnit->GetDexFile(); 62 it->target_method_idx_ = it->MethodIndex(); 63 64 InvokeType invoke_type = it->GetInvokeType(); 65 mirror::ArtMethod* resolved_method = 66 compiler_driver->ResolveMethod(soa, dex_cache, class_loader, mUnit, it->MethodIndex(), 67 invoke_type); 68 if (UNLIKELY(resolved_method == nullptr)) { 69 continue; 70 } 71 compiler_driver->GetResolvedMethodDexFileLocation(resolved_method, 72 &it->declaring_dex_file_, &it->declaring_class_idx_, &it->declaring_method_idx_); 73 it->vtable_idx_ = compiler_driver->GetResolvedMethodVTableIndex(resolved_method, invoke_type); 74 75 MethodReference target_method(mUnit->GetDexFile(), it->MethodIndex()); 76 int fast_path_flags = compiler_driver->IsFastInvoke( 77 soa, dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method, &invoke_type, 78 &target_method, devirt_target, &it->direct_code_, &it->direct_method_); 79 bool needs_clinit = 80 compiler_driver->NeedsClassInitialization(referrer_class.Get(), resolved_method); 81 uint16_t other_flags = it->flags_ & 82 ~(kFlagFastPath | kFlagNeedsClassInitialization | (kInvokeTypeMask << kBitSharpTypeBegin)); 83 it->flags_ = other_flags | 84 (fast_path_flags != 0 ? kFlagFastPath : 0u) | 85 (static_cast<uint16_t>(invoke_type) << kBitSharpTypeBegin) | 86 (needs_clinit ? kFlagNeedsClassInitialization : 0u); 87 it->target_dex_file_ = target_method.dex_file; 88 it->target_method_idx_ = target_method.dex_method_index; 89 it->stats_flags_ = fast_path_flags; 90 } 91 } 92 93 } // namespace art 94