1 /* 2 * Copyright (C) 2011 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 #ifndef ART_RUNTIME_CLASS_LINKER_INL_H_ 18 #define ART_RUNTIME_CLASS_LINKER_INL_H_ 19 20 #include "art_field.h" 21 #include "class_linker.h" 22 #include "gc_root-inl.h" 23 #include "gc/heap-inl.h" 24 #include "obj_ptr-inl.h" 25 #include "mirror/class_loader.h" 26 #include "mirror/dex_cache-inl.h" 27 #include "mirror/iftable.h" 28 #include "mirror/object_array-inl.h" 29 #include "handle_scope-inl.h" 30 #include "scoped_thread_state_change-inl.h" 31 32 #include <atomic> 33 34 namespace art { 35 36 inline mirror::Class* ClassLinker::FindArrayClass(Thread* self, 37 ObjPtr<mirror::Class>* element_class) { 38 for (size_t i = 0; i < kFindArrayCacheSize; ++i) { 39 // Read the cached array class once to avoid races with other threads setting it. 40 ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read(); 41 if (array_class != nullptr && array_class->GetComponentType() == *element_class) { 42 return array_class.Ptr(); 43 } 44 } 45 std::string descriptor = "["; 46 std::string temp; 47 descriptor += (*element_class)->GetDescriptor(&temp); 48 StackHandleScope<2> hs(Thread::Current()); 49 Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader())); 50 HandleWrapperObjPtr<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class)); 51 ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader); 52 if (array_class != nullptr) { 53 // Benign races in storing array class and incrementing index. 54 size_t victim_index = find_array_class_cache_next_victim_; 55 find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class); 56 find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize; 57 } else { 58 // We should have a NoClassDefFoundError. 59 self->AssertPendingException(); 60 } 61 return array_class.Ptr(); 62 } 63 64 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType( 65 dex::TypeIndex type_idx, 66 ObjPtr<mirror::DexCache> dex_cache, 67 ObjPtr<mirror::ClassLoader> class_loader) { 68 ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx); 69 if (type == nullptr) { 70 type = Runtime::Current()->GetClassLinker()->LookupResolvedType( 71 *dex_cache->GetDexFile(), type_idx, dex_cache, class_loader); 72 } 73 return type; 74 } 75 76 inline mirror::Class* ClassLinker::ResolveType(dex::TypeIndex type_idx, ArtMethod* referrer) { 77 Thread::PoisonObjectPointersIfDebug(); 78 if (kIsDebugBuild) { 79 Thread::Current()->AssertNoPendingException(); 80 } 81 ObjPtr<mirror::Class> resolved_type = referrer->GetDexCache()->GetResolvedType(type_idx); 82 if (UNLIKELY(resolved_type == nullptr)) { 83 StackHandleScope<2> hs(Thread::Current()); 84 ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass(); 85 Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); 86 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader())); 87 const DexFile& dex_file = *dex_cache->GetDexFile(); 88 resolved_type = ResolveType(dex_file, type_idx, dex_cache, class_loader); 89 } 90 return resolved_type.Ptr(); 91 } 92 93 inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) { 94 ArtMethod* resolved_method = referrer->GetDexCacheResolvedMethod(method_idx, image_pointer_size_); 95 if (resolved_method == nullptr || resolved_method->IsRuntimeMethod()) { 96 return nullptr; 97 } 98 return resolved_method; 99 } 100 101 inline mirror::Class* ClassLinker::ResolveReferencedClassOfMethod( 102 uint32_t method_idx, 103 Handle<mirror::DexCache> dex_cache, 104 Handle<mirror::ClassLoader> class_loader) { 105 // NB: We cannot simply use `GetResolvedMethod(method_idx, ...)->GetDeclaringClass()`. This is 106 // because if we did so than an invoke-super could be incorrectly dispatched in cases where 107 // GetMethodId(method_idx).class_idx_ refers to a non-interface, non-direct-superclass 108 // (super*-class?) of the referrer and the direct superclass of the referrer contains a concrete 109 // implementation of the method. If this class's implementation of the method is copied from an 110 // interface (either miranda, default or conflict) we would incorrectly assume that is what we 111 // want to invoke on, instead of the 'concrete' implementation that the direct superclass 112 // contains. 113 const DexFile* dex_file = dex_cache->GetDexFile(); 114 const DexFile::MethodId& method = dex_file->GetMethodId(method_idx); 115 ObjPtr<mirror::Class> resolved_type = dex_cache->GetResolvedType(method.class_idx_); 116 if (UNLIKELY(resolved_type == nullptr)) { 117 resolved_type = ResolveType(*dex_file, method.class_idx_, dex_cache, class_loader); 118 } 119 return resolved_type.Ptr(); 120 } 121 122 template <ClassLinker::ResolveMode kResolveMode> 123 inline ArtMethod* ClassLinker::ResolveMethod(Thread* self, 124 uint32_t method_idx, 125 ArtMethod* referrer, 126 InvokeType type) { 127 ArtMethod* resolved_method = GetResolvedMethod(method_idx, referrer); 128 Thread::PoisonObjectPointersIfDebug(); 129 if (UNLIKELY(resolved_method == nullptr)) { 130 ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass(); 131 StackHandleScope<2> hs(self); 132 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache())); 133 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader())); 134 const DexFile* dex_file = h_dex_cache->GetDexFile(); 135 resolved_method = ResolveMethod<kResolveMode>(*dex_file, 136 method_idx, 137 h_dex_cache, 138 h_class_loader, 139 referrer, 140 type); 141 } 142 // Note: We cannot check here to see whether we added the method to the cache. It 143 // might be an erroneous class, which results in it being hidden from us. 144 return resolved_method; 145 } 146 147 inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx, 148 ArtMethod* referrer, 149 bool is_static) { 150 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache(); 151 ArtField* field = dex_cache->GetResolvedField(field_idx, image_pointer_size_); 152 if (field == nullptr) { 153 field = LookupResolvedField(field_idx, dex_cache, referrer->GetClassLoader(), is_static); 154 } 155 return field; 156 } 157 158 inline ArtField* ClassLinker::ResolveField(uint32_t field_idx, 159 ArtMethod* referrer, 160 bool is_static) { 161 Thread::PoisonObjectPointersIfDebug(); 162 ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass(); 163 ArtField* resolved_field = 164 referrer->GetDexCache()->GetResolvedField(field_idx, image_pointer_size_); 165 if (UNLIKELY(resolved_field == nullptr)) { 166 StackHandleScope<2> hs(Thread::Current()); 167 Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache())); 168 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader())); 169 const DexFile& dex_file = *dex_cache->GetDexFile(); 170 resolved_field = ResolveField(dex_file, field_idx, dex_cache, class_loader, is_static); 171 // Note: We cannot check here to see whether we added the field to the cache. The type 172 // might be an erroneous class, which results in it being hidden from us. 173 } 174 return resolved_field; 175 } 176 177 inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) { 178 DCHECK(!class_roots_.IsNull()); 179 mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read(); 180 ObjPtr<mirror::Class> klass = class_roots->Get(class_root); 181 DCHECK(klass != nullptr); 182 return klass.Ptr(); 183 } 184 185 template<ReadBarrierOption kReadBarrierOption> 186 ArtMethod* ClassLinker::FindMethodForProxy(ObjPtr<mirror::Class> proxy_class, 187 ArtMethod* proxy_method) { 188 DCHECK(proxy_class->IsProxyClass()); 189 DCHECK(proxy_method->IsProxyMethod()); 190 { 191 Thread* const self = Thread::Current(); 192 ReaderMutexLock mu(self, *Locks::dex_lock_); 193 // Locate the dex cache of the original interface/Object 194 for (const DexCacheData& data : dex_caches_) { 195 if (!self->IsJWeakCleared(data.weak_root) && 196 proxy_method->HasSameDexCacheResolvedMethods(data.resolved_methods, 197 image_pointer_size_)) { 198 ObjPtr<mirror::DexCache> dex_cache = 199 ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root)); 200 if (dex_cache != nullptr) { 201 ArtMethod* resolved_method = dex_cache->GetResolvedMethod( 202 proxy_method->GetDexMethodIndex(), image_pointer_size_); 203 CHECK(resolved_method != nullptr); 204 return resolved_method; 205 } 206 } 207 } 208 } 209 LOG(FATAL) << "Didn't find dex cache for " << proxy_class->PrettyClass() << " " 210 << proxy_method->PrettyMethod(); 211 UNREACHABLE(); 212 } 213 214 } // namespace art 215 216 #endif // ART_RUNTIME_CLASS_LINKER_INL_H_ 217