blob: 67032055026d266e9b113b3ca642bb43e91700a0 [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"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070025#include "gc_root-inl.h"
26#include "handle_scope-inl.h"
Mathieu Chartier590fee92013-09-13 13:46:47 -070027#include "mirror/class_loader.h"
Mathieu Chartierbc56fc32014-06-03 15:37:03 -070028#include "mirror/dex_cache-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029#include "mirror/iftable.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070030#include "mirror/object_array-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070031#include "obj_ptr-inl.h"
Mathieu Chartierc4f39252016-10-05 18:32:08 -070032#include "scoped_thread_state_change-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080033
34namespace art {
35
Vladimir Markoa8bba7d2018-05-30 15:18:48 +010036inline ObjPtr<mirror::Class> ClassLinker::FindArrayClass(Thread* self,
Vladimir Markobcf17522018-06-01 13:14:32 +010037 ObjPtr<mirror::Class> element_class) {
Ian Rogers98379392014-02-24 16:53:16 -080038 for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
Ian Rogersa55cf412014-02-27 00:31:26 -080039 // Read the cached array class once to avoid races with other threads setting it.
Mathieu Chartier28357fa2016-10-18 16:27:40 -070040 ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
Vladimir Markobcf17522018-06-01 13:14:32 +010041 if (array_class != nullptr && array_class->GetComponentType() == element_class) {
42 return array_class;
Ian Rogers98379392014-02-24 16:53:16 -080043 }
44 }
Ian Rogers1ff3c982014-08-12 02:30:58 -070045 std::string descriptor = "[";
46 std::string temp;
Vladimir Markobcf17522018-06-01 13:14:32 +010047 descriptor += element_class->GetDescriptor(&temp);
48 StackHandleScope<1> hs(Thread::Current());
49 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(element_class->GetClassLoader()));
Mathieu Chartier28357fa2016-10-18 16:27:40 -070050 ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
Nicolas Geoffray9638b642015-06-23 18:16:46 +010051 if (array_class != nullptr) {
52 // Benign races in storing array class and incrementing index.
53 size_t victim_index = find_array_class_cache_next_victim_;
54 find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class);
55 find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize;
56 } else {
57 // We should have a NoClassDefFoundError.
58 self->AssertPendingException();
59 }
Vladimir Markobcf17522018-06-01 13:14:32 +010060 return array_class;
Ian Rogers98379392014-02-24 16:53:16 -080061}
62
Vladimir Marko18090d12018-06-01 16:53:12 +010063inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
64 ArtField* referrer) {
65 Thread::PoisonObjectPointersIfDebug();
66 DCHECK(!Thread::Current()->IsExceptionPending());
67 // We do not need the read barrier for getting the DexCache for the initial resolved type
68 // lookup as both from-space and to-space copies point to the same native resolved types array.
69 ObjPtr<mirror::String> resolved =
70 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
71 if (resolved == nullptr) {
72 resolved = DoResolveString(string_idx, referrer->GetDexCache());
73 }
74 return resolved;
75}
76
77inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
78 ArtMethod* referrer) {
79 Thread::PoisonObjectPointersIfDebug();
80 DCHECK(!Thread::Current()->IsExceptionPending());
81 // We do not need the read barrier for getting the DexCache for the initial resolved type
82 // lookup as both from-space and to-space copies point to the same native resolved types array.
83 ObjPtr<mirror::String> resolved =
84 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedString(string_idx);
85 if (resolved == nullptr) {
86 resolved = DoResolveString(string_idx, referrer->GetDexCache());
87 }
88 return resolved;
89}
90
91inline ObjPtr<mirror::String> ClassLinker::ResolveString(dex::StringIndex string_idx,
92 Handle<mirror::DexCache> dex_cache) {
93 Thread::PoisonObjectPointersIfDebug();
94 DCHECK(!Thread::Current()->IsExceptionPending());
95 ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
96 if (resolved == nullptr) {
97 resolved = DoResolveString(string_idx, dex_cache);
98 }
99 return resolved;
100}
101
102inline ObjPtr<mirror::String> ClassLinker::LookupString(dex::StringIndex string_idx,
103 ObjPtr<mirror::DexCache> dex_cache) {
104 ObjPtr<mirror::String> resolved = dex_cache->GetResolvedString(string_idx);
105 if (resolved == nullptr) {
106 resolved = DoLookupString(string_idx, dex_cache);
107 }
108 return resolved;
109}
110
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000111inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
112 ObjPtr<mirror::Class> referrer) {
113 if (kObjPtrPoisoning) {
114 StackHandleScope<1> hs(Thread::Current());
115 HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
116 Thread::Current()->PoisonObjectPointers();
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000117 }
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100118 DCHECK(!Thread::Current()->IsExceptionPending());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000119 // We do not need the read barrier for getting the DexCache for the initial resolved type
120 // lookup as both from-space and to-space copies point to the same native resolved types array.
121 ObjPtr<mirror::Class> resolved_type =
122 referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
123 if (resolved_type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100124 resolved_type = DoResolveType(type_idx, referrer);
125 }
126 return resolved_type;
127}
128
129inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
130 ArtField* referrer) {
131 Thread::PoisonObjectPointersIfDebug();
132 DCHECK(!Thread::Current()->IsExceptionPending());
133 // We do not need the read barrier for getting the DexCache for the initial resolved type
134 // lookup as both from-space and to-space copies point to the same native resolved types array.
135 ObjPtr<mirror::Class> resolved_type =
136 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
137 if (UNLIKELY(resolved_type == nullptr)) {
Andreas Gampe4835d212018-11-21 14:55:10 -0800138 resolved_type = DoResolveType(type_idx, referrer);
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000139 }
140 return resolved_type;
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000141}
142
Vladimir Marko28e012a2017-12-07 11:22:59 +0000143inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
144 ArtMethod* referrer) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700145 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100146 DCHECK(!Thread::Current()->IsExceptionPending());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000147 // We do not need the read barrier for getting the DexCache for the initial resolved type
148 // lookup as both from-space and to-space copies point to the same native resolved types array.
149 ObjPtr<mirror::Class> resolved_type =
150 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700151 if (UNLIKELY(resolved_type == nullptr)) {
Andreas Gampe4835d212018-11-21 14:55:10 -0800152 resolved_type = DoResolveType(type_idx, referrer);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800153 }
Vladimir Marko28e012a2017-12-07 11:22:59 +0000154 return resolved_type;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800155}
156
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000157inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
158 Handle<mirror::DexCache> dex_cache,
159 Handle<mirror::ClassLoader> class_loader) {
160 DCHECK(dex_cache != nullptr);
161 Thread::PoisonObjectPointersIfDebug();
162 ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
163 if (resolved == nullptr) {
164 resolved = DoResolveType(type_idx, dex_cache, class_loader);
165 }
166 return resolved;
167}
168
169inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
170 ObjPtr<mirror::Class> referrer) {
171 // We do not need the read barrier for getting the DexCache for the initial resolved type
172 // lookup as both from-space and to-space copies point to the same native resolved types array.
173 ObjPtr<mirror::Class> type =
174 referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
175 if (type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100176 type = DoLookupResolvedType(type_idx, referrer);
177 }
178 return type;
179}
180
181inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
182 ArtField* referrer) {
183 // We do not need the read barrier for getting the DexCache for the initial resolved type
184 // lookup as both from-space and to-space copies point to the same native resolved types array.
185 ObjPtr<mirror::Class> type =
186 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
187 if (type == nullptr) {
188 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000189 }
190 return type;
191}
192
193inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
194 ArtMethod* referrer) {
195 // We do not need the read barrier for getting the DexCache for the initial resolved type
196 // lookup as both from-space and to-space copies point to the same native resolved types array.
197 ObjPtr<mirror::Class> type =
198 referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
199 if (type == nullptr) {
Vladimir Marko09c5ca42018-05-31 15:15:31 +0100200 type = DoLookupResolvedType(type_idx, referrer->GetDeclaringClass());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000201 }
202 return type;
203}
204
205inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
206 dex::TypeIndex type_idx,
207 ObjPtr<mirror::DexCache> dex_cache,
208 ObjPtr<mirror::ClassLoader> class_loader) {
209 ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
210 if (type == nullptr) {
211 type = DoLookupResolvedType(type_idx, dex_cache, class_loader);
212 }
213 return type;
214}
215
Vladimir Markoba118822017-06-12 15:41:56 +0100216template <bool kThrowOnError, typename ClassGetter>
217inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
218 InvokeType type,
219 ClassGetter class_getter) {
220 switch (type) {
221 case kStatic:
222 case kSuper:
223 break;
224 case kInterface: {
225 // We have to check whether the method id really belongs to an interface (dex static bytecode
226 // constraints A15, A16). Otherwise you must not invoke-interface on it.
227 ObjPtr<mirror::Class> klass = class_getter();
228 if (UNLIKELY(!klass->IsInterface())) {
229 if (kThrowOnError) {
230 ThrowIncompatibleClassChangeError(klass,
231 "Found class %s, but interface was expected",
232 klass->PrettyDescriptor().c_str());
233 }
234 return true;
235 }
236 break;
237 }
238 case kDirect:
Mathieu Chartierf6e31472017-12-28 13:32:08 -0800239 if (dex_cache->GetDexFile()->SupportsDefaultMethods()) {
Vladimir Markoba118822017-06-12 15:41:56 +0100240 break;
241 }
242 FALLTHROUGH_INTENDED;
243 case kVirtual: {
244 // Similarly, invoke-virtual (and invoke-direct without default methods) must reference
245 // a non-interface class (dex static bytecode constraint A24, A25).
246 ObjPtr<mirror::Class> klass = class_getter();
247 if (UNLIKELY(klass->IsInterface())) {
248 if (kThrowOnError) {
249 ThrowIncompatibleClassChangeError(klass,
250 "Found interface %s, but class was expected",
251 klass->PrettyDescriptor().c_str());
252 }
253 return true;
254 }
255 break;
256 }
257 default:
258 LOG(FATAL) << "Unreachable - invocation type: " << type;
259 UNREACHABLE();
260 }
261 return false;
262}
263
264template <bool kThrow>
265inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
266 InvokeType type,
267 uint32_t method_idx,
268 ObjPtr<mirror::ClassLoader> class_loader) {
269 return CheckInvokeClassMismatch<kThrow>(
270 dex_cache,
271 type,
272 [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000273 const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
Vladimir Markoba118822017-06-12 15:41:56 +0100274 ObjPtr<mirror::Class> klass =
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000275 LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
Vladimir Markoba118822017-06-12 15:41:56 +0100276 DCHECK(klass != nullptr);
277 return klass;
278 });
279}
280
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100281inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
282 ObjPtr<mirror::DexCache> dex_cache,
283 ObjPtr<mirror::ClassLoader> class_loader) {
284 PointerSize pointer_size = image_pointer_size_;
285 ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, pointer_size);
286 if (resolved == nullptr) {
287 const DexFile& dex_file = *dex_cache->GetDexFile();
288 const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
289 ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
290 if (klass != nullptr) {
Nicolas Geoffrayea179f42018-02-08 22:30:18 +0000291 resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100292 }
293 }
294 return resolved;
295}
296
Vladimir Markoba118822017-06-12 15:41:56 +0100297template <InvokeType type, ClassLinker::ResolveMode kResolveMode>
Mathieu Chartiere401d142015-04-22 13:56:20 -0700298inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
Vladimir Markoba118822017-06-12 15:41:56 +0100299 DCHECK(referrer != nullptr);
300 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
301 // lookup in the context of the original method from where it steals the code.
302 // However, we delay the GetInterfaceMethodIfProxy() until needed.
303 DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000304 // We do not need the read barrier for getting the DexCache for the initial resolved method
305 // lookup as both from-space and to-space copies point to the same native resolved methods array.
Vladimir Marko5122e6b2017-08-17 16:10:09 +0100306 ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
307 method_idx, image_pointer_size_);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100308 if (resolved_method == nullptr) {
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700309 return nullptr;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800310 }
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100311 DCHECK(!resolved_method->IsRuntimeMethod());
Vladimir Markoba118822017-06-12 15:41:56 +0100312 if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
313 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
314 // Check if the invoke type matches the class type.
315 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
316 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700317 if (CheckInvokeClassMismatch</* kThrow= */ false>(dex_cache, type, method_idx, class_loader)) {
Vladimir Markoba118822017-06-12 15:41:56 +0100318 return nullptr;
319 }
320 // Check access.
321 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
322 if (!referring_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
323 resolved_method,
324 dex_cache,
325 method_idx)) {
326 return nullptr;
327 }
328 // Check if the invoke type matches the method type.
329 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
330 return nullptr;
331 }
Alex Lightfedd91d2016-01-07 14:49:16 -0800332 }
Vladimir Markoba118822017-06-12 15:41:56 +0100333 return resolved_method;
Alex Lightfedd91d2016-01-07 14:49:16 -0800334}
335
Andreas Gampe42ef8ab2015-12-03 17:27:32 -0800336template <ClassLinker::ResolveMode kResolveMode>
Mathieu Chartierc77f3ab2015-09-03 19:41:50 -0700337inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
338 uint32_t method_idx,
339 ArtMethod* referrer,
340 InvokeType type) {
Vladimir Markoba118822017-06-12 15:41:56 +0100341 DCHECK(referrer != nullptr);
342 // Note: The referrer can be a Proxy constructor. In that case, we need to do the
343 // lookup in the context of the original method from where it steals the code.
344 // However, we delay the GetInterfaceMethodIfProxy() until needed.
345 DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700346 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000347 // We do not need the read barrier for getting the DexCache for the initial resolved method
348 // lookup as both from-space and to-space copies point to the same native resolved methods array.
Vladimir Marko5122e6b2017-08-17 16:10:09 +0100349 ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
350 method_idx, image_pointer_size_);
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100351 DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
352 if (UNLIKELY(resolved_method == nullptr)) {
Vladimir Markoba118822017-06-12 15:41:56 +0100353 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700354 ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700355 StackHandleScope<2> hs(self);
Alex Light4ba388a2017-01-27 10:26:49 -0800356 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
Mathieu Chartiere401d142015-04-22 13:56:20 -0700357 Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
Vladimir Marko89011192017-12-11 13:45:05 +0000358 resolved_method = ResolveMethod<kResolveMode>(method_idx,
Andreas Gampe42ef8ab2015-12-03 17:27:32 -0800359 h_dex_cache,
360 h_class_loader,
361 referrer,
362 type);
Vladimir Markoba118822017-06-12 15:41:56 +0100363 } else if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
364 referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
365 // Check if the invoke type matches the class type.
366 ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
367 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700368 if (CheckInvokeClassMismatch</* kThrow= */ true>(dex_cache, type, method_idx, class_loader)) {
Vladimir Markoba118822017-06-12 15:41:56 +0100369 DCHECK(Thread::Current()->IsExceptionPending());
370 return nullptr;
371 }
372 // Check access.
373 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
374 if (!referring_class->CheckResolvedMethodAccess(resolved_method->GetDeclaringClass(),
375 resolved_method,
376 dex_cache,
377 method_idx,
378 type)) {
379 DCHECK(Thread::Current()->IsExceptionPending());
380 return nullptr;
381 }
382 // Check if the invoke type matches the method type.
383 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
384 ThrowIncompatibleClassChangeError(type,
385 resolved_method->GetInvokeType(),
386 resolved_method,
387 referrer);
388 return nullptr;
389 }
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700390 }
Andreas Gampe58a5af82014-07-31 16:23:49 -0700391 // Note: We cannot check here to see whether we added the method to the cache. It
392 // might be an erroneous class, which results in it being hidden from us.
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700393 return resolved_method;
394}
395
Vladimir Markof44d36c2017-03-14 14:18:46 +0000396inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx,
397 ArtMethod* referrer,
398 bool is_static) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000399 // We do not need the read barrier for getting the DexCache for the initial resolved field
400 // lookup as both from-space and to-space copies point to the same native resolved fields array.
401 ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
402 field_idx, image_pointer_size_);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000403 if (field == nullptr) {
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000404 ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
405 field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
Vladimir Markof44d36c2017-03-14 14:18:46 +0000406 }
407 return field;
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700408}
409
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700410inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
411 ArtMethod* referrer,
Mathieu Chartiere401d142015-04-22 13:56:20 -0700412 bool is_static) {
Mathieu Chartiera59d9b22016-09-26 18:13:17 -0700413 Thread::PoisonObjectPointersIfDebug();
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000414 // We do not need the read barrier for getting the DexCache for the initial resolved field
415 // lookup as both from-space and to-space copies point to the same native resolved fields array.
416 ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
417 field_idx, image_pointer_size_);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700418 if (UNLIKELY(resolved_field == nullptr)) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700419 StackHandleScope<2> hs(Thread::Current());
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000420 ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
Alex Lightdba61482016-12-21 08:20:29 -0800421 Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
Vladimir Marko666ee3d2017-12-11 18:37:36 +0000422 Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
Vladimir Markoe11dd502017-12-08 14:09:45 +0000423 resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static);
Andreas Gampe58a5af82014-07-31 16:23:49 -0700424 // Note: We cannot check here to see whether we added the field to the cache. The type
425 // might be an erroneous class, which results in it being hidden from us.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800426 }
427 return resolved_field;
428}
429
Mathieu Chartier72041a02017-07-14 18:23:25 -0700430template <class Visitor>
431inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
432 Thread* const self = Thread::Current();
433 WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
434 for (const ClassLoaderData& data : class_loaders_) {
435 if (data.class_table != nullptr) {
436 visitor(data.class_table);
437 }
438 }
439}
440
Andreas Gampe88dbad32018-06-26 19:54:12 -0700441template <ReadBarrierOption kReadBarrierOption>
442inline ObjPtr<mirror::ObjectArray<mirror::Class>> ClassLinker::GetClassRoots() {
443 ObjPtr<mirror::ObjectArray<mirror::Class>> class_roots =
444 class_roots_.Read<kReadBarrierOption>();
445 DCHECK(class_roots != nullptr);
446 return class_roots;
447}
448
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800449} // namespace art
450
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700451#endif // ART_RUNTIME_CLASS_LINKER_INL_H_