• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "dex_cache-inl.h"
18 
19 #include "art_method-inl.h"
20 #include "class_linker.h"
21 #include "gc/accounting/card_table-inl.h"
22 #include "gc/heap.h"
23 #include "jit/profile_saver.h"
24 #include "linear_alloc.h"
25 #include "oat_file.h"
26 #include "object-inl.h"
27 #include "object.h"
28 #include "object_array-inl.h"
29 #include "reflective_value_visitor.h"
30 #include "runtime.h"
31 #include "runtime_globals.h"
32 #include "string.h"
33 #include "thread.h"
34 #include "write_barrier.h"
35 
36 namespace art {
37 namespace mirror {
38 
39 // Whether to allocate full dex cache arrays during startup. Currently disabled
40 // while debugging b/283632504.
41 static constexpr bool kEnableFullArraysAtStartup = false;
42 
Initialize(const DexFile * dex_file,ObjPtr<ClassLoader> class_loader)43 void DexCache::Initialize(const DexFile* dex_file, ObjPtr<ClassLoader> class_loader) {
44   DCHECK(GetDexFile() == nullptr);
45   DCHECK(GetStrings() == nullptr);
46   DCHECK(GetResolvedTypes() == nullptr);
47   DCHECK(GetResolvedMethods() == nullptr);
48   DCHECK(GetResolvedFields() == nullptr);
49   DCHECK(GetResolvedMethodTypes() == nullptr);
50   DCHECK(GetResolvedCallSites() == nullptr);
51 
52   ScopedAssertNoThreadSuspension sants(__FUNCTION__);
53 
54   SetDexFile(dex_file);
55   SetClassLoader(class_loader);
56 }
57 
VisitReflectiveTargets(ReflectiveValueVisitor * visitor)58 void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) {
59   bool wrote = false;
60   auto* fields = GetResolvedFields();
61   size_t num_fields = NumResolvedFields();
62   // Check both the data pointer and count since the array might be initialized
63   // concurrently on other thread, and we might observe just one of the values.
64   for (size_t i = 0; fields != nullptr && i < num_fields; i++) {
65     auto pair(fields->GetNativePair(i));
66     if (pair.index == NativeDexCachePair<ArtField>::InvalidIndexForSlot(i)) {
67       continue;
68     }
69     ArtField* new_val = visitor->VisitField(
70         pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedField, pair.index, this));
71     if (UNLIKELY(new_val != pair.object)) {
72       if (new_val == nullptr) {
73         pair = NativeDexCachePair<ArtField>(
74             nullptr, NativeDexCachePair<ArtField>::InvalidIndexForSlot(i));
75       } else {
76         pair.object = new_val;
77       }
78       fields->SetNativePair(i, pair);
79       wrote = true;
80     }
81   }
82   auto* methods = GetResolvedMethods();
83   size_t num_methods = NumResolvedMethods();
84   // Check both the data pointer and count since the array might be initialized
85   // concurrently on other thread, and we might observe just one of the values.
86   for (size_t i = 0; methods != nullptr && i < num_methods; i++) {
87     auto pair(methods->GetNativePair(i));
88     if (pair.index == NativeDexCachePair<ArtMethod>::InvalidIndexForSlot(i)) {
89       continue;
90     }
91     ArtMethod* new_val = visitor->VisitMethod(
92         pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedMethod, pair.index, this));
93     if (UNLIKELY(new_val != pair.object)) {
94       if (new_val == nullptr) {
95         pair = NativeDexCachePair<ArtMethod>(
96             nullptr, NativeDexCachePair<ArtMethod>::InvalidIndexForSlot(i));
97       } else {
98         pair.object = new_val;
99       }
100       methods->SetNativePair(i, pair);
101       wrote = true;
102     }
103   }
104 
105   auto* fields_array = GetResolvedFieldsArray();
106   num_fields = NumResolvedFieldsArray();
107   for (size_t i = 0; fields_array != nullptr && i < num_fields; i++) {
108     ArtField* old_val = fields_array->Get(i);
109     if (old_val == nullptr) {
110       continue;
111     }
112     ArtField* new_val = visitor->VisitField(
113         old_val, DexCacheSourceInfo(kSourceDexCacheResolvedField, i, this));
114     if (new_val != old_val) {
115       fields_array->Set(i, new_val);
116       wrote = true;
117     }
118   }
119 
120   auto* methods_array = GetResolvedMethodsArray();
121   num_methods = NumResolvedMethodsArray();
122   for (size_t i = 0; methods_array != nullptr && i < num_methods; i++) {
123     ArtMethod* old_val = methods_array->Get(i);
124     if (old_val == nullptr) {
125       continue;
126     }
127     ArtMethod* new_val = visitor->VisitMethod(
128         old_val, DexCacheSourceInfo(kSourceDexCacheResolvedMethod, i, this));
129     if (new_val != old_val) {
130       methods_array->Set(i, new_val);
131       wrote = true;
132     }
133   }
134 
135   if (wrote) {
136     WriteBarrier::ForEveryFieldWrite(this);
137   }
138 }
139 
ResetNativeArrays()140 void DexCache::ResetNativeArrays() {
141   SetStrings(nullptr);
142   SetResolvedTypes(nullptr);
143   SetResolvedMethods(nullptr);
144   SetResolvedFields(nullptr);
145   SetResolvedMethodTypes(nullptr);
146   SetResolvedCallSites(nullptr);
147 
148   SetStringsArray(nullptr);
149   SetResolvedTypesArray(nullptr);
150   SetResolvedMethodsArray(nullptr);
151   SetResolvedFieldsArray(nullptr);
152   SetResolvedMethodTypesArray(nullptr);
153 }
154 
SetLocation(ObjPtr<mirror::String> location)155 void DexCache::SetLocation(ObjPtr<mirror::String> location) {
156   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
157 }
158 
SetClassLoader(ObjPtr<ClassLoader> class_loader)159 void DexCache::SetClassLoader(ObjPtr<ClassLoader> class_loader) {
160   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, class_loader_), class_loader);
161 }
162 
GetClassLoader()163 ObjPtr<ClassLoader> DexCache::GetClassLoader() {
164   return GetFieldObject<ClassLoader>(OFFSET_OF_OBJECT_MEMBER(DexCache, class_loader_));
165 }
166 
ShouldAllocateFullArrayAtStartup()167 bool DexCache::ShouldAllocateFullArrayAtStartup() {
168   if (!kEnableFullArraysAtStartup) {
169     return false;
170   }
171   Runtime* runtime = Runtime::Current();
172   if (runtime->IsAotCompiler()) {
173     // To save on memory in dex2oat, we don't allocate full arrays by default.
174     return false;
175   }
176 
177   if (runtime->IsZygote()) {
178     // Zygote doesn't have a notion of startup.
179     return false;
180   }
181 
182   if (runtime->GetStartupCompleted()) {
183     // We only allocate full arrays during app startup.
184     return false;
185   }
186 
187   if (GetClassLoader() == nullptr) {
188     // Only allocate full array for app dex files (also note that for
189     // multi-image, the `GetCompilerFilter` call below does not work for
190     // non-primary oat files).
191     return false;
192   }
193 
194   const OatDexFile* oat_dex_file = GetDexFile()->GetOatDexFile();
195   if (oat_dex_file != nullptr &&
196       CompilerFilter::IsAotCompilationEnabled(oat_dex_file->GetOatFile()->GetCompilerFilter())) {
197     // We only allocate full arrays for dex files where we do not have
198     // compilation.
199     return false;
200   }
201 
202   return true;
203 }
204 
UnlinkStartupCaches()205 void DexCache::UnlinkStartupCaches() {
206   if (GetDexFile() == nullptr) {
207     // Unused dex cache.
208     return;
209   }
210   UnlinkStringsArrayIfStartup();
211   UnlinkResolvedFieldsArrayIfStartup();
212   UnlinkResolvedMethodsArrayIfStartup();
213   UnlinkResolvedTypesArrayIfStartup();
214   UnlinkResolvedMethodTypesArrayIfStartup();
215 }
216 
SetResolvedType(dex::TypeIndex type_idx,ObjPtr<Class> resolved)217 void DexCache::SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved) {
218   DCHECK(resolved != nullptr);
219   DCHECK(resolved->IsResolved()) << resolved->GetStatus();
220   // TODO default transaction support.
221   // Use a release store for SetResolvedType. This is done to prevent other threads from seeing a
222   // class but not necessarily seeing the loaded members like the static fields array.
223   // See b/32075261.
224   SetResolvedTypesEntry(type_idx.index_, resolved.Ptr());
225   // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
226   WriteBarrier::ForEveryFieldWrite(this);
227 
228   if (this == resolved->GetDexCache()) {
229     // If we're updating the dex cache of the class, optimistically update the cache for methods and
230     // fields if the caches are full arrays.
231     auto* resolved_methods = GetResolvedMethodsArray();
232     if (resolved_methods != nullptr) {
233       PointerSize pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
234       // Because there could be duplicate method entries, we make sure we only
235       // update the cache with the first one found to be consistent with method
236       // resolution.
237       uint32_t previous_method_index = dex::kDexNoIndex;
238       for (ArtMethod& current_method : resolved->GetDeclaredMethods(pointer_size)) {
239         uint32_t new_index = current_method.GetDexMethodIndex();
240         if (new_index != previous_method_index) {
241           resolved_methods->Set(new_index, &current_method);
242           previous_method_index = new_index;
243         }
244       }
245     }
246     auto* resolved_fields = GetResolvedFieldsArray();
247     if (resolved_fields != nullptr) {
248       for (ArtField& current_field : resolved->GetSFields()) {
249         resolved_fields->Set(current_field.GetDexFieldIndex(), &current_field);
250       }
251       for (ArtField& current_field : resolved->GetIFields()) {
252         resolved_fields->Set(current_field.GetDexFieldIndex(), &current_field);
253       }
254     }
255   }
256 }
257 
258 }  // namespace mirror
259 }  // namespace art
260