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