Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 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" |
Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 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>. |
Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 24 | #include "scoped_thread_state_change.h" |
Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 25 | #include "handle_scope-inl.h" |
Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 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()); |
Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 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))); |
Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 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( |
Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 77 | soa, dex_cache, class_loader, mUnit, referrer_class.Get(), resolved_method, &invoke_type, |
Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 78 | &target_method, devirt_target, &it->direct_code_, &it->direct_method_); |
Vladimir Marko | 66c6d7b | 2014-10-16 15:41:48 +0100 | [diff] [blame] | 79 | bool is_referrers_class = (referrer_class.Get() == resolved_method->GetDeclaringClass()); |
| 80 | bool is_class_initialized = |
| 81 | compiler_driver->IsMethodsClassInitialized(referrer_class.Get(), resolved_method); |
Vladimir Marko | 9820b7c | 2014-01-02 16:40:37 +0000 | [diff] [blame] | 82 | uint16_t other_flags = it->flags_ & |
Vladimir Marko | 66c6d7b | 2014-10-16 15:41:48 +0100 | [diff] [blame] | 83 | ~(kFlagFastPath | kFlagClassIsInitialized | (kInvokeTypeMask << kBitSharpTypeBegin)); |
Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 84 | it->flags_ = other_flags | |
| 85 | (fast_path_flags != 0 ? kFlagFastPath : 0u) | |
Vladimir Marko | 9820b7c | 2014-01-02 16:40:37 +0000 | [diff] [blame] | 86 | (static_cast<uint16_t>(invoke_type) << kBitSharpTypeBegin) | |
Vladimir Marko | 66c6d7b | 2014-10-16 15:41:48 +0100 | [diff] [blame] | 87 | (is_referrers_class ? kFlagIsReferrersClass : 0u) | |
| 88 | (is_class_initialized ? kFlagClassIsInitialized : 0u); |
Vladimir Marko | f096aad | 2014-01-23 15:51:58 +0000 | [diff] [blame] | 89 | it->target_dex_file_ = target_method.dex_file; |
| 90 | it->target_method_idx_ = target_method.dex_method_index; |
| 91 | it->stats_flags_ = fast_path_flags; |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | } // namespace art |