xref: /aosp_15_r20/art/runtime/mirror/dex_cache-inl.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2013 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 #ifndef ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "dex_cache.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "art_field.h"
25*795d594fSAndroid Build Coastguard Worker #include "art_method.h"
26*795d594fSAndroid Build Coastguard Worker #include "base/atomic_pair.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/casts.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
29*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
30*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
31*795d594fSAndroid Build Coastguard Worker #include "gc_root-inl.h"
32*795d594fSAndroid Build Coastguard Worker #include "linear_alloc-inl.h"
33*795d594fSAndroid Build Coastguard Worker #include "mirror/call_site.h"
34*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
35*795d594fSAndroid Build Coastguard Worker #include "mirror/method_type.h"
36*795d594fSAndroid Build Coastguard Worker #include "obj_ptr.h"
37*795d594fSAndroid Build Coastguard Worker #include "object-inl.h"
38*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
39*795d594fSAndroid Build Coastguard Worker #include "write_barrier-inl.h"
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker #include <atomic>
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
44*795d594fSAndroid Build Coastguard Worker namespace mirror {
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker template<typename DexCachePair>
InitializeArray(std::atomic<DexCachePair> * array)47*795d594fSAndroid Build Coastguard Worker static void InitializeArray(std::atomic<DexCachePair>* array) {
48*795d594fSAndroid Build Coastguard Worker   DexCachePair::Initialize(array);
49*795d594fSAndroid Build Coastguard Worker }
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker template<typename T>
InitializeArray(T *)52*795d594fSAndroid Build Coastguard Worker static void InitializeArray(T*) {
53*795d594fSAndroid Build Coastguard Worker   // Nothing to do.
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker template<typename T>
AllocArray(MemberOffset obj_offset,size_t num,LinearAllocKind kind,bool startup)57*795d594fSAndroid Build Coastguard Worker T* DexCache::AllocArray(MemberOffset obj_offset, size_t num, LinearAllocKind kind, bool startup) {
58*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
59*795d594fSAndroid Build Coastguard Worker   mirror::DexCache* dex_cache = this;
60*795d594fSAndroid Build Coastguard Worker   if (gUseReadBarrier && self->GetIsGcMarking()) {
61*795d594fSAndroid Build Coastguard Worker     // Several code paths use DexCache without read-barrier for performance.
62*795d594fSAndroid Build Coastguard Worker     // We have to check the "to-space" object here to avoid allocating twice.
63*795d594fSAndroid Build Coastguard Worker     dex_cache = reinterpret_cast<DexCache*>(ReadBarrier::Mark(this));
64*795d594fSAndroid Build Coastguard Worker   }
65*795d594fSAndroid Build Coastguard Worker   // DON'T USE 'this' from now on.
66*795d594fSAndroid Build Coastguard Worker   Runtime* runtime = Runtime::Current();
67*795d594fSAndroid Build Coastguard Worker   // Note: in the 1002-notify-startup test, the startup linear alloc can become null
68*795d594fSAndroid Build Coastguard Worker   // concurrently, even if the runtime is marked at startup. Therefore we should only
69*795d594fSAndroid Build Coastguard Worker   // fetch it once here.
70*795d594fSAndroid Build Coastguard Worker   LinearAlloc* startup_linear_alloc = runtime->GetStartupLinearAlloc();
71*795d594fSAndroid Build Coastguard Worker   LinearAlloc* alloc = (startup && startup_linear_alloc != nullptr)
72*795d594fSAndroid Build Coastguard Worker       ? startup_linear_alloc
73*795d594fSAndroid Build Coastguard Worker       : runtime->GetClassLinker()->GetOrCreateAllocatorForClassLoader(GetClassLoader());
74*795d594fSAndroid Build Coastguard Worker   MutexLock mu(self, *Locks::dex_cache_lock_);  // Avoid allocation by multiple threads.
75*795d594fSAndroid Build Coastguard Worker   T* array = dex_cache->GetFieldPtr64<T*>(obj_offset);
76*795d594fSAndroid Build Coastguard Worker   if (array != nullptr) {
77*795d594fSAndroid Build Coastguard Worker     DCHECK(alloc->Contains(array));
78*795d594fSAndroid Build Coastguard Worker     return array;  // Other thread just allocated the array.
79*795d594fSAndroid Build Coastguard Worker   }
80*795d594fSAndroid Build Coastguard Worker   array = reinterpret_cast<T*>(alloc->AllocAlign16(self, RoundUp(num * sizeof(T), 16), kind));
81*795d594fSAndroid Build Coastguard Worker   InitializeArray(array);  // Ensure other threads see the array initialized.
82*795d594fSAndroid Build Coastguard Worker   dex_cache->SetField64Volatile<false, false>(obj_offset, reinterpret_cast64<uint64_t>(array));
83*795d594fSAndroid Build Coastguard Worker   return array;
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker 
86*795d594fSAndroid Build Coastguard Worker template <typename T>
DexCachePair(ObjPtr<T> object,uint32_t index)87*795d594fSAndroid Build Coastguard Worker inline DexCachePair<T>::DexCachePair(ObjPtr<T> object, uint32_t index)
88*795d594fSAndroid Build Coastguard Worker     : object(object), index(index) {}
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker template <typename T>
GetObjectForIndex(uint32_t idx)91*795d594fSAndroid Build Coastguard Worker inline T* DexCachePair<T>::GetObjectForIndex(uint32_t idx) {
92*795d594fSAndroid Build Coastguard Worker   if (idx != index) {
93*795d594fSAndroid Build Coastguard Worker     return nullptr;
94*795d594fSAndroid Build Coastguard Worker   }
95*795d594fSAndroid Build Coastguard Worker   DCHECK(!object.IsNull());
96*795d594fSAndroid Build Coastguard Worker   return object.Read();
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker 
99*795d594fSAndroid Build Coastguard Worker template <typename T>
Initialize(std::atomic<DexCachePair<T>> * dex_cache)100*795d594fSAndroid Build Coastguard Worker inline void DexCachePair<T>::Initialize(std::atomic<DexCachePair<T>>* dex_cache) {
101*795d594fSAndroid Build Coastguard Worker   DexCachePair<T> first_elem;
102*795d594fSAndroid Build Coastguard Worker   first_elem.object = GcRoot<T>(nullptr);
103*795d594fSAndroid Build Coastguard Worker   first_elem.index = InvalidIndexForSlot(0);
104*795d594fSAndroid Build Coastguard Worker   dex_cache[0].store(first_elem, std::memory_order_relaxed);
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker template <typename T>
Initialize(std::atomic<NativeDexCachePair<T>> * dex_cache)108*795d594fSAndroid Build Coastguard Worker inline void NativeDexCachePair<T>::Initialize(std::atomic<NativeDexCachePair<T>>* dex_cache) {
109*795d594fSAndroid Build Coastguard Worker   NativeDexCachePair<T> first_elem;
110*795d594fSAndroid Build Coastguard Worker   first_elem.object = nullptr;
111*795d594fSAndroid Build Coastguard Worker   first_elem.index = InvalidIndexForSlot(0);
112*795d594fSAndroid Build Coastguard Worker 
113*795d594fSAndroid Build Coastguard Worker   auto* array = reinterpret_cast<AtomicPair<uintptr_t>*>(dex_cache);
114*795d594fSAndroid Build Coastguard Worker   AtomicPair<uintptr_t> v(first_elem.index, reinterpret_cast<size_t>(first_elem.object));
115*795d594fSAndroid Build Coastguard Worker   AtomicPairStoreRelease(&array[0], v);
116*795d594fSAndroid Build Coastguard Worker }
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker template <typename T>
Set(uint32_t index,T * value)119*795d594fSAndroid Build Coastguard Worker inline void GcRootArray<T>::Set(uint32_t index, T* value) {
120*795d594fSAndroid Build Coastguard Worker   GcRoot<T> root(value);
121*795d594fSAndroid Build Coastguard Worker   entries_[index].store(root, std::memory_order_relaxed);
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker 
124*795d594fSAndroid Build Coastguard Worker template <typename T>
Get(uint32_t index)125*795d594fSAndroid Build Coastguard Worker inline T* GcRootArray<T>::Get(uint32_t index) {
126*795d594fSAndroid Build Coastguard Worker   return entries_[index].load(std::memory_order_relaxed).Read();
127*795d594fSAndroid Build Coastguard Worker }
128*795d594fSAndroid Build Coastguard Worker 
ClassSize(PointerSize pointer_size)129*795d594fSAndroid Build Coastguard Worker inline uint32_t DexCache::ClassSize(PointerSize pointer_size) {
130*795d594fSAndroid Build Coastguard Worker   const uint32_t vtable_entries = Object::kVTableLength;
131*795d594fSAndroid Build Coastguard Worker   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, 0, pointer_size);
132*795d594fSAndroid Build Coastguard Worker }
133*795d594fSAndroid Build Coastguard Worker 
GetResolvedString(dex::StringIndex string_idx)134*795d594fSAndroid Build Coastguard Worker inline String* DexCache::GetResolvedString(dex::StringIndex string_idx) {
135*795d594fSAndroid Build Coastguard Worker   return GetStringsEntry(string_idx.index_);
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker 
SetResolvedString(dex::StringIndex string_idx,ObjPtr<String> resolved)138*795d594fSAndroid Build Coastguard Worker inline void DexCache::SetResolvedString(dex::StringIndex string_idx, ObjPtr<String> resolved) {
139*795d594fSAndroid Build Coastguard Worker   DCHECK(resolved != nullptr);
140*795d594fSAndroid Build Coastguard Worker   SetStringsEntry(string_idx.index_, resolved.Ptr());
141*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
142*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(runtime->IsActiveTransaction())) {
143*795d594fSAndroid Build Coastguard Worker     DCHECK(runtime->IsAotCompiler());
144*795d594fSAndroid Build Coastguard Worker     runtime->GetClassLinker()->RecordResolveString(this, string_idx);
145*795d594fSAndroid Build Coastguard Worker   }
146*795d594fSAndroid Build Coastguard Worker   // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
147*795d594fSAndroid Build Coastguard Worker   WriteBarrier::ForEveryFieldWrite(this);
148*795d594fSAndroid Build Coastguard Worker }
149*795d594fSAndroid Build Coastguard Worker 
ClearString(dex::StringIndex string_idx)150*795d594fSAndroid Build Coastguard Worker inline void DexCache::ClearString(dex::StringIndex string_idx) {
151*795d594fSAndroid Build Coastguard Worker   DCHECK(Runtime::Current()->IsAotCompiler());
152*795d594fSAndroid Build Coastguard Worker   auto* array = GetStringsArray();
153*795d594fSAndroid Build Coastguard Worker   if (array != nullptr) {
154*795d594fSAndroid Build Coastguard Worker     array->Set(string_idx.index_, nullptr);
155*795d594fSAndroid Build Coastguard Worker   }
156*795d594fSAndroid Build Coastguard Worker   auto* strings = GetStrings();
157*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(strings == nullptr)) {
158*795d594fSAndroid Build Coastguard Worker     return;
159*795d594fSAndroid Build Coastguard Worker   }
160*795d594fSAndroid Build Coastguard Worker   strings->Clear(string_idx.index_);
161*795d594fSAndroid Build Coastguard Worker }
162*795d594fSAndroid Build Coastguard Worker 
GetResolvedType(dex::TypeIndex type_idx)163*795d594fSAndroid Build Coastguard Worker inline Class* DexCache::GetResolvedType(dex::TypeIndex type_idx) {
164*795d594fSAndroid Build Coastguard Worker   return GetResolvedTypesEntry(type_idx.index_);
165*795d594fSAndroid Build Coastguard Worker }
166*795d594fSAndroid Build Coastguard Worker 
ClearResolvedType(dex::TypeIndex type_idx)167*795d594fSAndroid Build Coastguard Worker inline void DexCache::ClearResolvedType(dex::TypeIndex type_idx) {
168*795d594fSAndroid Build Coastguard Worker   DCHECK(Runtime::Current()->IsAotCompiler());
169*795d594fSAndroid Build Coastguard Worker   auto* array = GetResolvedTypesArray();
170*795d594fSAndroid Build Coastguard Worker   if (array != nullptr) {
171*795d594fSAndroid Build Coastguard Worker     array->Set(type_idx.index_, nullptr);
172*795d594fSAndroid Build Coastguard Worker   }
173*795d594fSAndroid Build Coastguard Worker   auto* resolved_types = GetResolvedTypes();
174*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(resolved_types == nullptr)) {
175*795d594fSAndroid Build Coastguard Worker     return;
176*795d594fSAndroid Build Coastguard Worker   }
177*795d594fSAndroid Build Coastguard Worker   resolved_types->Clear(type_idx.index_);
178*795d594fSAndroid Build Coastguard Worker }
179*795d594fSAndroid Build Coastguard Worker 
GetResolvedMethodType(dex::ProtoIndex proto_idx)180*795d594fSAndroid Build Coastguard Worker inline MethodType* DexCache::GetResolvedMethodType(dex::ProtoIndex proto_idx) {
181*795d594fSAndroid Build Coastguard Worker   return GetResolvedMethodTypesEntry(proto_idx.index_);
182*795d594fSAndroid Build Coastguard Worker }
183*795d594fSAndroid Build Coastguard Worker 
SetResolvedMethodType(dex::ProtoIndex proto_idx,MethodType * resolved)184*795d594fSAndroid Build Coastguard Worker inline void DexCache::SetResolvedMethodType(dex::ProtoIndex proto_idx, MethodType* resolved) {
185*795d594fSAndroid Build Coastguard Worker   DCHECK(resolved != nullptr);
186*795d594fSAndroid Build Coastguard Worker   SetResolvedMethodTypesEntry(proto_idx.index_, resolved);
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker   Runtime* const runtime = Runtime::Current();
189*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(runtime->IsActiveTransaction())) {
190*795d594fSAndroid Build Coastguard Worker     DCHECK(runtime->IsAotCompiler());
191*795d594fSAndroid Build Coastguard Worker     runtime->GetClassLinker()->RecordResolveMethodType(this, proto_idx);
192*795d594fSAndroid Build Coastguard Worker   }
193*795d594fSAndroid Build Coastguard Worker   // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
194*795d594fSAndroid Build Coastguard Worker   WriteBarrier::ForEveryFieldWrite(this);
195*795d594fSAndroid Build Coastguard Worker }
196*795d594fSAndroid Build Coastguard Worker 
ClearMethodType(dex::ProtoIndex proto_idx)197*795d594fSAndroid Build Coastguard Worker inline void DexCache::ClearMethodType(dex::ProtoIndex proto_idx) {
198*795d594fSAndroid Build Coastguard Worker   DCHECK(Runtime::Current()->IsAotCompiler());
199*795d594fSAndroid Build Coastguard Worker   auto* array = GetResolvedMethodTypesArray();
200*795d594fSAndroid Build Coastguard Worker   if (array != nullptr) {
201*795d594fSAndroid Build Coastguard Worker     array->Set(proto_idx.index_, nullptr);
202*795d594fSAndroid Build Coastguard Worker   }
203*795d594fSAndroid Build Coastguard Worker   auto* methods = GetResolvedMethodTypes();
204*795d594fSAndroid Build Coastguard Worker   if (methods == nullptr) {
205*795d594fSAndroid Build Coastguard Worker     return;
206*795d594fSAndroid Build Coastguard Worker   }
207*795d594fSAndroid Build Coastguard Worker   methods->Clear(proto_idx.index_);
208*795d594fSAndroid Build Coastguard Worker }
209*795d594fSAndroid Build Coastguard Worker 
GetResolvedCallSite(uint32_t call_site_idx)210*795d594fSAndroid Build Coastguard Worker inline CallSite* DexCache::GetResolvedCallSite(uint32_t call_site_idx) {
211*795d594fSAndroid Build Coastguard Worker   DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
212*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(call_site_idx, GetDexFile()->NumCallSiteIds());
213*795d594fSAndroid Build Coastguard Worker   GcRootArray<CallSite>* call_sites = GetResolvedCallSites();
214*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(call_sites == nullptr)) {
215*795d594fSAndroid Build Coastguard Worker     return nullptr;
216*795d594fSAndroid Build Coastguard Worker   }
217*795d594fSAndroid Build Coastguard Worker   Atomic<GcRoot<mirror::CallSite>>* target = call_sites->GetGcRoot(call_site_idx);
218*795d594fSAndroid Build Coastguard Worker   return target->load(std::memory_order_seq_cst).Read();
219*795d594fSAndroid Build Coastguard Worker }
220*795d594fSAndroid Build Coastguard Worker 
SetResolvedCallSite(uint32_t call_site_idx,ObjPtr<CallSite> call_site)221*795d594fSAndroid Build Coastguard Worker inline ObjPtr<CallSite> DexCache::SetResolvedCallSite(uint32_t call_site_idx,
222*795d594fSAndroid Build Coastguard Worker                                                       ObjPtr<CallSite> call_site) {
223*795d594fSAndroid Build Coastguard Worker   DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
224*795d594fSAndroid Build Coastguard Worker   DCHECK_LT(call_site_idx, GetDexFile()->NumCallSiteIds());
225*795d594fSAndroid Build Coastguard Worker 
226*795d594fSAndroid Build Coastguard Worker   GcRoot<mirror::CallSite> null_call_site(nullptr);
227*795d594fSAndroid Build Coastguard Worker   GcRoot<mirror::CallSite> candidate(call_site);
228*795d594fSAndroid Build Coastguard Worker   GcRootArray<CallSite>* call_sites = GetResolvedCallSites();
229*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(call_sites == nullptr)) {
230*795d594fSAndroid Build Coastguard Worker     call_sites = AllocateResolvedCallSites();
231*795d594fSAndroid Build Coastguard Worker   }
232*795d594fSAndroid Build Coastguard Worker   Atomic<GcRoot<mirror::CallSite>>* target = call_sites->GetGcRoot(call_site_idx);
233*795d594fSAndroid Build Coastguard Worker 
234*795d594fSAndroid Build Coastguard Worker   // The first assignment for a given call site wins.
235*795d594fSAndroid Build Coastguard Worker   if (target->CompareAndSetStrongSequentiallyConsistent(null_call_site, candidate)) {
236*795d594fSAndroid Build Coastguard Worker     // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
237*795d594fSAndroid Build Coastguard Worker     WriteBarrier::ForEveryFieldWrite(this);
238*795d594fSAndroid Build Coastguard Worker     return call_site;
239*795d594fSAndroid Build Coastguard Worker   } else {
240*795d594fSAndroid Build Coastguard Worker     return target->load(std::memory_order_relaxed).Read();
241*795d594fSAndroid Build Coastguard Worker   }
242*795d594fSAndroid Build Coastguard Worker }
243*795d594fSAndroid Build Coastguard Worker 
GetResolvedField(uint32_t field_idx)244*795d594fSAndroid Build Coastguard Worker inline ArtField* DexCache::GetResolvedField(uint32_t field_idx) {
245*795d594fSAndroid Build Coastguard Worker   return GetResolvedFieldsEntry(field_idx);
246*795d594fSAndroid Build Coastguard Worker }
247*795d594fSAndroid Build Coastguard Worker 
SetResolvedField(uint32_t field_idx,ArtField * field)248*795d594fSAndroid Build Coastguard Worker inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field) {
249*795d594fSAndroid Build Coastguard Worker   SetResolvedFieldsEntry(field_idx, field);
250*795d594fSAndroid Build Coastguard Worker }
251*795d594fSAndroid Build Coastguard Worker 
GetResolvedMethod(uint32_t method_idx)252*795d594fSAndroid Build Coastguard Worker inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx) {
253*795d594fSAndroid Build Coastguard Worker   return GetResolvedMethodsEntry(method_idx);
254*795d594fSAndroid Build Coastguard Worker }
255*795d594fSAndroid Build Coastguard Worker 
SetResolvedMethod(uint32_t method_idx,ArtMethod * method)256*795d594fSAndroid Build Coastguard Worker inline void DexCache::SetResolvedMethod(uint32_t method_idx, ArtMethod* method) {
257*795d594fSAndroid Build Coastguard Worker   SetResolvedMethodsEntry(method_idx, method);
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker 
260*795d594fSAndroid Build Coastguard Worker template <ReadBarrierOption kReadBarrierOption,
261*795d594fSAndroid Build Coastguard Worker           typename Visitor,
262*795d594fSAndroid Build Coastguard Worker           typename T>
VisitDexCachePairs(T * array,size_t num_pairs,const Visitor & visitor)263*795d594fSAndroid Build Coastguard Worker inline void VisitDexCachePairs(T* array,
264*795d594fSAndroid Build Coastguard Worker                                size_t num_pairs,
265*795d594fSAndroid Build Coastguard Worker                                const Visitor& visitor)
266*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
267*795d594fSAndroid Build Coastguard Worker   // Check both the data pointer and count since the array might be initialized
268*795d594fSAndroid Build Coastguard Worker   // concurrently on other thread, and we might observe just one of the values.
269*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; array != nullptr && i < num_pairs; ++i) {
270*795d594fSAndroid Build Coastguard Worker     auto source = array->GetPair(i);
271*795d594fSAndroid Build Coastguard Worker     // NOTE: We need the "template" keyword here to avoid a compilation
272*795d594fSAndroid Build Coastguard Worker     // failure. GcRoot<T> is a template argument-dependent type and we need to
273*795d594fSAndroid Build Coastguard Worker     // tell the compiler to treat "Read" as a template rather than a field or
274*795d594fSAndroid Build Coastguard Worker     // function. Otherwise, on encountering the "<" token, the compiler would
275*795d594fSAndroid Build Coastguard Worker     // treat "Read" as a field.
276*795d594fSAndroid Build Coastguard Worker     auto const before = source.object.template Read<kReadBarrierOption>();
277*795d594fSAndroid Build Coastguard Worker     visitor.VisitRootIfNonNull(source.object.AddressWithoutBarrier());
278*795d594fSAndroid Build Coastguard Worker     if (source.object.template Read<kReadBarrierOption>() != before) {
279*795d594fSAndroid Build Coastguard Worker       array->SetPair(i, source);
280*795d594fSAndroid Build Coastguard Worker     }
281*795d594fSAndroid Build Coastguard Worker   }
282*795d594fSAndroid Build Coastguard Worker }
283*795d594fSAndroid Build Coastguard Worker 
284*795d594fSAndroid Build Coastguard Worker template <typename Visitor>
VisitDexCachePairRoots(Visitor & visitor,DexCachePair<Object> * pairs_begin,DexCachePair<Object> * pairs_end)285*795d594fSAndroid Build Coastguard Worker void DexCache::VisitDexCachePairRoots(Visitor& visitor,
286*795d594fSAndroid Build Coastguard Worker                                       DexCachePair<Object>* pairs_begin,
287*795d594fSAndroid Build Coastguard Worker                                       DexCachePair<Object>* pairs_end) {
288*795d594fSAndroid Build Coastguard Worker   for (; pairs_begin < pairs_end; pairs_begin++) {
289*795d594fSAndroid Build Coastguard Worker     visitor.VisitRootIfNonNull(pairs_begin->object.AddressWithoutBarrier());
290*795d594fSAndroid Build Coastguard Worker   }
291*795d594fSAndroid Build Coastguard Worker }
292*795d594fSAndroid Build Coastguard Worker 
293*795d594fSAndroid Build Coastguard Worker template <bool kVisitNativeRoots,
294*795d594fSAndroid Build Coastguard Worker           VerifyObjectFlags kVerifyFlags,
295*795d594fSAndroid Build Coastguard Worker           ReadBarrierOption kReadBarrierOption,
296*795d594fSAndroid Build Coastguard Worker           typename Visitor>
VisitReferences(ObjPtr<Class> klass,const Visitor & visitor)297*795d594fSAndroid Build Coastguard Worker inline void DexCache::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
298*795d594fSAndroid Build Coastguard Worker   // Visit instance fields first.
299*795d594fSAndroid Build Coastguard Worker   VisitInstanceFieldsReferences<kVerifyFlags>(klass, visitor);
300*795d594fSAndroid Build Coastguard Worker   // Visit arrays after.
301*795d594fSAndroid Build Coastguard Worker   if (kVisitNativeRoots) {
302*795d594fSAndroid Build Coastguard Worker     VisitNativeRoots<kVerifyFlags, kReadBarrierOption>(visitor);
303*795d594fSAndroid Build Coastguard Worker   }
304*795d594fSAndroid Build Coastguard Worker }
305*795d594fSAndroid Build Coastguard Worker 
306*795d594fSAndroid Build Coastguard Worker template <VerifyObjectFlags kVerifyFlags,
307*795d594fSAndroid Build Coastguard Worker           ReadBarrierOption kReadBarrierOption,
308*795d594fSAndroid Build Coastguard Worker           typename Visitor>
VisitNativeRoots(const Visitor & visitor)309*795d594fSAndroid Build Coastguard Worker inline void DexCache::VisitNativeRoots(const Visitor& visitor) {
310*795d594fSAndroid Build Coastguard Worker   VisitDexCachePairs<kReadBarrierOption, Visitor>(
311*795d594fSAndroid Build Coastguard Worker       GetStrings<kVerifyFlags>(), NumStrings<kVerifyFlags>(), visitor);
312*795d594fSAndroid Build Coastguard Worker 
313*795d594fSAndroid Build Coastguard Worker   VisitDexCachePairs<kReadBarrierOption, Visitor>(
314*795d594fSAndroid Build Coastguard Worker       GetResolvedTypes<kVerifyFlags>(), NumResolvedTypes<kVerifyFlags>(), visitor);
315*795d594fSAndroid Build Coastguard Worker 
316*795d594fSAndroid Build Coastguard Worker   VisitDexCachePairs<kReadBarrierOption, Visitor>(
317*795d594fSAndroid Build Coastguard Worker       GetResolvedMethodTypes<kVerifyFlags>(), NumResolvedMethodTypes<kVerifyFlags>(), visitor);
318*795d594fSAndroid Build Coastguard Worker 
319*795d594fSAndroid Build Coastguard Worker   GcRootArray<mirror::CallSite>* resolved_call_sites = GetResolvedCallSites<kVerifyFlags>();
320*795d594fSAndroid Build Coastguard Worker   size_t num_call_sites = NumResolvedCallSites<kVerifyFlags>();
321*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; resolved_call_sites != nullptr && i != num_call_sites; ++i) {
322*795d594fSAndroid Build Coastguard Worker     visitor.VisitRootIfNonNull(resolved_call_sites->GetGcRootAddress(i)->AddressWithoutBarrier());
323*795d594fSAndroid Build Coastguard Worker   }
324*795d594fSAndroid Build Coastguard Worker 
325*795d594fSAndroid Build Coastguard Worker   // Dex cache arrays can be reset and cleared during app startup. Assert we do not get
326*795d594fSAndroid Build Coastguard Worker   // suspended to ensure the arrays are not deallocated.
327*795d594fSAndroid Build Coastguard Worker   ScopedAssertNoThreadSuspension soants("dex caches");
328*795d594fSAndroid Build Coastguard Worker   GcRootArray<mirror::Class>* resolved_types = GetResolvedTypesArray<kVerifyFlags>();
329*795d594fSAndroid Build Coastguard Worker   size_t num_resolved_types = NumResolvedTypesArray<kVerifyFlags>();
330*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; resolved_types != nullptr && i != num_resolved_types; ++i) {
331*795d594fSAndroid Build Coastguard Worker     visitor.VisitRootIfNonNull(resolved_types->GetGcRootAddress(i)->AddressWithoutBarrier());
332*795d594fSAndroid Build Coastguard Worker   }
333*795d594fSAndroid Build Coastguard Worker 
334*795d594fSAndroid Build Coastguard Worker   GcRootArray<mirror::String>* resolved_strings = GetStringsArray<kVerifyFlags>();
335*795d594fSAndroid Build Coastguard Worker   size_t num_resolved_strings = NumStringsArray<kVerifyFlags>();
336*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; resolved_strings != nullptr && i != num_resolved_strings; ++i) {
337*795d594fSAndroid Build Coastguard Worker     visitor.VisitRootIfNonNull(resolved_strings->GetGcRootAddress(i)->AddressWithoutBarrier());
338*795d594fSAndroid Build Coastguard Worker   }
339*795d594fSAndroid Build Coastguard Worker 
340*795d594fSAndroid Build Coastguard Worker   GcRootArray<mirror::MethodType>* resolved_method_types =
341*795d594fSAndroid Build Coastguard Worker       GetResolvedMethodTypesArray<kVerifyFlags>();
342*795d594fSAndroid Build Coastguard Worker   size_t num_resolved_method_types = NumResolvedMethodTypesArray<kVerifyFlags>();
343*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; resolved_method_types != nullptr && i != num_resolved_method_types; ++i) {
344*795d594fSAndroid Build Coastguard Worker     visitor.VisitRootIfNonNull(resolved_method_types->GetGcRootAddress(i)->AddressWithoutBarrier());
345*795d594fSAndroid Build Coastguard Worker   }
346*795d594fSAndroid Build Coastguard Worker }
347*795d594fSAndroid Build Coastguard Worker 
348*795d594fSAndroid Build Coastguard Worker template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetLocation()349*795d594fSAndroid Build Coastguard Worker inline ObjPtr<String> DexCache::GetLocation() {
350*795d594fSAndroid Build Coastguard Worker   return GetFieldObject<String, kVerifyFlags, kReadBarrierOption>(
351*795d594fSAndroid Build Coastguard Worker       OFFSET_OF_OBJECT_MEMBER(DexCache, location_));
352*795d594fSAndroid Build Coastguard Worker }
353*795d594fSAndroid Build Coastguard Worker 
354*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
355*795d594fSAndroid Build Coastguard Worker }  // namespace art
356*795d594fSAndroid Build Coastguard Worker 
357*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_
358