blob: 888f713d8fd90671bc6ec44f44f4ebe40a53c843 [file] [log] [blame]
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001/*
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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_CLASS_LINKER_INL_H_
18#define ART_RUNTIME_CLASS_LINKER_INL_H_
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019
Vladimir Marko09c5ca42018-05-31 15:15:31 +010020#include <atomic>
21
22#include "art_field-inl.h"
23#include "art_method-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080024#include "class_linker.h"
Mathieu Chartier52e4b432014-06-10 11:22:31 -070025#include "gc/heap-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070026#include "gc_root-inl.h"
27#include "handle_scope-inl.h"
Mathieu Chartier590fee92013-09-13 13:46:47 -070028#include "mirror/class_loader.h"
Mathieu Chartierbc56fc32014-06-03 15:37:03 -070029#include "mirror/dex_cache-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080030#include "mirror/iftable.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070031#include "mirror/object_array-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070032#include "obj_ptr-inl.h"
Mathieu Chartierc4f39252016-10-05 18:32:08 -070033#include "scoped_thread_state_change-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080034
35namespace art {
36
Vladimir Markoa8bba7d2018-05-30 15:18:48 +010037inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
38 ObjPtr<mirror::Class>* element_class) {
Ian Rogers98379392014-02-24 16:53:16 -080039 for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
Ian Rogersa55cf412014-02-27 00:31:26 -080040 // Read the cached array class once to avoid races with other threads setting it.
Mathieu Chartier28357fa2016-10-18 16:27:40 -070041 ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
Mathieu Chartierb74cd292014-05-29 14:31:33 -070042 if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
Mathieu Chartier28357fa2016-10-18 16:27:40 -070043 return array_class.Ptr();
Ian Rogers98379392014-02-24 16:53:16 -080044 }
45 }
Ian Rogers1ff3c982014-08-12 02:30:58 -070046 std::string descriptor = "[";
47 std::string temp;
48 descriptor += (*element_class)->GetDescriptor(&temp);
Mathieu Chartierb74cd292014-05-29 14:31:33 -070049 StackHandleScope<2> hs(Thread::Current());
50 Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
Mathieu Chartierbc5a7952016-10-17 15:46:31 -070051 HandleWrapperObjPtr<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
Mathieu Chartier28357fa2016-10-18 16:27:40 -070052 ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
Nicolas Geoffray9638b642015-06-23 18:16:46 +010053 if (array_class != nullptr) {
54 // Benign races in storing array class and incrementing index.
55 size_t victim_index = find_array_class_cache_next_victim_;
56 find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class);
57 find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize;
58 } else {
59 // We should have a NoClassDefFoundError.
60 self->AssertPendingException();
61 }
Mathieu Chartier28357fa2016-10-18 16:27:40 -070062 return array_class.Ptr();
Ian Rogers98379392014-02-24 16:53:16 -080063}
64
Vladimir Marko666ee3d2017-12-11 18:37:36 +000065inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
66 ObjPtr<mirror::Class> referrer) {
67 if (kObjPtrPoisoning) {
68 StackHandleScope<1> hs(Thread::Current());
69 HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
70 Thread::Current()->PoisonObjectPointers();
Vladimir Marko8d6768d2017-03-14 10:13:21 +000071 }
Vladimir Marko09c5ca42018-05-31 15:15:31 +010072 DCHECK(!Thread::Current()->IsExceptionPending());
Vladimir Marko666ee3d2017-12-11 18:37:36 +000073 // We do not need the read barrier for getting the DexCache for the initial resolved type
74 // lookup as both from-space and to-space copies point to the same native resolved types array.
75 ObjPtr<mirror::Class> resolved_type =
76 referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
77 if (resolved_type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +010078 resolved_type = DoResolveType(type_idx, referrer);
79 }
80 return resolved_type;
81}
82
83inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
84 ArtField* referrer) {
85 Thread::PoisonObjectPointersIfDebug();
86 DCHECK(!Thread::Current()->IsExceptionPending());
87 // We do not need the read barrier for getting the DexCache for the initial resolved type
88 // lookup as both from-space and to-space copies point to the same native resolved types array.
89 ObjPtr<mirror::Class> resolved_type =
90 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
91 if (UNLIKELY(resolved_type == nullptr)) {
92 resolved_type = DoResolveType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +000093 }
94 return resolved_type;
Vladimir Marko8d6768d2017-03-14 10:13:21 +000095}
96
Vladimir Marko28e012a2017-12-07 11:22:59 +000097inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
98 ArtMethod* referrer) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -070099 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100100 DCHECK(!Thread::Current()->IsExceptionPending());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000101 // We do not need the read barrier for getting the DexCache for the initial resolved type
102 // lookup as both from-space and to-space copies point to the same native resolved types array.
103 ObjPtr<mirror::Class> resolved_type =
104 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700105 if (UNLIKELY(resolved_type == nullptr)) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100106 resolved_type = DoResolveType(type_idx, referrer->GetDeclaringClass());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800107 }
Vladimir Marko28e012a2017-12-07 11:22:59 +0000108 return resolved_type;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800109}
110
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000111inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
112 Handle<mirror::DexCache> dex_cache,
113 Handle<mirror::ClassLoader> class_loader) {
114 DCHECK(dex_cache != nullptr);
115 Thread::PoisonObjectPointersIfDebug();
116 ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
117 if (resolved == nullptr) {
118 resolved = DoResolveType(type_idx, dex_cache, class_loader);
119 }
120 return resolved;
121}
122
123inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
124 ObjPtr<mirror::Class> referrer) {
125 // We do not need the read barrier for getting the DexCache for the initial resolved type
126 // lookup as both from-space and to-space copies point to the same native resolved types array.
127 ObjPtr<mirror::Class> type =
128 referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
129 if (type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100130 type = DoLookupResolvedType(type_idx, referrer);
131 }
132 return type;
133}
134
135inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
136 ArtField* referrer) {
137 // We do not need the read barrier for getting the DexCache for the initial resolved type
138 // lookup as both from-space and to-space copies point to the same native resolved types array.
139 ObjPtr<mirror::Class> type =
140 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
141 if (type == nullptr) {
142 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000143 }
144 return type;
145}
146
147inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
148 ArtMethod* referrer) {
149 // We do not need the read barrier for getting the DexCache for the initial resolved type
150 // lookup as both from-space and to-space copies point to the same native resolved types array.
151 ObjPtr<mirror::Class> type =
152 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
153 if (type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100154 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000155 }
156 return type;
157}
158
159inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
160 dex::TypeIndex type_idx,
161 ObjPtr<mirror::DexCache> dex_cache,
162 ObjPtr<mirror::ClassLoader> class_loader) {
163 ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
164 if (type == nullptr) {
165 type = DoLookupResolvedType(type_idx, dex_cache, class_loader);
166 }
167 return type;
168}
169
Vladimir Markoba118822017-06-12 15:41:56 +0100170template <bool kThrowOnError, typename ClassGetter>
171inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
172 InvokeType type,
173 ClassGetter class_getter) {
174 switch (type) {
175 case kStatic:
176 case kSuper:
177 break;
178 case kInterface: {
179 // We have to check whether the method id really belongs to an interface (dex static bytecode
180 // constraints A15, A16). Otherwise you must not invoke-interface on it.
181 ObjPtr<mirror::Class> klass = class_getter();
182 if (UNLIKELY(!klass->IsInterface())) {
183 if (kThrowOnError) {
184 ThrowIncompatibleClassChangeError(klass,
185 "Found class %s, but interface was expected",
186 klass->PrettyDescriptor().c_str());
187 }
188 return true;
189 }
190 break;
191 }
192 case kDirect:
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800193 if (dex_cache->GetDexFile()->SupportsDefaultMethods()) {
Vladimir Markoba118822017-06-12 15:41:56 +0100194 break;
195 }
196 FALLTHROUGH_INTENDED;
197 case kVirtual: {
198 // Similarly, invoke-virtual (and invoke-direct without default methods) must reference
199 // a non-interface class (dex static bytecode constraint A24, A25).
200 ObjPtr<mirror::Class> klass = class_getter();
201 if (UNLIKELY(klass->IsInterface())) {
202 if (kThrowOnError) {
203 ThrowIncompatibleClassChangeError(klass,
204 "Found interface %s, but class was expected",
205 klass->PrettyDescriptor().c_str());
206 }
207 return true;
208 }
209 break;
210 }
211 default:
212 LOG(FATAL) << "Unreachable - invocation type: " << type;
213 UNREACHABLE();
214 }
215 return false;
216}
217
218template <bool kThrow>
219inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
220 InvokeType type,
221 uint32_t method_idx,
222 ObjPtr<mirror::ClassLoader> class_loader) {
223 return CheckInvokeClassMismatch<kThrow>(
224 dex_cache,
225 type,
226 [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000227 const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
Vladimir Markoba118822017-06-12 15:41:56 +0100228 ObjPtr<mirror::Class> klass =
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000229 LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
Vladimir Markoba118822017-06-12 15:41:56 +0100230 DCHECK(klass != nullptr);
231 return klass;
232 });
233}
234
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100235inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
236 ObjPtr<mirror::DexCache> dex_cache,
237 ObjPtr<mirror::ClassLoader> class_loader) {
238 PointerSize pointer_size = image_pointer_size_;
239 ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, pointer_size);
240 if (resolved == nullptr) {
241 const DexFile& dex_file = *dex_cache->GetDexFile();
242 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
243 ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
244 if (klass != nullptr) {
Nicolas Geoffrayea179f42018-02-08 22:30:18 +0000245 resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100246 }
247 }
248 return resolved;
249}
250
Vladimir Markoba118822017-06-12 15:41:56 +0100251template <InvokeType type, ClassLinker::ResolveMode kResolveMode>
Mathieu Chartiere401d142015-04-22 13:56:20 -0700252inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
Vladimir Markoba118822017-06-12 15:41:56 +0100253 DCHECK(referrer != nullptr);
254 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
255 // lookup in the context of the original method from where it steals the code.
256 // However, we delay the GetInterfaceMethodIfProxy() until needed.
257 DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000258 // We do not need the read barrier for getting the DexCache for the initial resolved method
259 // lookup as both from-space and to-space copies point to the same native resolved methods array.
Vladimir Marko5122e6b2017-08-17 16:10:09 +0100260 ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
261 method_idx, image_pointer_size_);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100262 if (resolved_method == nullptr) {
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700263 return nullptr;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800264 }
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100265 DCHECK(!resolved_method->IsRuntimeMethod());
Vladimir Markoba118822017-06-12 15:41:56 +0100266 if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
267 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
268 // Check if the invoke type matches the class type.
269 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
270 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
271 if (CheckInvokeClassMismatch</* kThrow */ false>(dex_cache, type, method_idx, class_loader)) {
272 return nullptr;
273 }
274 // Check access.
275 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
276 if (!referring_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
277 resolved_method,
278 dex_cache,
279 method_idx)) {
280 return nullptr;
281 }
282 // Check if the invoke type matches the method type.
283 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
284 return nullptr;
285 }
Alex Lightfedd91d2016-01-07 14:49:16 -0800286 }
Vladimir Markoba118822017-06-12 15:41:56 +0100287 return resolved_method;
Alex Lightfedd91d2016-01-07 14:49:16 -0800288}
289
Andreas Gampe42ef8ab2015-12-03 17:27:32 -0800290template <ClassLinker::ResolveMode kResolveMode>
Mathieu Chartierc77f3ab2015-09-03 19:41:50 -0700291inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
292 uint32_t method_idx,
293 ArtMethod* referrer,
294 InvokeType type) {
Vladimir Markoba118822017-06-12 15:41:56 +0100295 DCHECK(referrer != nullptr);
296 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
297 // lookup in the context of the original method from where it steals the code.
298 // However, we delay the GetInterfaceMethodIfProxy() until needed.
299 DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700300 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000301 // We do not need the read barrier for getting the DexCache for the initial resolved method
302 // lookup as both from-space and to-space copies point to the same native resolved methods array.
Vladimir Marko5122e6b2017-08-17 16:10:09 +0100303 ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
304 method_idx, image_pointer_size_);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100305 DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
306 if (UNLIKELY(resolved_method == nullptr)) {
Vladimir Markoba118822017-06-12 15:41:56 +0100307 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700308 ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700309 StackHandleScope<2> hs(self);
Alex Light4ba388a2017-01-27 10:26:49 -0800310 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700311 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
Vladimir Marko89011192017-12-11 13:45:05 +0000312 resolved_method = ResolveMethod<kResolveMode>(method_idx,
Andreas Gampe42ef8ab2015-12-03 17:27:32 -0800313 h_dex_cache,
314 h_class_loader,
315 referrer,
316 type);
Vladimir Markoba118822017-06-12 15:41:56 +0100317 } else if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
318 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
319 // Check if the invoke type matches the class type.
320 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
321 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
322 if (CheckInvokeClassMismatch</* kThrow */ true>(dex_cache, type, method_idx, class_loader)) {
323 DCHECK(Thread::Current()->IsExceptionPending());
324 return nullptr;
325 }
326 // Check access.
327 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
328 if (!referring_class->CheckResolvedMethodAccess(resolved_method->GetDeclaringClass(),
329 resolved_method,
330 dex_cache,
331 method_idx,
332 type)) {
333 DCHECK(Thread::Current()->IsExceptionPending());
334 return nullptr;
335 }
336 // Check if the invoke type matches the method type.
337 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
338 ThrowIncompatibleClassChangeError(type,
339 resolved_method->GetInvokeType(),
340 resolved_method,
341 referrer);
342 return nullptr;
343 }
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700344 }
Andreas Gampe58a5af82014-07-31 16:23:49 -0700345 // Note: We cannot check here to see whether we added the method to the cache. It
346 // might be an erroneous class, which results in it being hidden from us.
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700347 return resolved_method;
348}
349
Vladimir Markof44d36c2017-03-14 14:18:46 +0000350inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx,
351 ArtMethod* referrer,
352 bool is_static) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000353 // We do not need the read barrier for getting the DexCache for the initial resolved field
354 // lookup as both from-space and to-space copies point to the same native resolved fields array.
355 ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
356 field_idx, image_pointer_size_);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000357 if (field == nullptr) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000358 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
359 field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000360 }
361 return field;
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700362}
363
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700364inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
365 ArtMethod* referrer,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700366 bool is_static) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700367 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000368 // We do not need the read barrier for getting the DexCache for the initial resolved field
369 // lookup as both from-space and to-space copies point to the same native resolved fields array.
370 ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
371 field_idx, image_pointer_size_);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700372 if (UNLIKELY(resolved_field == nullptr)) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700373 StackHandleScope<2> hs(Thread::Current());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000374 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
Alex Lightdba61482016-12-21 08:20:29 -0800375 Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000376 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
Vladimir Markoe11dd502017-12-08 14:09:45 +0000377 resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static);
Andreas Gampe58a5af82014-07-31 16:23:49 -0700378 // Note: We cannot check here to see whether we added the field to the cache. The type
379 // might be an erroneous class, which results in it being hidden from us.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800380 }
381 return resolved_field;
382}
383
Mathieu Chartier72041a02017-07-14 18:23:25 -0700384template <class Visitor>
385inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
386 Thread* const self = Thread::Current();
387 WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
388 for (const ClassLoaderData& data : class_loaders_) {
389 if (data.class_table != nullptr) {
390 visitor(data.class_table);
391 }
392 }
393}
394
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800395} // namespace art
396
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700397#endif // ART_RUNTIME_CLASS_LINKER_INL_H_