blob: 2536b2341694dcd46acb22c7325c96bee1a9cc9c [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,
Vladimir Markobcf17522018-06-01 13:14:32 +010038 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();
Vladimir Markobcf17522018-06-01 13:14:32 +010042 if (array_class != nullptr && array_class->GetComponentType() == element_class) {
43 return array_class;
Ian Rogers98379392014-02-24 16:53:16 -080044 }
45 }
Ian Rogers1ff3c982014-08-12 02:30:58 -070046 std::string descriptor = "[";
47 std::string temp;
Vladimir Markobcf17522018-06-01 13:14:32 +010048 descriptor += element_class->GetDescriptor(&temp);
49 StackHandleScope<1> hs(Thread::Current());
50 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
Mathieu Chartier28357fa2016-10-18 16:27:40 -070051 ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
Nicolas Geoffray9638b642015-06-23 18:16:46 +010052 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 }
Vladimir Markobcf17522018-06-01 13:14:32 +010061 return array_class;
Ian Rogers98379392014-02-24 16:53:16 -080062}
63
Vladimir Marko18090d12018-06-01 16:53:12 +010064inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
65 ArtField* referrer) {
66 Thread::PoisonObjectPointersIfDebug();
67 DCHECK(!Thread::Current()->IsExceptionPending());
68 // We do not need the read barrier for getting the DexCache for the initial resolved type
69 // lookup as both from-space and to-space copies point to the same native resolved types array.
70 ObjPtr<mirror::String> resolved =
71 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
72 if (resolved == nullptr) {
73 resolved = DoResolveString(string_idx, referrer->GetDexCache());
74 }
75 return resolved;
76}
77
78inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
79 ArtMethod* referrer) {
80 Thread::PoisonObjectPointersIfDebug();
81 DCHECK(!Thread::Current()->IsExceptionPending());
82 // We do not need the read barrier for getting the DexCache for the initial resolved type
83 // lookup as both from-space and to-space copies point to the same native resolved types array.
84 ObjPtr<mirror::String> resolved =
85 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
86 if (resolved == nullptr) {
87 resolved = DoResolveString(string_idx, referrer->GetDexCache());
88 }
89 return resolved;
90}
91
92inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
93 Handle<mirror::DexCache> dex_cache) {
94 Thread::PoisonObjectPointersIfDebug();
95 DCHECK(!Thread::Current()->IsExceptionPending());
96 ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
97 if (resolved == nullptr) {
98 resolved = DoResolveString(string_idx, dex_cache);
99 }
100 return resolved;
101}
102
103inline ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
104 ObjPtr<mirror::DexCache> dex_cache) {
105 ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
106 if (resolved == nullptr) {
107 resolved = DoLookupString(string_idx, dex_cache);
108 }
109 return resolved;
110}
111
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000112inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
113 ObjPtr<mirror::Class> referrer) {
114 if (kObjPtrPoisoning) {
115 StackHandleScope<1> hs(Thread::Current());
116 HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
117 Thread::Current()->PoisonObjectPointers();
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000118 }
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100119 DCHECK(!Thread::Current()->IsExceptionPending());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000120 // We do not need the read barrier for getting the DexCache for the initial resolved type
121 // lookup as both from-space and to-space copies point to the same native resolved types array.
122 ObjPtr<mirror::Class> resolved_type =
123 referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
124 if (resolved_type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100125 resolved_type = DoResolveType(type_idx, referrer);
126 }
127 return resolved_type;
128}
129
130inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
131 ArtField* referrer) {
132 Thread::PoisonObjectPointersIfDebug();
133 DCHECK(!Thread::Current()->IsExceptionPending());
134 // We do not need the read barrier for getting the DexCache for the initial resolved type
135 // lookup as both from-space and to-space copies point to the same native resolved types array.
136 ObjPtr<mirror::Class> resolved_type =
137 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
138 if (UNLIKELY(resolved_type == nullptr)) {
139 resolved_type = DoResolveType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000140 }
141 return resolved_type;
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000142}
143
Vladimir Marko28e012a2017-12-07 11:22:59 +0000144inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
145 ArtMethod* referrer) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700146 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100147 DCHECK(!Thread::Current()->IsExceptionPending());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000148 // We do not need the read barrier for getting the DexCache for the initial resolved type
149 // lookup as both from-space and to-space copies point to the same native resolved types array.
150 ObjPtr<mirror::Class> resolved_type =
151 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700152 if (UNLIKELY(resolved_type == nullptr)) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100153 resolved_type = DoResolveType(type_idx, referrer->GetDeclaringClass());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800154 }
Vladimir Marko28e012a2017-12-07 11:22:59 +0000155 return resolved_type;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800156}
157
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000158inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
159 Handle<mirror::DexCache> dex_cache,
160 Handle<mirror::ClassLoader> class_loader) {
161 DCHECK(dex_cache != nullptr);
162 Thread::PoisonObjectPointersIfDebug();
163 ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
164 if (resolved == nullptr) {
165 resolved = DoResolveType(type_idx, dex_cache, class_loader);
166 }
167 return resolved;
168}
169
170inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
171 ObjPtr<mirror::Class> referrer) {
172 // We do not need the read barrier for getting the DexCache for the initial resolved type
173 // lookup as both from-space and to-space copies point to the same native resolved types array.
174 ObjPtr<mirror::Class> type =
175 referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
176 if (type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100177 type = DoLookupResolvedType(type_idx, referrer);
178 }
179 return type;
180}
181
182inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
183 ArtField* referrer) {
184 // We do not need the read barrier for getting the DexCache for the initial resolved type
185 // lookup as both from-space and to-space copies point to the same native resolved types array.
186 ObjPtr<mirror::Class> type =
187 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
188 if (type == nullptr) {
189 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000190 }
191 return type;
192}
193
194inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
195 ArtMethod* referrer) {
196 // We do not need the read barrier for getting the DexCache for the initial resolved type
197 // lookup as both from-space and to-space copies point to the same native resolved types array.
198 ObjPtr<mirror::Class> type =
199 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
200 if (type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100201 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000202 }
203 return type;
204}
205
206inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
207 dex::TypeIndex type_idx,
208 ObjPtr<mirror::DexCache> dex_cache,
209 ObjPtr<mirror::ClassLoader> class_loader) {
210 ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
211 if (type == nullptr) {
212 type = DoLookupResolvedType(type_idx, dex_cache, class_loader);
213 }
214 return type;
215}
216
Vladimir Markoba118822017-06-12 15:41:56 +0100217template <bool kThrowOnError, typename ClassGetter>
218inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
219 InvokeType type,
220 ClassGetter class_getter) {
221 switch (type) {
222 case kStatic:
223 case kSuper:
224 break;
225 case kInterface: {
226 // We have to check whether the method id really belongs to an interface (dex static bytecode
227 // constraints A15, A16). Otherwise you must not invoke-interface on it.
228 ObjPtr<mirror::Class> klass = class_getter();
229 if (UNLIKELY(!klass->IsInterface())) {
230 if (kThrowOnError) {
231 ThrowIncompatibleClassChangeError(klass,
232 "Found class %s, but interface was expected",
233 klass->PrettyDescriptor().c_str());
234 }
235 return true;
236 }
237 break;
238 }
239 case kDirect:
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800240 if (dex_cache->GetDexFile()->SupportsDefaultMethods()) {
Vladimir Markoba118822017-06-12 15:41:56 +0100241 break;
242 }
243 FALLTHROUGH_INTENDED;
244 case kVirtual: {
245 // Similarly, invoke-virtual (and invoke-direct without default methods) must reference
246 // a non-interface class (dex static bytecode constraint A24, A25).
247 ObjPtr<mirror::Class> klass = class_getter();
248 if (UNLIKELY(klass->IsInterface())) {
249 if (kThrowOnError) {
250 ThrowIncompatibleClassChangeError(klass,
251 "Found interface %s, but class was expected",
252 klass->PrettyDescriptor().c_str());
253 }
254 return true;
255 }
256 break;
257 }
258 default:
259 LOG(FATAL) << "Unreachable - invocation type: " << type;
260 UNREACHABLE();
261 }
262 return false;
263}
264
265template <bool kThrow>
266inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
267 InvokeType type,
268 uint32_t method_idx,
269 ObjPtr<mirror::ClassLoader> class_loader) {
270 return CheckInvokeClassMismatch<kThrow>(
271 dex_cache,
272 type,
273 [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000274 const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
Vladimir Markoba118822017-06-12 15:41:56 +0100275 ObjPtr<mirror::Class> klass =
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000276 LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
Vladimir Markoba118822017-06-12 15:41:56 +0100277 DCHECK(klass != nullptr);
278 return klass;
279 });
280}
281
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100282inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
283 ObjPtr<mirror::DexCache> dex_cache,
284 ObjPtr<mirror::ClassLoader> class_loader) {
285 PointerSize pointer_size = image_pointer_size_;
286 ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, pointer_size);
287 if (resolved == nullptr) {
288 const DexFile& dex_file = *dex_cache->GetDexFile();
289 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
290 ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
291 if (klass != nullptr) {
Nicolas Geoffrayea179f42018-02-08 22:30:18 +0000292 resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100293 }
294 }
295 return resolved;
296}
297
Vladimir Markoba118822017-06-12 15:41:56 +0100298template <InvokeType type, ClassLinker::ResolveMode kResolveMode>
Mathieu Chartiere401d142015-04-22 13:56:20 -0700299inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
Vladimir Markoba118822017-06-12 15:41:56 +0100300 DCHECK(referrer != nullptr);
301 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
302 // lookup in the context of the original method from where it steals the code.
303 // However, we delay the GetInterfaceMethodIfProxy() until needed.
304 DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000305 // We do not need the read barrier for getting the DexCache for the initial resolved method
306 // lookup as both from-space and to-space copies point to the same native resolved methods array.
Vladimir Marko5122e6b2017-08-17 16:10:09 +0100307 ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
308 method_idx, image_pointer_size_);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100309 if (resolved_method == nullptr) {
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700310 return nullptr;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800311 }
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100312 DCHECK(!resolved_method->IsRuntimeMethod());
Vladimir Markoba118822017-06-12 15:41:56 +0100313 if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
314 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
315 // Check if the invoke type matches the class type.
316 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
317 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
318 if (CheckInvokeClassMismatch</* kThrow */ false>(dex_cache, type, method_idx, class_loader)) {
319 return nullptr;
320 }
321 // Check access.
322 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
323 if (!referring_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
324 resolved_method,
325 dex_cache,
326 method_idx)) {
327 return nullptr;
328 }
329 // Check if the invoke type matches the method type.
330 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
331 return nullptr;
332 }
Alex Lightfedd91d2016-01-07 14:49:16 -0800333 }
Vladimir Markoba118822017-06-12 15:41:56 +0100334 return resolved_method;
Alex Lightfedd91d2016-01-07 14:49:16 -0800335}
336
Andreas Gampe42ef8ab2015-12-03 17:27:32 -0800337template <ClassLinker::ResolveMode kResolveMode>
Mathieu Chartierc77f3ab2015-09-03 19:41:50 -0700338inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
339 uint32_t method_idx,
340 ArtMethod* referrer,
341 InvokeType type) {
Vladimir Markoba118822017-06-12 15:41:56 +0100342 DCHECK(referrer != nullptr);
343 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
344 // lookup in the context of the original method from where it steals the code.
345 // However, we delay the GetInterfaceMethodIfProxy() until needed.
346 DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700347 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000348 // We do not need the read barrier for getting the DexCache for the initial resolved method
349 // lookup as both from-space and to-space copies point to the same native resolved methods array.
Vladimir Marko5122e6b2017-08-17 16:10:09 +0100350 ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
351 method_idx, image_pointer_size_);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100352 DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
353 if (UNLIKELY(resolved_method == nullptr)) {
Vladimir Markoba118822017-06-12 15:41:56 +0100354 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700355 ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700356 StackHandleScope<2> hs(self);
Alex Light4ba388a2017-01-27 10:26:49 -0800357 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700358 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
Vladimir Marko89011192017-12-11 13:45:05 +0000359 resolved_method = ResolveMethod<kResolveMode>(method_idx,
Andreas Gampe42ef8ab2015-12-03 17:27:32 -0800360 h_dex_cache,
361 h_class_loader,
362 referrer,
363 type);
Vladimir Markoba118822017-06-12 15:41:56 +0100364 } else if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
365 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
366 // Check if the invoke type matches the class type.
367 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
368 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
369 if (CheckInvokeClassMismatch</* kThrow */ true>(dex_cache, type, method_idx, class_loader)) {
370 DCHECK(Thread::Current()->IsExceptionPending());
371 return nullptr;
372 }
373 // Check access.
374 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
375 if (!referring_class->CheckResolvedMethodAccess(resolved_method->GetDeclaringClass(),
376 resolved_method,
377 dex_cache,
378 method_idx,
379 type)) {
380 DCHECK(Thread::Current()->IsExceptionPending());
381 return nullptr;
382 }
383 // Check if the invoke type matches the method type.
384 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
385 ThrowIncompatibleClassChangeError(type,
386 resolved_method->GetInvokeType(),
387 resolved_method,
388 referrer);
389 return nullptr;
390 }
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700391 }
Andreas Gampe58a5af82014-07-31 16:23:49 -0700392 // Note: We cannot check here to see whether we added the method to the cache. It
393 // might be an erroneous class, which results in it being hidden from us.
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700394 return resolved_method;
395}
396
Vladimir Markof44d36c2017-03-14 14:18:46 +0000397inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx,
398 ArtMethod* referrer,
399 bool is_static) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000400 // We do not need the read barrier for getting the DexCache for the initial resolved field
401 // lookup as both from-space and to-space copies point to the same native resolved fields array.
402 ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
403 field_idx, image_pointer_size_);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000404 if (field == nullptr) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000405 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
406 field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000407 }
408 return field;
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700409}
410
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700411inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
412 ArtMethod* referrer,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700413 bool is_static) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700414 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000415 // We do not need the read barrier for getting the DexCache for the initial resolved field
416 // lookup as both from-space and to-space copies point to the same native resolved fields array.
417 ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
418 field_idx, image_pointer_size_);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700419 if (UNLIKELY(resolved_field == nullptr)) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700420 StackHandleScope<2> hs(Thread::Current());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000421 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
Alex Lightdba61482016-12-21 08:20:29 -0800422 Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000423 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
Vladimir Markoe11dd502017-12-08 14:09:45 +0000424 resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static);
Andreas Gampe58a5af82014-07-31 16:23:49 -0700425 // Note: We cannot check here to see whether we added the field to the cache. The type
426 // might be an erroneous class, which results in it being hidden from us.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800427 }
428 return resolved_field;
429}
430
Mathieu Chartier72041a02017-07-14 18:23:25 -0700431template <class Visitor>
432inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
433 Thread* const self = Thread::Current();
434 WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
435 for (const ClassLoaderData& data : class_loaders_) {
436 if (data.class_table != nullptr) {
437 visitor(data.class_table);
438 }
439 }
440}
441
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800442} // namespace art
443
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700444#endif // ART_RUNTIME_CLASS_LINKER_INL_H_