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