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 #include "class.h"
18
19 #include <unordered_set>
20 #include <string_view>
21
22 #include "android-base/macros.h"
23 #include "android-base/stringprintf.h"
24
25 #include "array-inl.h"
26 #include "art_field-inl.h"
27 #include "art_method-inl.h"
28 #include "base/enums.h"
29 #include "base/logging.h" // For VLOG.
30 #include "base/utils.h"
31 #include "class-inl.h"
32 #include "class_ext-inl.h"
33 #include "class_linker-inl.h"
34 #include "class_loader.h"
35 #include "class_root-inl.h"
36 #include "dex/descriptors_names.h"
37 #include "dex/dex_file-inl.h"
38 #include "dex/dex_file_annotations.h"
39 #include "dex/signature-inl.h"
40 #include "dex_cache-inl.h"
41 #include "field.h"
42 #include "gc/accounting/card_table-inl.h"
43 #include "gc/heap-inl.h"
44 #include "handle_scope-inl.h"
45 #include "hidden_api.h"
46 #include "jni_id_type.h"
47 #include "subtype_check.h"
48 #include "method.h"
49 #include "object-inl.h"
50 #include "object-refvisitor-inl.h"
51 #include "object_array-alloc-inl.h"
52 #include "object_array-inl.h"
53 #include "object_lock.h"
54 #include "string-inl.h"
55 #include "runtime.h"
56 #include "thread.h"
57 #include "throwable.h"
58 #include "well_known_classes.h"
59
60 namespace art {
61
62 // TODO: move to own CC file?
63 constexpr size_t BitString::kBitSizeAtPosition[BitString::kCapacity];
64 constexpr size_t BitString::kCapacity;
65
66 namespace mirror {
67
68 using android::base::StringPrintf;
69
IsMirrored()70 bool Class::IsMirrored() {
71 if (LIKELY(!IsBootStrapClassLoaded())) {
72 return false;
73 }
74 if (IsPrimitive() || IsArrayClass() || IsProxyClass()) {
75 return true;
76 }
77 std::string name_storage;
78 const std::string_view name(this->GetDescriptor(&name_storage));
79 return IsMirroredDescriptor(name);
80 }
81
GetPrimitiveClass(ObjPtr<mirror::String> name)82 ObjPtr<mirror::Class> Class::GetPrimitiveClass(ObjPtr<mirror::String> name) {
83 const char* expected_name = nullptr;
84 ClassRoot class_root = ClassRoot::kJavaLangObject; // Invalid.
85 if (name != nullptr && name->GetLength() >= 2) {
86 // Perfect hash for the expected values: from the second letters of the primitive types,
87 // only 'y' has the bit 0x10 set, so use it to change 'b' to 'B'.
88 char hash = name->CharAt(0) ^ ((name->CharAt(1) & 0x10) << 1);
89 switch (hash) {
90 case 'b': expected_name = "boolean"; class_root = ClassRoot::kPrimitiveBoolean; break;
91 case 'B': expected_name = "byte"; class_root = ClassRoot::kPrimitiveByte; break;
92 case 'c': expected_name = "char"; class_root = ClassRoot::kPrimitiveChar; break;
93 case 'd': expected_name = "double"; class_root = ClassRoot::kPrimitiveDouble; break;
94 case 'f': expected_name = "float"; class_root = ClassRoot::kPrimitiveFloat; break;
95 case 'i': expected_name = "int"; class_root = ClassRoot::kPrimitiveInt; break;
96 case 'l': expected_name = "long"; class_root = ClassRoot::kPrimitiveLong; break;
97 case 's': expected_name = "short"; class_root = ClassRoot::kPrimitiveShort; break;
98 case 'v': expected_name = "void"; class_root = ClassRoot::kPrimitiveVoid; break;
99 default: break;
100 }
101 }
102 if (expected_name != nullptr && name->Equals(expected_name)) {
103 ObjPtr<mirror::Class> klass = GetClassRoot(class_root);
104 DCHECK(klass != nullptr);
105 return klass;
106 } else {
107 Thread* self = Thread::Current();
108 if (name == nullptr) {
109 // Note: ThrowNullPointerException() requires a message which we deliberately want to omit.
110 self->ThrowNewException("Ljava/lang/NullPointerException;", /* msg= */ nullptr);
111 } else {
112 self->ThrowNewException("Ljava/lang/ClassNotFoundException;", name->ToModifiedUtf8().c_str());
113 }
114 return nullptr;
115 }
116 }
117
EnsureExtDataPresent(Handle<Class> h_this,Thread * self)118 ObjPtr<ClassExt> Class::EnsureExtDataPresent(Handle<Class> h_this, Thread* self) {
119 ObjPtr<ClassExt> existing(h_this->GetExtData());
120 if (!existing.IsNull()) {
121 return existing;
122 }
123 StackHandleScope<2> hs(self);
124 // Clear exception so we can allocate.
125 Handle<Throwable> throwable(hs.NewHandle(self->GetException()));
126 self->ClearException();
127 // Allocate the ClassExt
128 Handle<ClassExt> new_ext(hs.NewHandle(ClassExt::Alloc(self)));
129 if (new_ext == nullptr) {
130 // OOM allocating the classExt.
131 // TODO Should we restore the suppressed exception?
132 self->AssertPendingOOMException();
133 return nullptr;
134 } else {
135 MemberOffset ext_offset(OFFSET_OF_OBJECT_MEMBER(Class, ext_data_));
136 bool set;
137 // Set the ext_data_ field using CAS semantics.
138 if (Runtime::Current()->IsActiveTransaction()) {
139 set = h_this->CasFieldObject<true>(ext_offset,
140 nullptr,
141 new_ext.Get(),
142 CASMode::kStrong,
143 std::memory_order_seq_cst);
144 } else {
145 set = h_this->CasFieldObject<false>(ext_offset,
146 nullptr,
147 new_ext.Get(),
148 CASMode::kStrong,
149 std::memory_order_seq_cst);
150 }
151 ObjPtr<ClassExt> ret(set ? new_ext.Get() : h_this->GetExtData());
152 DCHECK_IMPLIES(set, h_this->GetExtData() == new_ext.Get());
153 CHECK(!ret.IsNull());
154 // Restore the exception if there was one.
155 if (throwable != nullptr) {
156 self->SetException(throwable.Get());
157 }
158 return ret;
159 }
160 }
161
162 template <typename T>
CheckSetStatus(Thread * self,T thiz,ClassStatus new_status,ClassStatus old_status)163 static void CheckSetStatus(Thread* self, T thiz, ClassStatus new_status, ClassStatus old_status)
164 REQUIRES_SHARED(Locks::mutator_lock_) {
165 if (UNLIKELY(new_status <= old_status && new_status != ClassStatus::kErrorUnresolved &&
166 new_status != ClassStatus::kErrorResolved && new_status != ClassStatus::kRetired)) {
167 LOG(FATAL) << "Unexpected change back of class status for " << thiz->PrettyClass() << " "
168 << old_status << " -> " << new_status;
169 }
170 if (old_status == ClassStatus::kInitialized) {
171 // We do not hold the lock for making the class visibly initialized
172 // as this is unnecessary and could lead to deadlocks.
173 CHECK_EQ(new_status, ClassStatus::kVisiblyInitialized);
174 } else if ((new_status >= ClassStatus::kResolved || old_status >= ClassStatus::kResolved) &&
175 !Locks::mutator_lock_->IsExclusiveHeld(self)) {
176 // When classes are being resolved the resolution code should hold the
177 // lock or have everything else suspended
178 CHECK_EQ(thiz->GetLockOwnerThreadId(), self->GetThreadId())
179 << "Attempt to change status of class while not holding its lock: " << thiz->PrettyClass()
180 << " " << old_status << " -> " << new_status;
181 }
182 if (UNLIKELY(Locks::mutator_lock_->IsExclusiveHeld(self))) {
183 CHECK(!Class::IsErroneous(new_status))
184 << "status " << new_status
185 << " cannot be set while suspend-all is active. Would require allocations.";
186 CHECK(thiz->IsResolved())
187 << thiz->PrettyClass()
188 << " not resolved during suspend-all status change. Waiters might be missed!";
189 }
190 }
191
SetStatusInternal(ClassStatus new_status)192 void Class::SetStatusInternal(ClassStatus new_status) {
193 if (kBitstringSubtypeCheckEnabled) {
194 // FIXME: This looks broken with respect to aborted transactions.
195 SubtypeCheck<ObjPtr<mirror::Class>>::WriteStatus(this, new_status);
196 } else {
197 // The ClassStatus is always in the 4 most-significant bits of status_.
198 static_assert(sizeof(status_) == sizeof(uint32_t), "Size of status_ not equal to uint32");
199 uint32_t new_status_value = static_cast<uint32_t>(new_status) << (32 - kClassStatusBitSize);
200 if (Runtime::Current()->IsActiveTransaction()) {
201 SetField32Volatile<true>(StatusOffset(), new_status_value);
202 } else {
203 SetField32Volatile<false>(StatusOffset(), new_status_value);
204 }
205 }
206 }
207
SetStatusLocked(ClassStatus new_status)208 void Class::SetStatusLocked(ClassStatus new_status) {
209 ClassStatus old_status = GetStatus();
210 CheckSetStatus(Thread::Current(), this, new_status, old_status);
211 SetStatusInternal(new_status);
212 }
213
SetStatus(Handle<Class> h_this,ClassStatus new_status,Thread * self)214 void Class::SetStatus(Handle<Class> h_this, ClassStatus new_status, Thread* self) {
215 ClassStatus old_status = h_this->GetStatus();
216 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
217 bool class_linker_initialized = class_linker != nullptr && class_linker->IsInitialized();
218 if (LIKELY(class_linker_initialized)) {
219 CheckSetStatus(self, h_this, new_status, old_status);
220 }
221 if (UNLIKELY(IsErroneous(new_status))) {
222 CHECK(!h_this->IsErroneous())
223 << "Attempt to set as erroneous an already erroneous class "
224 << h_this->PrettyClass()
225 << " old_status: " << old_status << " new_status: " << new_status;
226 CHECK_EQ(new_status == ClassStatus::kErrorResolved, old_status >= ClassStatus::kResolved);
227 if (VLOG_IS_ON(class_linker)) {
228 LOG(ERROR) << "Setting " << h_this->PrettyDescriptor() << " to erroneous.";
229 if (self->IsExceptionPending()) {
230 LOG(ERROR) << "Exception: " << self->GetException()->Dump();
231 }
232 }
233
234 ObjPtr<ClassExt> ext(EnsureExtDataPresent(h_this, self));
235 if (!ext.IsNull()) {
236 self->AssertPendingException();
237 ext->SetErroneousStateError(self->GetException());
238 } else {
239 self->AssertPendingOOMException();
240 }
241 self->AssertPendingException();
242 }
243
244 h_this->SetStatusInternal(new_status);
245
246 // Setting the object size alloc fast path needs to be after the status write so that if the
247 // alloc path sees a valid object size, we would know that it's initialized as long as it has a
248 // load-acquire/fake dependency.
249 if (new_status == ClassStatus::kVisiblyInitialized && !h_this->IsVariableSize()) {
250 DCHECK_EQ(h_this->GetObjectSizeAllocFastPath(), std::numeric_limits<uint32_t>::max());
251 // Finalizable objects must always go slow path.
252 if (!h_this->IsFinalizable()) {
253 h_this->SetObjectSizeAllocFastPath(RoundUp(h_this->GetObjectSize(), kObjectAlignment));
254 }
255 }
256
257 if (!class_linker_initialized) {
258 // When the class linker is being initialized its single threaded and by definition there can be
259 // no waiters. During initialization classes may appear temporary but won't be retired as their
260 // size was statically computed.
261 } else {
262 // Classes that are being resolved or initialized need to notify waiters that the class status
263 // changed. See ClassLinker::EnsureResolved and ClassLinker::WaitForInitializeClass.
264 if (h_this->IsTemp()) {
265 // Class is a temporary one, ensure that waiters for resolution get notified of retirement
266 // so that they can grab the new version of the class from the class linker's table.
267 CHECK_LT(new_status, ClassStatus::kResolved) << h_this->PrettyDescriptor();
268 if (new_status == ClassStatus::kRetired || new_status == ClassStatus::kErrorUnresolved) {
269 h_this->NotifyAll(self);
270 }
271 } else if (old_status == ClassStatus::kInitialized) {
272 // Do not notify for transition from kInitialized to ClassStatus::kVisiblyInitialized.
273 // This is a hidden transition, not observable by bytecode.
274 DCHECK_EQ(new_status, ClassStatus::kVisiblyInitialized); // Already CHECK()ed above.
275 } else {
276 CHECK_NE(new_status, ClassStatus::kRetired);
277 if (old_status >= ClassStatus::kResolved || new_status >= ClassStatus::kResolved) {
278 h_this->NotifyAll(self);
279 }
280 }
281 }
282 }
283
SetStatusForPrimitiveOrArray(ClassStatus new_status)284 void Class::SetStatusForPrimitiveOrArray(ClassStatus new_status) {
285 DCHECK(IsPrimitive<kVerifyNone>() || IsArrayClass<kVerifyNone>());
286 DCHECK(!IsErroneous(new_status));
287 DCHECK(!IsErroneous(GetStatus<kVerifyNone>()));
288 DCHECK_GT(new_status, GetStatus<kVerifyNone>());
289
290 if (kBitstringSubtypeCheckEnabled) {
291 LOG(FATAL) << "Unimplemented";
292 }
293 // The ClassStatus is always in the 4 most-significant bits of status_.
294 static_assert(sizeof(status_) == sizeof(uint32_t), "Size of status_ not equal to uint32");
295 uint32_t new_status_value = static_cast<uint32_t>(new_status) << (32 - kClassStatusBitSize);
296 // Use normal store. For primitives and core arrays classes (Object[],
297 // Class[], String[] and primitive arrays), the status is set while the
298 // process is still single threaded. For other arrays classes, it is set
299 // in a pre-fence visitor which initializes all fields and the subsequent
300 // fence together with address dependency shall ensure memory visibility.
301 SetField32</*kTransactionActive=*/ false,
302 /*kCheckTransaction=*/ false,
303 kVerifyNone>(StatusOffset(), new_status_value);
304
305 // Do not update `object_alloc_fast_path_`. Arrays are variable size and
306 // instances of primitive classes cannot be created at all.
307
308 // There can be no waiters to notify as these classes are initialized
309 // before another thread can see them.
310 }
311
SetDexCache(ObjPtr<DexCache> new_dex_cache)312 void Class::SetDexCache(ObjPtr<DexCache> new_dex_cache) {
313 SetFieldObjectTransaction(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache);
314 }
315
SetClassSize(uint32_t new_class_size)316 void Class::SetClassSize(uint32_t new_class_size) {
317 if (kIsDebugBuild && new_class_size < GetClassSize()) {
318 DumpClass(LOG_STREAM(FATAL_WITHOUT_ABORT), kDumpClassFullDetail);
319 LOG(FATAL_WITHOUT_ABORT) << new_class_size << " vs " << GetClassSize();
320 LOG(FATAL) << "class=" << PrettyTypeOf();
321 }
322 SetField32</*kTransactionActive=*/ false, /*kCheckTransaction=*/ false>(
323 OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size);
324 }
325
GetObsoleteClass()326 ObjPtr<Class> Class::GetObsoleteClass() {
327 ObjPtr<ClassExt> ext(GetExtData());
328 if (ext.IsNull()) {
329 return nullptr;
330 } else {
331 return ext->GetObsoleteClass();
332 }
333 }
334
335 // Return the class' name. The exact format is bizarre, but it's the specified behavior for
336 // Class.getName: keywords for primitive types, regular "[I" form for primitive arrays (so "int"
337 // but "[I"), and arrays of reference types written between "L" and ";" but with dots rather than
338 // slashes (so "java.lang.String" but "[Ljava.lang.String;"). Madness.
ComputeName(Handle<Class> h_this)339 ObjPtr<String> Class::ComputeName(Handle<Class> h_this) {
340 ObjPtr<String> name = h_this->GetName();
341 if (name != nullptr) {
342 return name;
343 }
344 std::string temp;
345 const char* descriptor = h_this->GetDescriptor(&temp);
346 Thread* self = Thread::Current();
347 if ((descriptor[0] != 'L') && (descriptor[0] != '[')) {
348 // The descriptor indicates that this is the class for
349 // a primitive type; special-case the return value.
350 const char* c_name = nullptr;
351 switch (descriptor[0]) {
352 case 'Z': c_name = "boolean"; break;
353 case 'B': c_name = "byte"; break;
354 case 'C': c_name = "char"; break;
355 case 'S': c_name = "short"; break;
356 case 'I': c_name = "int"; break;
357 case 'J': c_name = "long"; break;
358 case 'F': c_name = "float"; break;
359 case 'D': c_name = "double"; break;
360 case 'V': c_name = "void"; break;
361 default:
362 LOG(FATAL) << "Unknown primitive type: " << PrintableChar(descriptor[0]);
363 }
364 name = String::AllocFromModifiedUtf8(self, c_name);
365 } else {
366 // Convert the UTF-8 name to a java.lang.String. The name must use '.' to separate package
367 // components.
368 name = String::AllocFromModifiedUtf8(self, DescriptorToDot(descriptor).c_str());
369 }
370 h_this->SetName(name);
371 return name;
372 }
373
DumpClass(std::ostream & os,int flags)374 void Class::DumpClass(std::ostream& os, int flags) {
375 ScopedAssertNoThreadSuspension ants(__FUNCTION__);
376 if ((flags & kDumpClassFullDetail) == 0) {
377 os << PrettyClass();
378 if ((flags & kDumpClassClassLoader) != 0) {
379 os << ' ' << GetClassLoader();
380 }
381 if ((flags & kDumpClassInitialized) != 0) {
382 os << ' ' << GetStatus();
383 }
384 os << "\n";
385 return;
386 }
387
388 ObjPtr<Class> super = GetSuperClass();
389 auto image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
390
391 std::string temp;
392 os << "----- " << (IsInterface() ? "interface" : "class") << " "
393 << "'" << GetDescriptor(&temp) << "' cl=" << GetClassLoader() << " -----\n"
394 << " objectSize=" << SizeOf() << " "
395 << "(" << (super != nullptr ? super->SizeOf() : -1) << " from super)\n"
396 << StringPrintf(" access=0x%04x.%04x\n",
397 GetAccessFlags() >> 16,
398 GetAccessFlags() & kAccJavaFlagsMask);
399 if (super != nullptr) {
400 os << " super='" << super->PrettyClass() << "' (cl=" << super->GetClassLoader() << ")\n";
401 }
402 if (IsArrayClass()) {
403 os << " componentType=" << PrettyClass(GetComponentType()) << "\n";
404 }
405 const size_t num_direct_interfaces = NumDirectInterfaces();
406 if (num_direct_interfaces > 0) {
407 os << " interfaces (" << num_direct_interfaces << "):\n";
408 for (size_t i = 0; i < num_direct_interfaces; ++i) {
409 ObjPtr<Class> interface = GetDirectInterface(i);
410 if (interface == nullptr) {
411 os << StringPrintf(" %2zd: nullptr!\n", i);
412 } else {
413 ObjPtr<ClassLoader> cl = interface->GetClassLoader();
414 os << StringPrintf(" %2zd: %s (cl=%p)\n", i, PrettyClass(interface).c_str(), cl.Ptr());
415 }
416 }
417 }
418 if (!IsLoaded()) {
419 os << " class not yet loaded";
420 } else {
421 os << " vtable (" << NumVirtualMethods() << " entries, "
422 << (super != nullptr ? super->NumVirtualMethods() : 0) << " in super):\n";
423 for (size_t i = 0; i < NumVirtualMethods(); ++i) {
424 os << StringPrintf(" %2zd: %s\n", i, ArtMethod::PrettyMethod(
425 GetVirtualMethodDuringLinking(i, image_pointer_size)).c_str());
426 }
427 os << " direct methods (" << NumDirectMethods() << " entries):\n";
428 for (size_t i = 0; i < NumDirectMethods(); ++i) {
429 os << StringPrintf(" %2zd: %s\n", i, ArtMethod::PrettyMethod(
430 GetDirectMethod(i, image_pointer_size)).c_str());
431 }
432 if (NumStaticFields() > 0) {
433 os << " static fields (" << NumStaticFields() << " entries):\n";
434 if (IsResolved()) {
435 for (size_t i = 0; i < NumStaticFields(); ++i) {
436 os << StringPrintf(" %2zd: %s\n", i, ArtField::PrettyField(GetStaticField(i)).c_str());
437 }
438 } else {
439 os << " <not yet available>";
440 }
441 }
442 if (NumInstanceFields() > 0) {
443 os << " instance fields (" << NumInstanceFields() << " entries):\n";
444 if (IsResolved()) {
445 for (size_t i = 0; i < NumInstanceFields(); ++i) {
446 os << StringPrintf(" %2zd: %s\n", i,
447 ArtField::PrettyField(GetInstanceField(i)).c_str());
448 }
449 } else {
450 os << " <not yet available>";
451 }
452 }
453 }
454 }
455
SetReferenceInstanceOffsets(uint32_t new_reference_offsets)456 void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
457 if (kIsDebugBuild && new_reference_offsets != kClassWalkSuper) {
458 // Check that the number of bits set in the reference offset bitmap
459 // agrees with the number of references.
460 uint32_t count = 0;
461 for (ObjPtr<Class> c = this; c != nullptr; c = c->GetSuperClass()) {
462 count += c->NumReferenceInstanceFieldsDuringLinking();
463 }
464 // +1 for the Class in Object.
465 CHECK_EQ(static_cast<uint32_t>(POPCOUNT(new_reference_offsets)) + 1, count);
466 }
467 // Not called within a transaction.
468 SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
469 new_reference_offsets);
470 }
471
IsInSamePackage(std::string_view descriptor1,std::string_view descriptor2)472 bool Class::IsInSamePackage(std::string_view descriptor1, std::string_view descriptor2) {
473 size_t i = 0;
474 size_t min_length = std::min(descriptor1.size(), descriptor2.size());
475 while (i < min_length && descriptor1[i] == descriptor2[i]) {
476 ++i;
477 }
478 if (descriptor1.find('/', i) != std::string_view::npos ||
479 descriptor2.find('/', i) != std::string_view::npos) {
480 return false;
481 } else {
482 return true;
483 }
484 }
485
IsInSamePackage(ObjPtr<Class> that)486 bool Class::IsInSamePackage(ObjPtr<Class> that) {
487 ObjPtr<Class> klass1 = this;
488 ObjPtr<Class> klass2 = that;
489 if (klass1 == klass2) {
490 return true;
491 }
492 // Class loaders must match.
493 if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
494 return false;
495 }
496 // Arrays are in the same package when their element classes are.
497 while (klass1->IsArrayClass()) {
498 klass1 = klass1->GetComponentType();
499 }
500 while (klass2->IsArrayClass()) {
501 klass2 = klass2->GetComponentType();
502 }
503 // trivial check again for array types
504 if (klass1 == klass2) {
505 return true;
506 }
507 // Compare the package part of the descriptor string.
508 std::string temp1, temp2;
509 return IsInSamePackage(klass1->GetDescriptor(&temp1), klass2->GetDescriptor(&temp2));
510 }
511
IsThrowableClass()512 bool Class::IsThrowableClass() {
513 return GetClassRoot<mirror::Throwable>()->IsAssignableFrom(this);
514 }
515
516 template <typename SignatureType>
FindInterfaceMethodWithSignature(ObjPtr<Class> klass,std::string_view name,const SignatureType & signature,PointerSize pointer_size)517 static inline ArtMethod* FindInterfaceMethodWithSignature(ObjPtr<Class> klass,
518 std::string_view name,
519 const SignatureType& signature,
520 PointerSize pointer_size)
521 REQUIRES_SHARED(Locks::mutator_lock_) {
522 // If the current class is not an interface, skip the search of its declared methods;
523 // such lookup is used only to distinguish between IncompatibleClassChangeError and
524 // NoSuchMethodError and the caller has already tried to search methods in the class.
525 if (LIKELY(klass->IsInterface())) {
526 // Search declared methods, both direct and virtual.
527 // (This lookup is used also for invoke-static on interface classes.)
528 for (ArtMethod& method : klass->GetDeclaredMethodsSlice(pointer_size)) {
529 if (method.GetNameView() == name && method.GetSignature() == signature) {
530 return &method;
531 }
532 }
533 }
534
535 // TODO: If there is a unique maximally-specific non-abstract superinterface method,
536 // we should return it, otherwise an arbitrary one can be returned.
537 ObjPtr<IfTable> iftable = klass->GetIfTable();
538 for (int32_t i = 0, iftable_count = iftable->Count(); i < iftable_count; ++i) {
539 ObjPtr<Class> iface = iftable->GetInterface(i);
540 for (ArtMethod& method : iface->GetVirtualMethodsSlice(pointer_size)) {
541 if (method.GetNameView() == name && method.GetSignature() == signature) {
542 return &method;
543 }
544 }
545 }
546
547 // Then search for public non-static methods in the java.lang.Object.
548 if (LIKELY(klass->IsInterface())) {
549 ObjPtr<Class> object_class = klass->GetSuperClass();
550 DCHECK(object_class->IsObjectClass());
551 for (ArtMethod& method : object_class->GetDeclaredMethodsSlice(pointer_size)) {
552 if (method.IsPublic() && !method.IsStatic() &&
553 method.GetNameView() == name && method.GetSignature() == signature) {
554 return &method;
555 }
556 }
557 }
558 return nullptr;
559 }
560
FindInterfaceMethod(std::string_view name,std::string_view signature,PointerSize pointer_size)561 ArtMethod* Class::FindInterfaceMethod(std::string_view name,
562 std::string_view signature,
563 PointerSize pointer_size) {
564 return FindInterfaceMethodWithSignature(this, name, signature, pointer_size);
565 }
566
FindInterfaceMethod(std::string_view name,const Signature & signature,PointerSize pointer_size)567 ArtMethod* Class::FindInterfaceMethod(std::string_view name,
568 const Signature& signature,
569 PointerSize pointer_size) {
570 return FindInterfaceMethodWithSignature(this, name, signature, pointer_size);
571 }
572
FindInterfaceMethod(ObjPtr<DexCache> dex_cache,uint32_t dex_method_idx,PointerSize pointer_size)573 ArtMethod* Class::FindInterfaceMethod(ObjPtr<DexCache> dex_cache,
574 uint32_t dex_method_idx,
575 PointerSize pointer_size) {
576 // We always search by name and signature, ignoring the type index in the MethodId.
577 const DexFile& dex_file = *dex_cache->GetDexFile();
578 const dex::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
579 std::string_view name = dex_file.StringViewByIdx(method_id.name_idx_);
580 const Signature signature = dex_file.GetMethodSignature(method_id);
581 return FindInterfaceMethod(name, signature, pointer_size);
582 }
583
IsValidInheritanceCheck(ObjPtr<mirror::Class> klass,ObjPtr<mirror::Class> declaring_class)584 static inline bool IsValidInheritanceCheck(ObjPtr<mirror::Class> klass,
585 ObjPtr<mirror::Class> declaring_class)
586 REQUIRES_SHARED(Locks::mutator_lock_) {
587 if (klass->IsArrayClass()) {
588 return declaring_class->IsObjectClass();
589 } else if (klass->IsInterface()) {
590 return declaring_class->IsObjectClass() || declaring_class == klass;
591 } else {
592 return klass->IsSubClass(declaring_class);
593 }
594 }
595
IsInheritedMethod(ObjPtr<mirror::Class> klass,ObjPtr<mirror::Class> declaring_class,ArtMethod & method)596 static inline bool IsInheritedMethod(ObjPtr<mirror::Class> klass,
597 ObjPtr<mirror::Class> declaring_class,
598 ArtMethod& method)
599 REQUIRES_SHARED(Locks::mutator_lock_) {
600 DCHECK_EQ(declaring_class, method.GetDeclaringClass());
601 DCHECK_NE(klass, declaring_class);
602 DCHECK(IsValidInheritanceCheck(klass, declaring_class));
603 uint32_t access_flags = method.GetAccessFlags();
604 if ((access_flags & (kAccPublic | kAccProtected)) != 0) {
605 return true;
606 }
607 if ((access_flags & kAccPrivate) != 0) {
608 return false;
609 }
610 for (; klass != declaring_class; klass = klass->GetSuperClass()) {
611 if (!klass->IsInSamePackage(declaring_class)) {
612 return false;
613 }
614 }
615 return true;
616 }
617
618 template <typename SignatureType>
FindClassMethodWithSignature(ObjPtr<Class> this_klass,std::string_view name,const SignatureType & signature,PointerSize pointer_size)619 static inline ArtMethod* FindClassMethodWithSignature(ObjPtr<Class> this_klass,
620 std::string_view name,
621 const SignatureType& signature,
622 PointerSize pointer_size)
623 REQUIRES_SHARED(Locks::mutator_lock_) {
624 // Search declared methods first.
625 for (ArtMethod& method : this_klass->GetDeclaredMethodsSlice(pointer_size)) {
626 ArtMethod* np_method = method.GetInterfaceMethodIfProxy(pointer_size);
627 if (np_method->GetNameView() == name && np_method->GetSignature() == signature) {
628 return &method;
629 }
630 }
631
632 // Then search the superclass chain. If we find an inherited method, return it.
633 // If we find a method that's not inherited because of access restrictions,
634 // try to find a method inherited from an interface in copied methods.
635 ObjPtr<Class> klass = this_klass->GetSuperClass();
636 ArtMethod* uninherited_method = nullptr;
637 for (; klass != nullptr; klass = klass->GetSuperClass()) {
638 DCHECK(!klass->IsProxyClass());
639 for (ArtMethod& method : klass->GetDeclaredMethodsSlice(pointer_size)) {
640 if (method.GetNameView() == name && method.GetSignature() == signature) {
641 if (IsInheritedMethod(this_klass, klass, method)) {
642 return &method;
643 }
644 uninherited_method = &method;
645 break;
646 }
647 }
648 if (uninherited_method != nullptr) {
649 break;
650 }
651 }
652
653 // Then search copied methods.
654 // If we found a method that's not inherited, stop the search in its declaring class.
655 ObjPtr<Class> end_klass = klass;
656 DCHECK_EQ(uninherited_method != nullptr, end_klass != nullptr);
657 klass = this_klass;
658 if (UNLIKELY(klass->IsProxyClass())) {
659 DCHECK(klass->GetCopiedMethodsSlice(pointer_size).empty());
660 klass = klass->GetSuperClass();
661 }
662 for (; klass != end_klass; klass = klass->GetSuperClass()) {
663 DCHECK(!klass->IsProxyClass());
664 for (ArtMethod& method : klass->GetCopiedMethodsSlice(pointer_size)) {
665 if (method.GetNameView() == name && method.GetSignature() == signature) {
666 return &method; // No further check needed, copied methods are inherited by definition.
667 }
668 }
669 }
670 return uninherited_method; // Return the `uninherited_method` if any.
671 }
672
673
FindClassMethod(std::string_view name,std::string_view signature,PointerSize pointer_size)674 ArtMethod* Class::FindClassMethod(std::string_view name,
675 std::string_view signature,
676 PointerSize pointer_size) {
677 return FindClassMethodWithSignature(this, name, signature, pointer_size);
678 }
679
FindClassMethod(std::string_view name,const Signature & signature,PointerSize pointer_size)680 ArtMethod* Class::FindClassMethod(std::string_view name,
681 const Signature& signature,
682 PointerSize pointer_size) {
683 return FindClassMethodWithSignature(this, name, signature, pointer_size);
684 }
685
686 // Binary search a range with a three-way compare function.
687 //
688 // Return a tuple consisting of a `success` value, the index of the match (`mid`) and
689 // the remaining range when we found the match (`begin` and `end`). This is useful for
690 // subsequent binary search with a secondary comparator, see `ClassMemberBinarySearch()`.
691 template <typename Compare>
692 ALWAYS_INLINE
BinarySearch(uint32_t begin,uint32_t end,Compare && cmp)693 std::tuple<bool, uint32_t, uint32_t, uint32_t> BinarySearch(uint32_t begin,
694 uint32_t end,
695 Compare&& cmp)
696 REQUIRES_SHARED(Locks::mutator_lock_) {
697 while (begin != end) {
698 uint32_t mid = (begin + end) >> 1;
699 auto cmp_result = cmp(mid);
700 if (cmp_result == 0) {
701 return {true, mid, begin, end};
702 }
703 if (cmp_result > 0) {
704 begin = mid + 1u;
705 } else {
706 end = mid;
707 }
708 }
709 return {false, 0u, 0u, 0u};
710 }
711
712 // Binary search for class members. The range passed to this search must be sorted, so
713 // declared methods or fields cannot be searched directly but declared direct methods,
714 // declared virtual methods, declared static fields or declared instance fields can.
715 template <typename NameCompare, typename SecondCompare, typename NameIndexGetter>
716 ALWAYS_INLINE
ClassMemberBinarySearch(uint32_t begin,uint32_t end,NameCompare && name_cmp,SecondCompare && second_cmp,NameIndexGetter && get_name_idx)717 std::tuple<bool, uint32_t> ClassMemberBinarySearch(uint32_t begin,
718 uint32_t end,
719 NameCompare&& name_cmp,
720 SecondCompare&& second_cmp,
721 NameIndexGetter&& get_name_idx)
722 REQUIRES_SHARED(Locks::mutator_lock_) {
723 // First search for the item with the given name.
724 bool success;
725 uint32_t mid;
726 std::tie(success, mid, begin, end) = BinarySearch(begin, end, name_cmp);
727 if (!success) {
728 return {false, 0u};
729 }
730 // If found, do the secondary comparison.
731 auto second_cmp_result = second_cmp(mid);
732 if (second_cmp_result == 0) {
733 return {true, mid};
734 }
735 // We have matched the name but not the secondary comparison. We no longer need to
736 // search for the name as string as we know the matching name string index.
737 // Repeat the above binary searches and secondary comparisons with a simpler name
738 // index compare until the search range contains only matching name.
739 auto name_idx = get_name_idx(mid);
740 if (second_cmp_result > 0) {
741 do {
742 begin = mid + 1u;
743 auto name_index_cmp = [&](uint32_t mid2) REQUIRES_SHARED(Locks::mutator_lock_) {
744 DCHECK_LE(name_idx, get_name_idx(mid2));
745 return (name_idx != get_name_idx(mid2)) ? -1 : 0;
746 };
747 std::tie(success, mid, begin, end) = BinarySearch(begin, end, name_index_cmp);
748 if (!success) {
749 return {false, 0u};
750 }
751 second_cmp_result = second_cmp(mid);
752 } while (second_cmp_result > 0);
753 end = mid;
754 } else {
755 do {
756 end = mid;
757 auto name_index_cmp = [&](uint32_t mid2) REQUIRES_SHARED(Locks::mutator_lock_) {
758 DCHECK_GE(name_idx, get_name_idx(mid2));
759 return (name_idx != get_name_idx(mid2)) ? 1 : 0;
760 };
761 std::tie(success, mid, begin, end) = BinarySearch(begin, end, name_index_cmp);
762 if (!success) {
763 return {false, 0u};
764 }
765 second_cmp_result = second_cmp(mid);
766 } while (second_cmp_result < 0);
767 begin = mid + 1u;
768 }
769 if (second_cmp_result == 0) {
770 return {true, mid};
771 }
772 // All items in the remaining range have a matching name, so search with secondary comparison.
773 std::tie(success, mid, std::ignore, std::ignore) = BinarySearch(begin, end, second_cmp);
774 return {success, mid};
775 }
776
FindDeclaredClassMethod(ObjPtr<mirror::Class> klass,const DexFile & dex_file,std::string_view name,Signature signature,PointerSize pointer_size)777 static std::tuple<bool, ArtMethod*> FindDeclaredClassMethod(ObjPtr<mirror::Class> klass,
778 const DexFile& dex_file,
779 std::string_view name,
780 Signature signature,
781 PointerSize pointer_size)
782 REQUIRES_SHARED(Locks::mutator_lock_) {
783 DCHECK(&klass->GetDexFile() == &dex_file);
784 DCHECK(!name.empty());
785
786 ArraySlice<ArtMethod> declared_methods = klass->GetDeclaredMethodsSlice(pointer_size);
787 DCHECK(!declared_methods.empty());
788 auto get_method_id = [&](uint32_t mid) REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE
789 -> const dex::MethodId& {
790 ArtMethod& method = declared_methods[mid];
791 DCHECK(method.GetDexFile() == &dex_file);
792 DCHECK_NE(method.GetDexMethodIndex(), dex::kDexNoIndex);
793 return dex_file.GetMethodId(method.GetDexMethodIndex());
794 };
795 auto name_cmp = [&](uint32_t mid) REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE {
796 // Do not use ArtMethod::GetNameView() to avoid reloading dex file through the same
797 // declaring class from different methods and also avoid the runtime method check.
798 const dex::MethodId& method_id = get_method_id(mid);
799 return name.compare(dex_file.GetMethodNameView(method_id));
800 };
801 auto signature_cmp = [&](uint32_t mid) REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE {
802 // Do not use ArtMethod::GetSignature() to avoid reloading dex file through the same
803 // declaring class from different methods and also avoid the runtime method check.
804 const dex::MethodId& method_id = get_method_id(mid);
805 return signature.Compare(dex_file.GetMethodSignature(method_id));
806 };
807 auto get_name_idx = [&](uint32_t mid) REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE {
808 const dex::MethodId& method_id = get_method_id(mid);
809 return method_id.name_idx_;
810 };
811
812 // Use binary search in the sorted direct methods, then in the sorted virtual methods.
813 uint32_t num_direct_methods = klass->NumDirectMethods();
814 uint32_t num_declared_methods = dchecked_integral_cast<uint32_t>(declared_methods.size());
815 DCHECK_LE(num_direct_methods, num_declared_methods);
816 const uint32_t ranges[2][2] = {
817 {0u, num_direct_methods}, // Declared direct methods.
818 {num_direct_methods, num_declared_methods} // Declared virtual methods.
819 };
820 for (const uint32_t (&range)[2] : ranges) {
821 auto [success, mid] =
822 ClassMemberBinarySearch(range[0], range[1], name_cmp, signature_cmp, get_name_idx);
823 if (success) {
824 return {true, &declared_methods[mid]};
825 }
826 }
827
828 // Did not find a declared method in either slice.
829 return {false, nullptr};
830 }
831
832 FLATTEN
FindClassMethod(ObjPtr<DexCache> dex_cache,uint32_t dex_method_idx,PointerSize pointer_size)833 ArtMethod* Class::FindClassMethod(ObjPtr<DexCache> dex_cache,
834 uint32_t dex_method_idx,
835 PointerSize pointer_size) {
836 // FIXME: Hijacking a proxy class by a custom class loader can break this assumption.
837 DCHECK(!IsProxyClass());
838
839 // First try to find a declared method by dex_method_idx if we have a dex_cache match.
840 ObjPtr<DexCache> this_dex_cache = GetDexCache();
841 if (this_dex_cache == dex_cache) {
842 // Lookup is always performed in the class referenced by the MethodId.
843 DCHECK_EQ(dex_type_idx_, GetDexFile().GetMethodId(dex_method_idx).class_idx_.index_);
844 for (ArtMethod& method : GetDeclaredMethodsSlice(pointer_size)) {
845 if (method.GetDexMethodIndex() == dex_method_idx) {
846 return &method;
847 }
848 }
849 }
850
851 // If not found, we need to search by name and signature.
852 const DexFile& dex_file = *dex_cache->GetDexFile();
853 const dex::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
854 const Signature signature = dex_file.GetMethodSignature(method_id);
855 std::string_view name; // Do not touch the dex file string data until actually needed.
856
857 // If we do not have a dex_cache match, try to find the declared method in this class now.
858 if (this_dex_cache != dex_cache && !GetDeclaredMethodsSlice(pointer_size).empty()) {
859 DCHECK(name.empty());
860 name = dex_file.GetMethodNameView(method_id);
861 auto [success, method] = FindDeclaredClassMethod(
862 this, *this_dex_cache->GetDexFile(), name, signature, pointer_size);
863 DCHECK_EQ(success, method != nullptr);
864 if (success) {
865 return method;
866 }
867 }
868
869 // Then search the superclass chain. If we find an inherited method, return it.
870 // If we find a method that's not inherited because of access restrictions,
871 // try to find a method inherited from an interface in copied methods.
872 ArtMethod* uninherited_method = nullptr;
873 ObjPtr<Class> klass = GetSuperClass();
874 for (; klass != nullptr; klass = klass->GetSuperClass()) {
875 ArtMethod* candidate_method = nullptr;
876 ArraySlice<ArtMethod> declared_methods = klass->GetDeclaredMethodsSlice(pointer_size);
877 ObjPtr<DexCache> klass_dex_cache = klass->GetDexCache();
878 if (klass_dex_cache == dex_cache) {
879 // Matching dex_cache. We cannot compare the `dex_method_idx` anymore because
880 // the type index differs, so compare the name index and proto index.
881 for (ArtMethod& method : declared_methods) {
882 const dex::MethodId& cmp_method_id = dex_file.GetMethodId(method.GetDexMethodIndex());
883 if (cmp_method_id.name_idx_ == method_id.name_idx_ &&
884 cmp_method_id.proto_idx_ == method_id.proto_idx_) {
885 candidate_method = &method;
886 break;
887 }
888 }
889 } else if (!declared_methods.empty()) {
890 if (name.empty()) {
891 name = dex_file.GetMethodNameView(method_id);
892 }
893 auto [success, method] = FindDeclaredClassMethod(
894 klass, *klass_dex_cache->GetDexFile(), name, signature, pointer_size);
895 DCHECK_EQ(success, method != nullptr);
896 if (success) {
897 candidate_method = method;
898 }
899 }
900 if (candidate_method != nullptr) {
901 if (IsInheritedMethod(this, klass, *candidate_method)) {
902 return candidate_method;
903 } else {
904 uninherited_method = candidate_method;
905 break;
906 }
907 }
908 }
909
910 // Then search copied methods.
911 // If we found a method that's not inherited, stop the search in its declaring class.
912 ObjPtr<Class> end_klass = klass;
913 DCHECK_EQ(uninherited_method != nullptr, end_klass != nullptr);
914 // After we have searched the declared methods of the super-class chain,
915 // search copied methods which can contain methods from interfaces.
916 for (klass = this; klass != end_klass; klass = klass->GetSuperClass()) {
917 ArraySlice<ArtMethod> copied_methods = klass->GetCopiedMethodsSlice(pointer_size);
918 if (!copied_methods.empty() && name.empty()) {
919 name = dex_file.StringDataByIdx(method_id.name_idx_);
920 }
921 for (ArtMethod& method : copied_methods) {
922 if (method.GetNameView() == name && method.GetSignature() == signature) {
923 return &method; // No further check needed, copied methods are inherited by definition.
924 }
925 }
926 }
927 return uninherited_method; // Return the `uninherited_method` if any.
928 }
929
FindConstructor(std::string_view signature,PointerSize pointer_size)930 ArtMethod* Class::FindConstructor(std::string_view signature, PointerSize pointer_size) {
931 // Internal helper, never called on proxy classes. We can skip GetInterfaceMethodIfProxy().
932 DCHECK(!IsProxyClass());
933 std::string_view name("<init>");
934 for (ArtMethod& method : GetDirectMethodsSliceUnchecked(pointer_size)) {
935 if (method.GetName() == name && method.GetSignature() == signature) {
936 return &method;
937 }
938 }
939 return nullptr;
940 }
941
FindDeclaredDirectMethodByName(std::string_view name,PointerSize pointer_size)942 ArtMethod* Class::FindDeclaredDirectMethodByName(std::string_view name, PointerSize pointer_size) {
943 for (auto& method : GetDirectMethods(pointer_size)) {
944 ArtMethod* const np_method = method.GetInterfaceMethodIfProxy(pointer_size);
945 if (name == np_method->GetName()) {
946 return &method;
947 }
948 }
949 return nullptr;
950 }
951
FindDeclaredVirtualMethodByName(std::string_view name,PointerSize pointer_size)952 ArtMethod* Class::FindDeclaredVirtualMethodByName(std::string_view name, PointerSize pointer_size) {
953 for (auto& method : GetVirtualMethods(pointer_size)) {
954 ArtMethod* const np_method = method.GetInterfaceMethodIfProxy(pointer_size);
955 if (name == np_method->GetName()) {
956 return &method;
957 }
958 }
959 return nullptr;
960 }
961
FindVirtualMethodForInterfaceSuper(ArtMethod * method,PointerSize pointer_size)962 ArtMethod* Class::FindVirtualMethodForInterfaceSuper(ArtMethod* method, PointerSize pointer_size) {
963 DCHECK(method->GetDeclaringClass()->IsInterface());
964 DCHECK(IsInterface()) << "Should only be called on a interface class";
965 // Check if we have one defined on this interface first. This includes searching copied ones to
966 // get any conflict methods. Conflict methods are copied into each subtype from the supertype. We
967 // don't do any indirect method checks here.
968 for (ArtMethod& iface_method : GetVirtualMethods(pointer_size)) {
969 if (method->HasSameNameAndSignature(&iface_method)) {
970 return &iface_method;
971 }
972 }
973
974 std::vector<ArtMethod*> abstract_methods;
975 // Search through the IFTable for a working version. We don't need to check for conflicts
976 // because if there was one it would appear in this classes virtual_methods_ above.
977
978 Thread* self = Thread::Current();
979 StackHandleScope<2> hs(self);
980 MutableHandle<IfTable> iftable(hs.NewHandle(GetIfTable()));
981 MutableHandle<Class> iface(hs.NewHandle<Class>(nullptr));
982 size_t iftable_count = GetIfTableCount();
983 // Find the method. We don't need to check for conflicts because they would have been in the
984 // copied virtuals of this interface. Order matters, traverse in reverse topological order; most
985 // subtypiest interfaces get visited first.
986 for (size_t k = iftable_count; k != 0;) {
987 k--;
988 DCHECK_LT(k, iftable->Count());
989 iface.Assign(iftable->GetInterface(k));
990 // Iterate through every declared method on this interface. Each direct method's name/signature
991 // is unique so the order of the inner loop doesn't matter.
992 for (auto& method_iter : iface->GetDeclaredVirtualMethods(pointer_size)) {
993 ArtMethod* current_method = &method_iter;
994 if (current_method->HasSameNameAndSignature(method)) {
995 if (current_method->IsDefault()) {
996 // Handle JLS soft errors, a default method from another superinterface tree can
997 // "override" an abstract method(s) from another superinterface tree(s). To do this,
998 // ignore any [default] method which are dominated by the abstract methods we've seen so
999 // far. Check if overridden by any in abstract_methods. We do not need to check for
1000 // default_conflicts because we would hit those before we get to this loop.
1001 bool overridden = false;
1002 for (ArtMethod* possible_override : abstract_methods) {
1003 DCHECK(possible_override->HasSameNameAndSignature(current_method));
1004 if (iface->IsAssignableFrom(possible_override->GetDeclaringClass())) {
1005 overridden = true;
1006 break;
1007 }
1008 }
1009 if (!overridden) {
1010 return current_method;
1011 }
1012 } else {
1013 // Is not default.
1014 // This might override another default method. Just stash it for now.
1015 abstract_methods.push_back(current_method);
1016 }
1017 }
1018 }
1019 }
1020 // If we reach here we either never found any declaration of the method (in which case
1021 // 'abstract_methods' is empty or we found no non-overriden default methods in which case
1022 // 'abstract_methods' contains a number of abstract implementations of the methods. We choose one
1023 // of these arbitrarily.
1024 return abstract_methods.empty() ? nullptr : abstract_methods[0];
1025 }
1026
FindClassInitializer(PointerSize pointer_size)1027 ArtMethod* Class::FindClassInitializer(PointerSize pointer_size) {
1028 for (ArtMethod& method : GetDirectMethods(pointer_size)) {
1029 if (method.IsClassInitializer()) {
1030 DCHECK_STREQ(method.GetName(), "<clinit>");
1031 DCHECK_STREQ(method.GetSignature().ToString().c_str(), "()V");
1032 return &method;
1033 }
1034 }
1035 return nullptr;
1036 }
1037
FindFieldByNameAndType(const DexFile & dex_file,LengthPrefixedArray<ArtField> * fields,std::string_view name,std::string_view type)1038 static std::tuple<bool, ArtField*> FindFieldByNameAndType(const DexFile& dex_file,
1039 LengthPrefixedArray<ArtField>* fields,
1040 std::string_view name,
1041 std::string_view type)
1042 REQUIRES_SHARED(Locks::mutator_lock_) {
1043 DCHECK(fields != nullptr);
1044 DCHECK(!name.empty());
1045 DCHECK(!type.empty());
1046
1047 // Fields are sorted by class, then name, then type descriptor. This is verified in dex file
1048 // verifier. There can be multiple fields with the same name in the same class due to proguard.
1049 // Note: std::string_view::compare() uses lexicographical comparison and treats the `char` as
1050 // unsigned; for Modified-UTF-8 without embedded nulls this is consistent with the
1051 // CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues() ordering.
1052 auto get_field_id = [&](uint32_t mid) REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE
1053 -> const dex::FieldId& {
1054 ArtField& field = fields->At(mid);
1055 DCHECK(field.GetDexFile() == &dex_file);
1056 return dex_file.GetFieldId(field.GetDexFieldIndex());
1057 };
1058 auto name_cmp = [&](uint32_t mid) REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE {
1059 const dex::FieldId& field_id = get_field_id(mid);
1060 return name.compare(dex_file.GetFieldNameView(field_id));
1061 };
1062 auto type_cmp = [&](uint32_t mid) REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE {
1063 const dex::FieldId& field_id = get_field_id(mid);
1064 return type.compare(dex_file.GetTypeDescriptorView(dex_file.GetTypeId(field_id.type_idx_)));
1065 };
1066 auto get_name_idx = [&](uint32_t mid) REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE {
1067 const dex::FieldId& field_id = get_field_id(mid);
1068 return field_id.name_idx_;
1069 };
1070
1071 // Use binary search in the sorted fields.
1072 auto [success, mid] =
1073 ClassMemberBinarySearch(/*begin=*/ 0u, fields->size(), name_cmp, type_cmp, get_name_idx);
1074
1075 if (kIsDebugBuild) {
1076 ArtField* found = nullptr;
1077 for (ArtField& field : MakeIterationRangeFromLengthPrefixedArray(fields)) {
1078 if (name == field.GetName() && type == field.GetTypeDescriptor()) {
1079 found = &field;
1080 break;
1081 }
1082 }
1083
1084 ArtField* ret = success ? &fields->At(mid) : nullptr;
1085 CHECK_EQ(found, ret)
1086 << "Found " << ArtField::PrettyField(found) << " vs " << ArtField::PrettyField(ret);
1087 }
1088
1089 if (success) {
1090 return {true, &fields->At(mid)};
1091 }
1092
1093 return {false, nullptr};
1094 }
1095
FindDeclaredInstanceField(std::string_view name,std::string_view type)1096 ArtField* Class::FindDeclaredInstanceField(std::string_view name, std::string_view type) {
1097 // Binary search by name. Interfaces are not relevant because they can't contain instance fields.
1098 LengthPrefixedArray<ArtField>* ifields = GetIFieldsPtr();
1099 if (ifields == nullptr) {
1100 return nullptr;
1101 }
1102 DCHECK(!IsProxyClass());
1103 auto [success, field] = FindFieldByNameAndType(GetDexFile(), ifields, name, type);
1104 DCHECK_EQ(success, field != nullptr);
1105 return field;
1106 }
1107
FindDeclaredInstanceField(ObjPtr<DexCache> dex_cache,uint32_t dex_field_idx)1108 ArtField* Class::FindDeclaredInstanceField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) {
1109 if (GetDexCache() == dex_cache) {
1110 for (ArtField& field : GetIFields()) {
1111 if (field.GetDexFieldIndex() == dex_field_idx) {
1112 return &field;
1113 }
1114 }
1115 }
1116 return nullptr;
1117 }
1118
FindInstanceField(std::string_view name,std::string_view type)1119 ArtField* Class::FindInstanceField(std::string_view name, std::string_view type) {
1120 // Is the field in this class, or any of its superclasses?
1121 // Interfaces are not relevant because they can't contain instance fields.
1122 for (ObjPtr<Class> c = this; c != nullptr; c = c->GetSuperClass()) {
1123 ArtField* f = c->FindDeclaredInstanceField(name, type);
1124 if (f != nullptr) {
1125 return f;
1126 }
1127 }
1128 return nullptr;
1129 }
1130
FindDeclaredStaticField(std::string_view name,std::string_view type)1131 ArtField* Class::FindDeclaredStaticField(std::string_view name, std::string_view type) {
1132 DCHECK(!type.empty());
1133 LengthPrefixedArray<ArtField>* sfields = GetSFieldsPtr();
1134 if (sfields == nullptr) {
1135 return nullptr;
1136 }
1137 if (UNLIKELY(IsProxyClass())) {
1138 // Proxy fields do not have appropriate dex field indexes required by
1139 // `FindFieldByNameAndType()`. However, each proxy class has exactly
1140 // the same artificial fields created by the `ClassLinker`.
1141 DCHECK_EQ(sfields->size(), 2u);
1142 DCHECK_EQ(strcmp(sfields->At(0).GetName(), "interfaces"), 0);
1143 DCHECK_EQ(strcmp(sfields->At(0).GetTypeDescriptor(), "[Ljava/lang/Class;"), 0);
1144 DCHECK_EQ(strcmp(sfields->At(1).GetName(), "throws"), 0);
1145 DCHECK_EQ(strcmp(sfields->At(1).GetTypeDescriptor(), "[[Ljava/lang/Class;"), 0);
1146 if (name == "interfaces") {
1147 return (type == "[Ljava/lang/Class;") ? &sfields->At(0) : nullptr;
1148 } else if (name == "throws") {
1149 return (type == "[[Ljava/lang/Class;") ? &sfields->At(1) : nullptr;
1150 } else {
1151 return nullptr;
1152 }
1153 }
1154 auto [success, field] = FindFieldByNameAndType(GetDexFile(), sfields, name, type);
1155 DCHECK_EQ(success, field != nullptr);
1156 return field;
1157 }
1158
FindDeclaredStaticField(ObjPtr<DexCache> dex_cache,uint32_t dex_field_idx)1159 ArtField* Class::FindDeclaredStaticField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) {
1160 if (dex_cache == GetDexCache()) {
1161 for (ArtField& field : GetSFields()) {
1162 if (field.GetDexFieldIndex() == dex_field_idx) {
1163 return &field;
1164 }
1165 }
1166 }
1167 return nullptr;
1168 }
1169
GetDeclaredFields(Thread * self,bool public_only,bool force_resolve)1170 ObjPtr<mirror::ObjectArray<mirror::Field>> Class::GetDeclaredFields(
1171 Thread* self,
1172 bool public_only,
1173 bool force_resolve) REQUIRES_SHARED(Locks::mutator_lock_) {
1174 if (UNLIKELY(IsObsoleteObject())) {
1175 ThrowRuntimeException("Obsolete Object!");
1176 return nullptr;
1177 }
1178 StackHandleScope<1> hs(self);
1179 IterationRange<StrideIterator<ArtField>> ifields = GetIFields();
1180 IterationRange<StrideIterator<ArtField>> sfields = GetSFields();
1181 size_t array_size = NumInstanceFields() + NumStaticFields();
1182 auto hiddenapi_context = hiddenapi::GetReflectionCallerAccessContext(self);
1183 // Lets go subtract all the non discoverable fields.
1184 for (ArtField& field : ifields) {
1185 if (!IsDiscoverable(public_only, hiddenapi_context, &field)) {
1186 --array_size;
1187 }
1188 }
1189 for (ArtField& field : sfields) {
1190 if (!IsDiscoverable(public_only, hiddenapi_context, &field)) {
1191 --array_size;
1192 }
1193 }
1194 size_t array_idx = 0;
1195 auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
1196 self, GetClassRoot<mirror::ObjectArray<mirror::Field>>(), array_size));
1197 if (object_array == nullptr) {
1198 return nullptr;
1199 }
1200 for (ArtField& field : ifields) {
1201 if (IsDiscoverable(public_only, hiddenapi_context, &field)) {
1202 ObjPtr<mirror::Field> reflect_field =
1203 mirror::Field::CreateFromArtField(self, &field, force_resolve);
1204 if (reflect_field == nullptr) {
1205 if (kIsDebugBuild) {
1206 self->AssertPendingException();
1207 }
1208 // Maybe null due to OOME or type resolving exception.
1209 return nullptr;
1210 }
1211 // We're initializing a newly allocated object, so we do not need to record that under
1212 // a transaction. If the transaction is aborted, the whole object shall be unreachable.
1213 object_array->SetWithoutChecks</*kTransactionActive=*/ false,
1214 /*kCheckTransaction=*/ false>(
1215 array_idx++, reflect_field);
1216 }
1217 }
1218 for (ArtField& field : sfields) {
1219 if (IsDiscoverable(public_only, hiddenapi_context, &field)) {
1220 ObjPtr<mirror::Field> reflect_field =
1221 mirror::Field::CreateFromArtField(self, &field, force_resolve);
1222 if (reflect_field == nullptr) {
1223 if (kIsDebugBuild) {
1224 self->AssertPendingException();
1225 }
1226 return nullptr;
1227 }
1228 // We're initializing a newly allocated object, so we do not need to record that under
1229 // a transaction. If the transaction is aborted, the whole object shall be unreachable.
1230 object_array->SetWithoutChecks</*kTransactionActive=*/ false,
1231 /*kCheckTransaction=*/ false>(
1232 array_idx++, reflect_field);
1233 }
1234 }
1235 DCHECK_EQ(array_idx, array_size);
1236 return object_array.Get();
1237 }
1238
FindStaticField(std::string_view name,std::string_view type)1239 ArtField* Class::FindStaticField(std::string_view name, std::string_view type) {
1240 ScopedAssertNoThreadSuspension ants(__FUNCTION__);
1241 // Is the field in this class (or its interfaces), or any of its
1242 // superclasses (or their interfaces)?
1243 for (ObjPtr<Class> k = this; k != nullptr; k = k->GetSuperClass()) {
1244 // Is the field in this class?
1245 ArtField* f = k->FindDeclaredStaticField(name, type);
1246 if (f != nullptr) {
1247 return f;
1248 }
1249 // Is this field in any of this class' interfaces?
1250 for (uint32_t i = 0, num_interfaces = k->NumDirectInterfaces(); i != num_interfaces; ++i) {
1251 ObjPtr<Class> interface = k->GetDirectInterface(i);
1252 DCHECK(interface != nullptr);
1253 f = interface->FindStaticField(name, type);
1254 if (f != nullptr) {
1255 return f;
1256 }
1257 }
1258 }
1259 return nullptr;
1260 }
1261
1262 // Find a field using the JLS field resolution order.
1263 // Template arguments can be used to limit the search to either static or instance fields.
1264 // The search should be limited only if we know that a full search would yield a field of
1265 // the right type or no field at all. This can be known for field references in a method
1266 // if we have previously verified that method and did not find a field type mismatch.
1267 template <bool kSearchInstanceFields, bool kSearchStaticFields>
1268 ALWAYS_INLINE
FindFieldImpl(ObjPtr<mirror::Class> klass,ObjPtr<mirror::DexCache> dex_cache,uint32_t field_idx)1269 ArtField* FindFieldImpl(ObjPtr<mirror::Class> klass,
1270 ObjPtr<mirror::DexCache> dex_cache,
1271 uint32_t field_idx) REQUIRES_SHARED(Locks::mutator_lock_) {
1272 static_assert(kSearchInstanceFields || kSearchStaticFields);
1273
1274 // FIXME: Hijacking a proxy class by a custom class loader can break this assumption.
1275 DCHECK(!klass->IsProxyClass());
1276
1277 ScopedAssertNoThreadSuspension ants(__FUNCTION__);
1278
1279 // First try to find a declared field by `field_idx` if we have a `dex_cache` match.
1280 ObjPtr<DexCache> klass_dex_cache = klass->GetDexCache();
1281 if (klass_dex_cache == dex_cache) {
1282 // Lookup is always performed in the class referenced by the FieldId.
1283 DCHECK_EQ(klass->GetDexTypeIndex(),
1284 klass_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_);
1285 ArtField* f = kSearchInstanceFields
1286 ? klass->FindDeclaredInstanceField(klass_dex_cache, field_idx)
1287 : nullptr;
1288 if (kSearchStaticFields && f == nullptr) {
1289 f = klass->FindDeclaredStaticField(klass_dex_cache, field_idx);
1290 }
1291 if (f != nullptr) {
1292 return f;
1293 }
1294 }
1295
1296 const DexFile& dex_file = *dex_cache->GetDexFile();
1297 const dex::FieldId& field_id = dex_file.GetFieldId(field_idx);
1298
1299 std::string_view name; // Do not touch the dex file string data until actually needed.
1300 std::string_view type;
1301 auto ensure_name_and_type_initialized = [&]() REQUIRES_SHARED(Locks::mutator_lock_) {
1302 if (name.empty()) {
1303 name = dex_file.GetFieldNameView(field_id);
1304 type = dex_file.GetFieldTypeDescriptorView(field_id);
1305 }
1306 };
1307
1308 auto search_direct_interfaces = [&](ObjPtr<mirror::Class> k)
1309 REQUIRES_SHARED(Locks::mutator_lock_) {
1310 // TODO: The `FindStaticField()` performs a recursive search and it's possible to
1311 // construct interface hierarchies that make the time complexity exponential in depth.
1312 // Rewrite this with a `HashSet<mirror::Class*>` to mark classes we have already
1313 // searched for the field, so that we call `FindDeclaredStaticField()` only once
1314 // on each interface. And use a work queue to avoid unlimited recursion depth.
1315 // TODO: Once we call `FindDeclaredStaticField()` directly, use search by indexes
1316 // instead of strings if the interface's dex cache matches `dex_cache`. This shall
1317 // allow delaying the `ensure_name_and_type_initialized()` call further.
1318 uint32_t num_interfaces = k->NumDirectInterfaces();
1319 if (num_interfaces != 0u) {
1320 ensure_name_and_type_initialized();
1321 for (uint32_t i = 0; i != num_interfaces; ++i) {
1322 ObjPtr<Class> interface = k->GetDirectInterface(i);
1323 DCHECK(interface != nullptr);
1324 ArtField* f = interface->FindStaticField(name, type);
1325 if (f != nullptr) {
1326 return f;
1327 }
1328 }
1329 }
1330 return static_cast<ArtField*>(nullptr);
1331 };
1332
1333 auto find_field_by_name_and_type = [&](ObjPtr<mirror::Class> k, ObjPtr<DexCache> k_dex_cache)
1334 REQUIRES_SHARED(Locks::mutator_lock_) -> std::tuple<bool, ArtField*> {
1335 if ((!kSearchInstanceFields || k->GetIFieldsPtr() == nullptr) &&
1336 (!kSearchStaticFields || k->GetSFieldsPtr() == nullptr)) {
1337 return {false, nullptr};
1338 }
1339 ensure_name_and_type_initialized();
1340 const DexFile& k_dex_file = *k_dex_cache->GetDexFile();
1341 if (kSearchInstanceFields && k->GetIFieldsPtr() != nullptr) {
1342 auto [success, field] = FindFieldByNameAndType(k_dex_file, k->GetIFieldsPtr(), name, type);
1343 DCHECK_EQ(success, field != nullptr);
1344 if (success) {
1345 return {true, field};
1346 }
1347 }
1348 if (kSearchStaticFields && k->GetSFieldsPtr() != nullptr) {
1349 auto [success, field] = FindFieldByNameAndType(k_dex_file, k->GetSFieldsPtr(), name, type);
1350 DCHECK_EQ(success, field != nullptr);
1351 if (success) {
1352 return {true, field};
1353 }
1354 }
1355 return {false, nullptr};
1356 };
1357
1358 // If we had a dex cache mismatch, search declared fields by name and type.
1359 if (klass_dex_cache != dex_cache) {
1360 auto [success, field] = find_field_by_name_and_type(klass, klass_dex_cache);
1361 DCHECK_EQ(success, field != nullptr);
1362 if (success) {
1363 return field;
1364 }
1365 }
1366
1367 // Search direct interfaces for static fields.
1368 if (kSearchStaticFields) {
1369 ArtField* f = search_direct_interfaces(klass);
1370 if (f != nullptr) {
1371 return f;
1372 }
1373 }
1374
1375 // Continue searching in superclasses.
1376 for (ObjPtr<Class> k = klass->GetSuperClass(); k != nullptr; k = k->GetSuperClass()) {
1377 // Is the field in this class?
1378 ObjPtr<DexCache> k_dex_cache = k->GetDexCache();
1379 if (k_dex_cache == dex_cache) {
1380 // Matching dex_cache. We cannot compare the `field_idx` anymore because
1381 // the type index differs, so compare the name index and type index.
1382 if (kSearchInstanceFields) {
1383 for (ArtField& field : k->GetIFields()) {
1384 const dex::FieldId& other_field_id = dex_file.GetFieldId(field.GetDexFieldIndex());
1385 if (other_field_id.name_idx_ == field_id.name_idx_ &&
1386 other_field_id.type_idx_ == field_id.type_idx_) {
1387 return &field;
1388 }
1389 }
1390 }
1391 if (kSearchStaticFields) {
1392 for (ArtField& field : k->GetSFields()) {
1393 const dex::FieldId& other_field_id = dex_file.GetFieldId(field.GetDexFieldIndex());
1394 if (other_field_id.name_idx_ == field_id.name_idx_ &&
1395 other_field_id.type_idx_ == field_id.type_idx_) {
1396 return &field;
1397 }
1398 }
1399 }
1400 } else {
1401 auto [success, field] = find_field_by_name_and_type(k, k_dex_cache);
1402 DCHECK_EQ(success, field != nullptr);
1403 if (success) {
1404 return field;
1405 }
1406 }
1407 if (kSearchStaticFields) {
1408 // Is this field in any of this class' interfaces?
1409 ArtField* f = search_direct_interfaces(k);
1410 if (f != nullptr) {
1411 return f;
1412 }
1413 }
1414 }
1415 return nullptr;
1416 }
1417
1418 FLATTEN
FindField(ObjPtr<mirror::DexCache> dex_cache,uint32_t field_idx)1419 ArtField* Class::FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) {
1420 return FindFieldImpl</*kSearchInstanceFields=*/ true,
1421 /*kSearchStaticFields*/ true>(this, dex_cache, field_idx);
1422 }
1423
1424 FLATTEN
FindInstanceField(ObjPtr<mirror::DexCache> dex_cache,uint32_t field_idx)1425 ArtField* Class::FindInstanceField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) {
1426 return FindFieldImpl</*kSearchInstanceFields=*/ true,
1427 /*kSearchStaticFields*/ false>(this, dex_cache, field_idx);
1428 }
1429
1430 FLATTEN
FindStaticField(ObjPtr<mirror::DexCache> dex_cache,uint32_t field_idx)1431 ArtField* Class::FindStaticField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) {
1432 return FindFieldImpl</*kSearchInstanceFields=*/ false,
1433 /*kSearchStaticFields*/ true>(this, dex_cache, field_idx);
1434 }
1435
ClearSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size)1436 void Class::ClearSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size) {
1437 DCHECK(IsVerified());
1438 for (auto& m : GetMethods(pointer_size)) {
1439 if (!m.IsNative() && m.IsInvokable()) {
1440 m.ClearSkipAccessChecks();
1441 }
1442 }
1443 }
1444
ClearMustCountLocksFlagOnAllMethods(PointerSize pointer_size)1445 void Class::ClearMustCountLocksFlagOnAllMethods(PointerSize pointer_size) {
1446 DCHECK(IsVerified());
1447 for (auto& m : GetMethods(pointer_size)) {
1448 if (!m.IsNative() && m.IsInvokable()) {
1449 m.ClearMustCountLocks();
1450 }
1451 }
1452 }
1453
ClearDontCompileFlagOnAllMethods(PointerSize pointer_size)1454 void Class::ClearDontCompileFlagOnAllMethods(PointerSize pointer_size) {
1455 DCHECK(IsVerified());
1456 for (auto& m : GetMethods(pointer_size)) {
1457 if (!m.IsNative() && m.IsInvokable()) {
1458 m.ClearDontCompile();
1459 }
1460 }
1461 }
1462
SetSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size)1463 void Class::SetSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size) {
1464 DCHECK(IsVerified());
1465 for (auto& m : GetMethods(pointer_size)) {
1466 if (!m.IsNative() && m.IsInvokable()) {
1467 m.SetSkipAccessChecks();
1468 }
1469 }
1470 }
1471
GetDescriptor(std::string * storage)1472 const char* Class::GetDescriptor(std::string* storage) {
1473 size_t dim = 0u;
1474 ObjPtr<mirror::Class> klass = this;
1475 while (klass->IsArrayClass()) {
1476 ++dim;
1477 // No read barrier needed, we're reading a chain of constant references for comparison
1478 // with null. Then we follow up below with reading constant references to read constant
1479 // primitive data in both proxy and non-proxy paths. See ReadBarrierOption.
1480 klass = klass->GetComponentType<kDefaultVerifyFlags, kWithoutReadBarrier>();
1481 }
1482 if (klass->IsProxyClass()) {
1483 // No read barrier needed, the `name` field is constant for proxy classes and
1484 // the contents of the String are also constant. See ReadBarrierOption.
1485 ObjPtr<mirror::String> name = klass->GetName<kVerifyNone, kWithoutReadBarrier>();
1486 DCHECK(name != nullptr);
1487 *storage = DotToDescriptor(name->ToModifiedUtf8().c_str());
1488 } else {
1489 const char* descriptor;
1490 if (klass->IsPrimitive()) {
1491 descriptor = Primitive::Descriptor(klass->GetPrimitiveType());
1492 } else {
1493 const DexFile& dex_file = klass->GetDexFile();
1494 const dex::TypeId& type_id = dex_file.GetTypeId(klass->GetDexTypeIndex());
1495 descriptor = dex_file.GetTypeDescriptor(type_id);
1496 }
1497 if (dim == 0) {
1498 return descriptor;
1499 }
1500 *storage = descriptor;
1501 }
1502 storage->insert(0u, dim, '[');
1503 return storage->c_str();
1504 }
1505
GetClassDef()1506 const dex::ClassDef* Class::GetClassDef() {
1507 uint16_t class_def_idx = GetDexClassDefIndex();
1508 if (class_def_idx == DexFile::kDexNoIndex16) {
1509 return nullptr;
1510 }
1511 return &GetDexFile().GetClassDef(class_def_idx);
1512 }
1513
GetDirectInterfaceTypeIdx(uint32_t idx)1514 dex::TypeIndex Class::GetDirectInterfaceTypeIdx(uint32_t idx) {
1515 DCHECK(!IsPrimitive());
1516 DCHECK(!IsArrayClass());
1517 return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
1518 }
1519
GetDirectInterface(uint32_t idx)1520 ObjPtr<Class> Class::GetDirectInterface(uint32_t idx) {
1521 DCHECK(!IsPrimitive());
1522 if (IsArrayClass()) {
1523 ObjPtr<IfTable> iftable = GetIfTable();
1524 DCHECK(iftable != nullptr);
1525 DCHECK_EQ(iftable->Count(), 2u);
1526 DCHECK_LT(idx, 2u);
1527 ObjPtr<Class> interface = iftable->GetInterface(idx);
1528 DCHECK(interface != nullptr);
1529 return interface;
1530 } else if (IsProxyClass()) {
1531 ObjPtr<ObjectArray<Class>> interfaces = GetProxyInterfaces();
1532 DCHECK(interfaces != nullptr);
1533 return interfaces->Get(idx);
1534 } else {
1535 dex::TypeIndex type_idx = GetDirectInterfaceTypeIdx(idx);
1536 ObjPtr<Class> interface = Runtime::Current()->GetClassLinker()->LookupResolvedType(
1537 type_idx, GetDexCache(), GetClassLoader());
1538 return interface;
1539 }
1540 }
1541
ResolveDirectInterface(Thread * self,Handle<Class> klass,uint32_t idx)1542 ObjPtr<Class> Class::ResolveDirectInterface(Thread* self, Handle<Class> klass, uint32_t idx) {
1543 ObjPtr<Class> interface = klass->GetDirectInterface(idx);
1544 if (interface == nullptr) {
1545 DCHECK(!klass->IsArrayClass());
1546 DCHECK(!klass->IsProxyClass());
1547 dex::TypeIndex type_idx = klass->GetDirectInterfaceTypeIdx(idx);
1548 interface = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, klass.Get());
1549 CHECK_IMPLIES(interface == nullptr, self->IsExceptionPending());
1550 }
1551 return interface;
1552 }
1553
GetCommonSuperClass(Handle<Class> klass)1554 ObjPtr<Class> Class::GetCommonSuperClass(Handle<Class> klass) {
1555 DCHECK(klass != nullptr);
1556 DCHECK(!klass->IsInterface());
1557 DCHECK(!IsInterface());
1558 ObjPtr<Class> common_super_class = this;
1559 while (!common_super_class->IsAssignableFrom(klass.Get())) {
1560 ObjPtr<Class> old_common = common_super_class;
1561 common_super_class = old_common->GetSuperClass();
1562 DCHECK(common_super_class != nullptr) << old_common->PrettyClass();
1563 }
1564 return common_super_class;
1565 }
1566
GetSourceFile()1567 const char* Class::GetSourceFile() {
1568 const DexFile& dex_file = GetDexFile();
1569 const dex::ClassDef* dex_class_def = GetClassDef();
1570 if (dex_class_def == nullptr) {
1571 // Generated classes have no class def.
1572 return nullptr;
1573 }
1574 return dex_file.GetSourceFile(*dex_class_def);
1575 }
1576
GetLocation()1577 std::string Class::GetLocation() {
1578 ObjPtr<DexCache> dex_cache = GetDexCache();
1579 if (dex_cache != nullptr && !IsProxyClass()) {
1580 return dex_cache->GetLocation()->ToModifiedUtf8();
1581 }
1582 // Arrays and proxies are generated and have no corresponding dex file location.
1583 return "generated class";
1584 }
1585
GetInterfaceTypeList()1586 const dex::TypeList* Class::GetInterfaceTypeList() {
1587 const dex::ClassDef* class_def = GetClassDef();
1588 if (class_def == nullptr) {
1589 return nullptr;
1590 }
1591 return GetDexFile().GetInterfacesList(*class_def);
1592 }
1593
PopulateEmbeddedVTable(PointerSize pointer_size)1594 void Class::PopulateEmbeddedVTable(PointerSize pointer_size) {
1595 ObjPtr<PointerArray> table = GetVTableDuringLinking();
1596 CHECK(table != nullptr) << PrettyClass();
1597 const size_t table_length = table->GetLength();
1598 SetEmbeddedVTableLength(table_length);
1599 for (size_t i = 0; i < table_length; i++) {
1600 SetEmbeddedVTableEntry(i, table->GetElementPtrSize<ArtMethod*>(i, pointer_size), pointer_size);
1601 }
1602 // Keep java.lang.Object class's vtable around for since it's easier
1603 // to be reused by array classes during their linking.
1604 if (!IsObjectClass()) {
1605 SetVTable(nullptr);
1606 }
1607 }
1608
1609 class ReadBarrierOnNativeRootsVisitor {
1610 public:
operator ()(ObjPtr<Object> obj ATTRIBUTE_UNUSED,MemberOffset offset ATTRIBUTE_UNUSED,bool is_static ATTRIBUTE_UNUSED) const1611 void operator()(ObjPtr<Object> obj ATTRIBUTE_UNUSED,
1612 MemberOffset offset ATTRIBUTE_UNUSED,
1613 bool is_static ATTRIBUTE_UNUSED) const {}
1614
VisitRootIfNonNull(CompressedReference<Object> * root) const1615 void VisitRootIfNonNull(CompressedReference<Object>* root) const
1616 REQUIRES_SHARED(Locks::mutator_lock_) {
1617 if (!root->IsNull()) {
1618 VisitRoot(root);
1619 }
1620 }
1621
VisitRoot(CompressedReference<Object> * root) const1622 void VisitRoot(CompressedReference<Object>* root) const
1623 REQUIRES_SHARED(Locks::mutator_lock_) {
1624 ObjPtr<Object> old_ref = root->AsMirrorPtr();
1625 ObjPtr<Object> new_ref = ReadBarrier::BarrierForRoot(root);
1626 if (old_ref != new_ref) {
1627 // Update the field atomically. This may fail if mutator updates before us, but it's ok.
1628 auto* atomic_root =
1629 reinterpret_cast<Atomic<CompressedReference<Object>>*>(root);
1630 atomic_root->CompareAndSetStrongSequentiallyConsistent(
1631 CompressedReference<Object>::FromMirrorPtr(old_ref.Ptr()),
1632 CompressedReference<Object>::FromMirrorPtr(new_ref.Ptr()));
1633 }
1634 }
1635 };
1636
1637 // The pre-fence visitor for Class::CopyOf().
1638 class CopyClassVisitor {
1639 public:
CopyClassVisitor(Thread * self,Handle<Class> * orig,size_t new_length,size_t copy_bytes,ImTable * imt,PointerSize pointer_size)1640 CopyClassVisitor(Thread* self,
1641 Handle<Class>* orig,
1642 size_t new_length,
1643 size_t copy_bytes,
1644 ImTable* imt,
1645 PointerSize pointer_size)
1646 : self_(self), orig_(orig), new_length_(new_length),
1647 copy_bytes_(copy_bytes), imt_(imt), pointer_size_(pointer_size) {
1648 }
1649
operator ()(ObjPtr<Object> obj,size_t usable_size ATTRIBUTE_UNUSED) const1650 void operator()(ObjPtr<Object> obj, size_t usable_size ATTRIBUTE_UNUSED) const
1651 REQUIRES_SHARED(Locks::mutator_lock_) {
1652 StackHandleScope<1> hs(self_);
1653 Handle<mirror::Class> h_new_class_obj(hs.NewHandle(obj->AsClass()));
1654 Object::CopyObject(h_new_class_obj.Get(), orig_->Get(), copy_bytes_);
1655 Class::SetStatus(h_new_class_obj, ClassStatus::kResolving, self_);
1656 h_new_class_obj->PopulateEmbeddedVTable(pointer_size_);
1657 h_new_class_obj->SetImt(imt_, pointer_size_);
1658 h_new_class_obj->SetClassSize(new_length_);
1659 // Visit all of the references to make sure there is no from space references in the native
1660 // roots.
1661 h_new_class_obj->Object::VisitReferences(ReadBarrierOnNativeRootsVisitor(), VoidFunctor());
1662 }
1663
1664 private:
1665 Thread* const self_;
1666 Handle<Class>* const orig_;
1667 const size_t new_length_;
1668 const size_t copy_bytes_;
1669 ImTable* imt_;
1670 const PointerSize pointer_size_;
1671 DISALLOW_COPY_AND_ASSIGN(CopyClassVisitor);
1672 };
1673
CopyOf(Handle<Class> h_this,Thread * self,int32_t new_length,ImTable * imt,PointerSize pointer_size)1674 ObjPtr<Class> Class::CopyOf(Handle<Class> h_this,
1675 Thread* self,
1676 int32_t new_length,
1677 ImTable* imt,
1678 PointerSize pointer_size) {
1679 DCHECK_GE(new_length, static_cast<int32_t>(sizeof(Class)));
1680 // We may get copied by a compacting GC.
1681 Runtime* runtime = Runtime::Current();
1682 gc::Heap* heap = runtime->GetHeap();
1683 // The num_bytes (3rd param) is sizeof(Class) as opposed to SizeOf()
1684 // to skip copying the tail part that we will overwrite here.
1685 CopyClassVisitor visitor(self, &h_this, new_length, sizeof(Class), imt, pointer_size);
1686 ObjPtr<mirror::Class> java_lang_Class = GetClassRoot<mirror::Class>(runtime->GetClassLinker());
1687 ObjPtr<Object> new_class = kMovingClasses ?
1688 heap->AllocObject(self, java_lang_Class, new_length, visitor) :
1689 heap->AllocNonMovableObject(self, java_lang_Class, new_length, visitor);
1690 if (UNLIKELY(new_class == nullptr)) {
1691 self->AssertPendingOOMException();
1692 return nullptr;
1693 }
1694 return new_class->AsClass();
1695 }
1696
ProxyDescriptorEquals(const char * match)1697 bool Class::ProxyDescriptorEquals(const char* match) {
1698 DCHECK(IsProxyClass());
1699 std::string storage;
1700 const char* descriptor = GetDescriptor(&storage);
1701 DCHECK(descriptor == storage.c_str());
1702 return storage == match;
1703 }
1704
UpdateHashForProxyClass(uint32_t hash,ObjPtr<mirror::Class> proxy_class)1705 uint32_t Class::UpdateHashForProxyClass(uint32_t hash, ObjPtr<mirror::Class> proxy_class) {
1706 // No read barrier needed, the `name` field is constant for proxy classes and
1707 // the contents of the String are also constant. See ReadBarrierOption.
1708 // Note: The `proxy_class` can be a from-space reference.
1709 DCHECK(proxy_class->IsProxyClass());
1710 ObjPtr<mirror::String> name = proxy_class->GetName<kVerifyNone, kWithoutReadBarrier>();
1711 DCHECK(name != nullptr);
1712 // Update hash for characters we would get from `DotToDescriptor(name->ToModifiedUtf8())`.
1713 DCHECK_NE(name->GetLength(), 0);
1714 DCHECK_NE(name->CharAt(0), '[');
1715 hash = UpdateModifiedUtf8Hash(hash, 'L');
1716 if (name->IsCompressed()) {
1717 std::string_view dot_name(reinterpret_cast<const char*>(name->GetValueCompressed()),
1718 name->GetLength());
1719 for (char c : dot_name) {
1720 hash = UpdateModifiedUtf8Hash(hash, (c != '.') ? c : '/');
1721 }
1722 } else {
1723 std::string dot_name = name->ToModifiedUtf8();
1724 for (char c : dot_name) {
1725 hash = UpdateModifiedUtf8Hash(hash, (c != '.') ? c : '/');
1726 }
1727 }
1728 hash = UpdateModifiedUtf8Hash(hash, ';');
1729 return hash;
1730 }
1731
1732 // TODO: Move this to java_lang_Class.cc?
GetDeclaredConstructor(Thread * self,Handle<ObjectArray<Class>> args,PointerSize pointer_size)1733 ArtMethod* Class::GetDeclaredConstructor(
1734 Thread* self, Handle<ObjectArray<Class>> args, PointerSize pointer_size) {
1735 for (auto& m : GetDirectMethods(pointer_size)) {
1736 // Skip <clinit> which is a static constructor, as well as non constructors.
1737 if (m.IsStatic() || !m.IsConstructor()) {
1738 continue;
1739 }
1740 // May cause thread suspension and exceptions.
1741 if (m.GetInterfaceMethodIfProxy(kRuntimePointerSize)->EqualParameters(args)) {
1742 return &m;
1743 }
1744 if (UNLIKELY(self->IsExceptionPending())) {
1745 return nullptr;
1746 }
1747 }
1748 return nullptr;
1749 }
1750
Depth()1751 uint32_t Class::Depth() {
1752 uint32_t depth = 0;
1753 for (ObjPtr<Class> cls = this; cls->GetSuperClass() != nullptr; cls = cls->GetSuperClass()) {
1754 depth++;
1755 }
1756 return depth;
1757 }
1758
FindTypeIndexInOtherDexFile(const DexFile & dex_file)1759 dex::TypeIndex Class::FindTypeIndexInOtherDexFile(const DexFile& dex_file) {
1760 std::string temp;
1761 const dex::TypeId* type_id = dex_file.FindTypeId(GetDescriptor(&temp));
1762 return (type_id == nullptr) ? dex::TypeIndex() : dex_file.GetIndexForTypeId(*type_id);
1763 }
1764
1765 ALWAYS_INLINE
IsMethodPreferredOver(ArtMethod * orig_method,bool orig_method_hidden,ArtMethod * new_method,bool new_method_hidden)1766 static bool IsMethodPreferredOver(ArtMethod* orig_method,
1767 bool orig_method_hidden,
1768 ArtMethod* new_method,
1769 bool new_method_hidden) {
1770 DCHECK(new_method != nullptr);
1771
1772 // Is this the first result?
1773 if (orig_method == nullptr) {
1774 return true;
1775 }
1776
1777 // Original method is hidden, the new one is not?
1778 if (orig_method_hidden && !new_method_hidden) {
1779 return true;
1780 }
1781
1782 // We iterate over virtual methods first and then over direct ones,
1783 // so we can never be in situation where `orig_method` is direct and
1784 // `new_method` is virtual.
1785 DCHECK_IMPLIES(orig_method->IsDirect(), new_method->IsDirect());
1786
1787 // Original method is synthetic, the new one is not?
1788 if (orig_method->IsSynthetic() && !new_method->IsSynthetic()) {
1789 return true;
1790 }
1791
1792 return false;
1793 }
1794
1795 template <PointerSize kPointerSize>
GetDeclaredMethodInternal(Thread * self,ObjPtr<Class> klass,ObjPtr<String> name,ObjPtr<ObjectArray<Class>> args,const std::function<hiddenapi::AccessContext ()> & fn_get_access_context)1796 ObjPtr<Method> Class::GetDeclaredMethodInternal(
1797 Thread* self,
1798 ObjPtr<Class> klass,
1799 ObjPtr<String> name,
1800 ObjPtr<ObjectArray<Class>> args,
1801 const std::function<hiddenapi::AccessContext()>& fn_get_access_context) {
1802 // Covariant return types (or smali) permit the class to define
1803 // multiple methods with the same name and parameter types.
1804 // Prefer (in decreasing order of importance):
1805 // 1) non-hidden method over hidden
1806 // 2) virtual methods over direct
1807 // 3) non-synthetic methods over synthetic
1808 // We never return miranda methods that were synthesized by the runtime.
1809 StackHandleScope<3> hs(self);
1810 auto h_method_name = hs.NewHandle(name);
1811 if (UNLIKELY(h_method_name == nullptr)) {
1812 ThrowNullPointerException("name == null");
1813 return nullptr;
1814 }
1815 auto h_args = hs.NewHandle(args);
1816 Handle<Class> h_klass = hs.NewHandle(klass);
1817 constexpr hiddenapi::AccessMethod access_method = hiddenapi::AccessMethod::kNone;
1818 ArtMethod* result = nullptr;
1819 bool result_hidden = false;
1820 for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) {
1821 if (m.IsMiranda()) {
1822 continue;
1823 }
1824 ArtMethod* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
1825 if (!np_method->NameEquals(h_method_name.Get())) {
1826 continue;
1827 }
1828 // `ArtMethod::EqualParameters()` may throw when resolving types.
1829 if (!np_method->EqualParameters(h_args)) {
1830 if (UNLIKELY(self->IsExceptionPending())) {
1831 return nullptr;
1832 }
1833 continue;
1834 }
1835 bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);
1836 if (!m_hidden && !m.IsSynthetic()) {
1837 // Non-hidden, virtual, non-synthetic. Best possible result, exit early.
1838 return Method::CreateFromArtMethod<kPointerSize>(self, &m);
1839 } else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
1840 // Remember as potential result.
1841 result = &m;
1842 result_hidden = m_hidden;
1843 }
1844 }
1845
1846 if ((result != nullptr) && !result_hidden) {
1847 // We have not found a non-hidden, virtual, non-synthetic method, but
1848 // if we have found a non-hidden, virtual, synthetic method, we cannot
1849 // do better than that later.
1850 DCHECK(!result->IsDirect());
1851 DCHECK(result->IsSynthetic());
1852 } else {
1853 for (auto& m : h_klass->GetDirectMethods(kPointerSize)) {
1854 auto modifiers = m.GetAccessFlags();
1855 if ((modifiers & kAccConstructor) != 0) {
1856 continue;
1857 }
1858 ArtMethod* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
1859 if (!np_method->NameEquals(h_method_name.Get())) {
1860 continue;
1861 }
1862 // `ArtMethod::EqualParameters()` may throw when resolving types.
1863 if (!np_method->EqualParameters(h_args)) {
1864 if (UNLIKELY(self->IsExceptionPending())) {
1865 return nullptr;
1866 }
1867 continue;
1868 }
1869 DCHECK(!m.IsMiranda()); // Direct methods cannot be miranda methods.
1870 bool m_hidden = hiddenapi::ShouldDenyAccessToMember(&m, fn_get_access_context, access_method);
1871 if (!m_hidden && !m.IsSynthetic()) {
1872 // Non-hidden, direct, non-synthetic. Any virtual result could only have been
1873 // hidden, therefore this is the best possible match. Exit now.
1874 DCHECK((result == nullptr) || result_hidden);
1875 return Method::CreateFromArtMethod<kPointerSize>(self, &m);
1876 } else if (IsMethodPreferredOver(result, result_hidden, &m, m_hidden)) {
1877 // Remember as potential result.
1878 result = &m;
1879 result_hidden = m_hidden;
1880 }
1881 }
1882 }
1883
1884 return result != nullptr
1885 ? Method::CreateFromArtMethod<kPointerSize>(self, result)
1886 : nullptr;
1887 }
1888
1889 template
1890 ObjPtr<Method> Class::GetDeclaredMethodInternal<PointerSize::k32>(
1891 Thread* self,
1892 ObjPtr<Class> klass,
1893 ObjPtr<String> name,
1894 ObjPtr<ObjectArray<Class>> args,
1895 const std::function<hiddenapi::AccessContext()>& fn_get_access_context);
1896 template
1897 ObjPtr<Method> Class::GetDeclaredMethodInternal<PointerSize::k64>(
1898 Thread* self,
1899 ObjPtr<Class> klass,
1900 ObjPtr<String> name,
1901 ObjPtr<ObjectArray<Class>> args,
1902 const std::function<hiddenapi::AccessContext()>& fn_get_access_context);
1903
1904 template <PointerSize kPointerSize>
GetDeclaredConstructorInternal(Thread * self,ObjPtr<Class> klass,ObjPtr<ObjectArray<Class>> args)1905 ObjPtr<Constructor> Class::GetDeclaredConstructorInternal(
1906 Thread* self,
1907 ObjPtr<Class> klass,
1908 ObjPtr<ObjectArray<Class>> args) {
1909 StackHandleScope<1> hs(self);
1910 ArtMethod* result = klass->GetDeclaredConstructor(self, hs.NewHandle(args), kPointerSize);
1911 return result != nullptr
1912 ? Constructor::CreateFromArtMethod<kPointerSize>(self, result)
1913 : nullptr;
1914 }
1915
1916 // Constructor::CreateFromArtMethod<kTransactionActive>(self, result)
1917
1918 template
1919 ObjPtr<Constructor> Class::GetDeclaredConstructorInternal<PointerSize::k32>(
1920 Thread* self,
1921 ObjPtr<Class> klass,
1922 ObjPtr<ObjectArray<Class>> args);
1923 template
1924 ObjPtr<Constructor> Class::GetDeclaredConstructorInternal<PointerSize::k64>(
1925 Thread* self,
1926 ObjPtr<Class> klass,
1927 ObjPtr<ObjectArray<Class>> args);
1928
GetInnerClassFlags(Handle<Class> h_this,int32_t default_value)1929 int32_t Class::GetInnerClassFlags(Handle<Class> h_this, int32_t default_value) {
1930 if (h_this->IsProxyClass() || h_this->GetDexCache() == nullptr) {
1931 return default_value;
1932 }
1933 uint32_t flags;
1934 if (!annotations::GetInnerClassFlags(h_this, &flags)) {
1935 return default_value;
1936 }
1937 return flags;
1938 }
1939
SetObjectSizeAllocFastPath(uint32_t new_object_size)1940 void Class::SetObjectSizeAllocFastPath(uint32_t new_object_size) {
1941 if (Runtime::Current()->IsActiveTransaction()) {
1942 SetField32Volatile<true>(ObjectSizeAllocFastPathOffset(), new_object_size);
1943 } else {
1944 SetField32Volatile<false>(ObjectSizeAllocFastPathOffset(), new_object_size);
1945 }
1946 }
1947
PrettyDescriptor(ObjPtr<mirror::Class> klass)1948 std::string Class::PrettyDescriptor(ObjPtr<mirror::Class> klass) {
1949 if (klass == nullptr) {
1950 return "null";
1951 }
1952 return klass->PrettyDescriptor();
1953 }
1954
PrettyDescriptor()1955 std::string Class::PrettyDescriptor() {
1956 std::string temp;
1957 return art::PrettyDescriptor(GetDescriptor(&temp));
1958 }
1959
PrettyClass(ObjPtr<mirror::Class> c)1960 std::string Class::PrettyClass(ObjPtr<mirror::Class> c) {
1961 if (c == nullptr) {
1962 return "null";
1963 }
1964 return c->PrettyClass();
1965 }
1966
PrettyClass()1967 std::string Class::PrettyClass() {
1968 std::string result;
1969 if (IsObsoleteObject()) {
1970 result += "(Obsolete)";
1971 }
1972 if (IsRetired()) {
1973 result += "(Retired)";
1974 }
1975 result += "java.lang.Class<";
1976 result += PrettyDescriptor();
1977 result += ">";
1978 return result;
1979 }
1980
PrettyClassAndClassLoader(ObjPtr<mirror::Class> c)1981 std::string Class::PrettyClassAndClassLoader(ObjPtr<mirror::Class> c) {
1982 if (c == nullptr) {
1983 return "null";
1984 }
1985 return c->PrettyClassAndClassLoader();
1986 }
1987
PrettyClassAndClassLoader()1988 std::string Class::PrettyClassAndClassLoader() {
1989 std::string result;
1990 result += "java.lang.Class<";
1991 result += PrettyDescriptor();
1992 result += ",";
1993 result += mirror::Object::PrettyTypeOf(GetClassLoader());
1994 // TODO: add an identifying hash value for the loader
1995 result += ">";
1996 return result;
1997 }
1998
GetAccessFlagsDCheck()1999 template<VerifyObjectFlags kVerifyFlags> void Class::GetAccessFlagsDCheck() {
2000 // Check class is loaded/retired or this is java.lang.String that has a
2001 // circularity issue during loading the names of its members
2002 DCHECK(IsIdxLoaded<kVerifyFlags>() || IsRetired<kVerifyFlags>() ||
2003 IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ||
2004 this == GetClassRoot<String>())
2005 << "IsIdxLoaded=" << IsIdxLoaded<kVerifyFlags>()
2006 << " IsRetired=" << IsRetired<kVerifyFlags>()
2007 << " IsErroneous=" <<
2008 IsErroneous<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>()
2009 << " IsString=" << (this == GetClassRoot<String>())
2010 << " status= " << GetStatus<kVerifyFlags>()
2011 << " descriptor=" << PrettyDescriptor();
2012 }
2013 // Instantiate the common cases.
2014 template void Class::GetAccessFlagsDCheck<kVerifyNone>();
2015 template void Class::GetAccessFlagsDCheck<kVerifyThis>();
2016 template void Class::GetAccessFlagsDCheck<kVerifyReads>();
2017 template void Class::GetAccessFlagsDCheck<kVerifyWrites>();
2018 template void Class::GetAccessFlagsDCheck<kVerifyAll>();
2019
GetMethodIds()2020 ObjPtr<Object> Class::GetMethodIds() {
2021 ObjPtr<ClassExt> ext(GetExtData());
2022 if (ext.IsNull()) {
2023 return nullptr;
2024 } else {
2025 return ext->GetJMethodIDs();
2026 }
2027 }
EnsureMethodIds(Handle<Class> h_this)2028 bool Class::EnsureMethodIds(Handle<Class> h_this) {
2029 DCHECK_NE(Runtime::Current()->GetJniIdType(), JniIdType::kPointer) << "JNI Ids are pointers!";
2030 Thread* self = Thread::Current();
2031 ObjPtr<ClassExt> ext(EnsureExtDataPresent(h_this, self));
2032 if (ext.IsNull()) {
2033 self->AssertPendingOOMException();
2034 return false;
2035 }
2036 return ext->EnsureJMethodIDsArrayPresent(h_this->NumMethods());
2037 }
2038
GetStaticFieldIds()2039 ObjPtr<Object> Class::GetStaticFieldIds() {
2040 ObjPtr<ClassExt> ext(GetExtData());
2041 if (ext.IsNull()) {
2042 return nullptr;
2043 } else {
2044 return ext->GetStaticJFieldIDs();
2045 }
2046 }
EnsureStaticFieldIds(Handle<Class> h_this)2047 bool Class::EnsureStaticFieldIds(Handle<Class> h_this) {
2048 DCHECK_NE(Runtime::Current()->GetJniIdType(), JniIdType::kPointer) << "JNI Ids are pointers!";
2049 Thread* self = Thread::Current();
2050 ObjPtr<ClassExt> ext(EnsureExtDataPresent(h_this, self));
2051 if (ext.IsNull()) {
2052 self->AssertPendingOOMException();
2053 return false;
2054 }
2055 return ext->EnsureStaticJFieldIDsArrayPresent(h_this->NumStaticFields());
2056 }
GetInstanceFieldIds()2057 ObjPtr<Object> Class::GetInstanceFieldIds() {
2058 ObjPtr<ClassExt> ext(GetExtData());
2059 if (ext.IsNull()) {
2060 return nullptr;
2061 } else {
2062 return ext->GetInstanceJFieldIDs();
2063 }
2064 }
EnsureInstanceFieldIds(Handle<Class> h_this)2065 bool Class::EnsureInstanceFieldIds(Handle<Class> h_this) {
2066 DCHECK_NE(Runtime::Current()->GetJniIdType(), JniIdType::kPointer) << "JNI Ids are pointers!";
2067 Thread* self = Thread::Current();
2068 ObjPtr<ClassExt> ext(EnsureExtDataPresent(h_this, self));
2069 if (ext.IsNull()) {
2070 self->AssertPendingOOMException();
2071 return false;
2072 }
2073 return ext->EnsureInstanceJFieldIDsArrayPresent(h_this->NumInstanceFields());
2074 }
2075
GetStaticFieldIdOffset(ArtField * field)2076 size_t Class::GetStaticFieldIdOffset(ArtField* field) {
2077 DCHECK_LT(reinterpret_cast<uintptr_t>(field),
2078 reinterpret_cast<uintptr_t>(&*GetSFieldsPtr()->end()))
2079 << "field not part of the current class. " << field->PrettyField() << " class is "
2080 << PrettyClass();
2081 DCHECK_GE(reinterpret_cast<uintptr_t>(field),
2082 reinterpret_cast<uintptr_t>(&*GetSFieldsPtr()->begin()))
2083 << "field not part of the current class. " << field->PrettyField() << " class is "
2084 << PrettyClass();
2085 uintptr_t start = reinterpret_cast<uintptr_t>(&GetSFieldsPtr()->At(0));
2086 uintptr_t fld = reinterpret_cast<uintptr_t>(field);
2087 size_t res = (fld - start) / sizeof(ArtField);
2088 DCHECK_EQ(&GetSFieldsPtr()->At(res), field)
2089 << "Incorrect field computation expected: " << field->PrettyField()
2090 << " got: " << GetSFieldsPtr()->At(res).PrettyField();
2091 return res;
2092 }
2093
GetInstanceFieldIdOffset(ArtField * field)2094 size_t Class::GetInstanceFieldIdOffset(ArtField* field) {
2095 DCHECK_LT(reinterpret_cast<uintptr_t>(field),
2096 reinterpret_cast<uintptr_t>(&*GetIFieldsPtr()->end()))
2097 << "field not part of the current class. " << field->PrettyField() << " class is "
2098 << PrettyClass();
2099 DCHECK_GE(reinterpret_cast<uintptr_t>(field),
2100 reinterpret_cast<uintptr_t>(&*GetIFieldsPtr()->begin()))
2101 << "field not part of the current class. " << field->PrettyField() << " class is "
2102 << PrettyClass();
2103 uintptr_t start = reinterpret_cast<uintptr_t>(&GetIFieldsPtr()->At(0));
2104 uintptr_t fld = reinterpret_cast<uintptr_t>(field);
2105 size_t res = (fld - start) / sizeof(ArtField);
2106 DCHECK_EQ(&GetIFieldsPtr()->At(res), field)
2107 << "Incorrect field computation expected: " << field->PrettyField()
2108 << " got: " << GetIFieldsPtr()->At(res).PrettyField();
2109 return res;
2110 }
2111
GetMethodIdOffset(ArtMethod * method,PointerSize pointer_size)2112 size_t Class::GetMethodIdOffset(ArtMethod* method, PointerSize pointer_size) {
2113 DCHECK(GetMethodsSlice(kRuntimePointerSize).Contains(method))
2114 << "method not part of the current class. " << method->PrettyMethod() << "( " << reinterpret_cast<void*>(method) << ")" << " class is "
2115 << PrettyClass() << [&]() REQUIRES_SHARED(Locks::mutator_lock_) {
2116 std::ostringstream os;
2117 os << " Methods are [";
2118 for (ArtMethod& m : GetMethodsSlice(kRuntimePointerSize)) {
2119 os << m.PrettyMethod() << "( " << reinterpret_cast<void*>(&m) << "), ";
2120 }
2121 os << "]";
2122 return os.str();
2123 }();
2124 uintptr_t start = reinterpret_cast<uintptr_t>(&*GetMethodsSlice(pointer_size).begin());
2125 uintptr_t fld = reinterpret_cast<uintptr_t>(method);
2126 size_t art_method_size = ArtMethod::Size(pointer_size);
2127 size_t art_method_align = ArtMethod::Alignment(pointer_size);
2128 size_t res = (fld - start) / art_method_size;
2129 DCHECK_EQ(&GetMethodsPtr()->At(res, art_method_size, art_method_align), method)
2130 << "Incorrect method computation expected: " << method->PrettyMethod()
2131 << " got: " << GetMethodsPtr()->At(res, art_method_size, art_method_align).PrettyMethod();
2132 return res;
2133 }
2134
FindAccessibleInterfaceMethod(ArtMethod * implementation_method,PointerSize pointer_size)2135 ArtMethod* Class::FindAccessibleInterfaceMethod(ArtMethod* implementation_method,
2136 PointerSize pointer_size)
2137 REQUIRES_SHARED(Locks::mutator_lock_) {
2138 ObjPtr<mirror::IfTable> iftable = GetIfTable();
2139 for (int32_t i = 0, iftable_count = iftable->Count(); i < iftable_count; ++i) {
2140 ObjPtr<mirror::PointerArray> methods = iftable->GetMethodArrayOrNull(i);
2141 if (methods == nullptr) {
2142 continue;
2143 }
2144 for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
2145 if (implementation_method == methods->GetElementPtrSize<ArtMethod*>(j, pointer_size)) {
2146 ObjPtr<mirror::Class> iface = iftable->GetInterface(i);
2147 ArtMethod* interface_method = &iface->GetVirtualMethodsSlice(pointer_size)[j];
2148 // If the interface method is part of the public SDK, return it.
2149 if ((hiddenapi::GetRuntimeFlags(interface_method) & kAccPublicApi) != 0) {
2150 hiddenapi::ApiList api_list(hiddenapi::detail::GetDexFlags(interface_method));
2151 // The kAccPublicApi flag is also used as an optimization to avoid
2152 // other hiddenapi checks to always go on the slow path. Therefore, we
2153 // need to check here if the method is in the SDK list.
2154 if (api_list.IsSdkApi()) {
2155 return interface_method;
2156 }
2157 }
2158 }
2159 }
2160 }
2161 return nullptr;
2162 }
2163
2164
2165 } // namespace mirror
2166 } // namespace art
2167