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 "linear_alloc.h"
24 #include "oat_file.h"
25 #include "object-inl.h"
26 #include "object.h"
27 #include "object_array-inl.h"
28 #include "reflective_value_visitor.h"
29 #include "runtime.h"
30 #include "runtime_globals.h"
31 #include "string.h"
32 #include "thread.h"
33 #include "utils/dex_cache_arrays_layout-inl.h"
34 #include "write_barrier.h"
35 
36 namespace art {
37 namespace mirror {
38 
InitializeDexCache(Thread * self,ObjPtr<mirror::DexCache> dex_cache,ObjPtr<mirror::String> location,const DexFile * dex_file,LinearAlloc * linear_alloc,PointerSize image_pointer_size)39 void DexCache::InitializeDexCache(Thread* self,
40                                   ObjPtr<mirror::DexCache> dex_cache,
41                                   ObjPtr<mirror::String> location,
42                                   const DexFile* dex_file,
43                                   LinearAlloc* linear_alloc,
44                                   PointerSize image_pointer_size) {
45   DCHECK(dex_file != nullptr);
46   ScopedAssertNoThreadSuspension sants(__FUNCTION__);
47   DexCacheArraysLayout layout(image_pointer_size, dex_file);
48   uint8_t* raw_arrays = nullptr;
49 
50   if (dex_file->NumStringIds() != 0u ||
51       dex_file->NumTypeIds() != 0u ||
52       dex_file->NumMethodIds() != 0u ||
53       dex_file->NumFieldIds() != 0u) {
54     static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8.");
55     DCHECK(layout.Alignment() == 8u || layout.Alignment() == 16u);
56     // Zero-initialized.
57     raw_arrays = (layout.Alignment() == 16u)
58         ? reinterpret_cast<uint8_t*>(linear_alloc->AllocAlign16(self, layout.Size()))
59         : reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
60   }
61 
62   StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr :
63       reinterpret_cast<StringDexCacheType*>(raw_arrays + layout.StringsOffset());
64   TypeDexCacheType* types = (dex_file->NumTypeIds() == 0u) ? nullptr :
65       reinterpret_cast<TypeDexCacheType*>(raw_arrays + layout.TypesOffset());
66   MethodDexCacheType* methods = (dex_file->NumMethodIds() == 0u) ? nullptr :
67       reinterpret_cast<MethodDexCacheType*>(raw_arrays + layout.MethodsOffset());
68   FieldDexCacheType* fields = (dex_file->NumFieldIds() == 0u) ? nullptr :
69       reinterpret_cast<FieldDexCacheType*>(raw_arrays + layout.FieldsOffset());
70 
71   size_t num_strings = kDexCacheStringCacheSize;
72   if (dex_file->NumStringIds() < num_strings) {
73     num_strings = dex_file->NumStringIds();
74   }
75   size_t num_types = kDexCacheTypeCacheSize;
76   if (dex_file->NumTypeIds() < num_types) {
77     num_types = dex_file->NumTypeIds();
78   }
79   size_t num_fields = kDexCacheFieldCacheSize;
80   if (dex_file->NumFieldIds() < num_fields) {
81     num_fields = dex_file->NumFieldIds();
82   }
83   size_t num_methods = kDexCacheMethodCacheSize;
84   if (dex_file->NumMethodIds() < num_methods) {
85     num_methods = dex_file->NumMethodIds();
86   }
87 
88   // Note that we allocate the method type dex caches regardless of this flag,
89   // and we make sure here that they're not used by the runtime. This is in the
90   // interest of simplicity and to avoid extensive compiler and layout class changes.
91   //
92   // If this needs to be mitigated in a production system running this code,
93   // DexCache::kDexCacheMethodTypeCacheSize can be set to zero.
94   MethodTypeDexCacheType* method_types = nullptr;
95   size_t num_method_types = 0;
96 
97   if (dex_file->NumProtoIds() < kDexCacheMethodTypeCacheSize) {
98     num_method_types = dex_file->NumProtoIds();
99   } else {
100     num_method_types = kDexCacheMethodTypeCacheSize;
101   }
102 
103   if (num_method_types > 0) {
104     method_types = reinterpret_cast<MethodTypeDexCacheType*>(
105         raw_arrays + layout.MethodTypesOffset());
106   }
107 
108   GcRoot<mirror::CallSite>* call_sites = (dex_file->NumCallSiteIds() == 0)
109       ? nullptr
110       : reinterpret_cast<GcRoot<CallSite>*>(raw_arrays + layout.CallSitesOffset());
111 
112   DCHECK_ALIGNED(raw_arrays, alignof(StringDexCacheType)) <<
113                  "Expected raw_arrays to align to StringDexCacheType.";
114   DCHECK_ALIGNED(layout.StringsOffset(), alignof(StringDexCacheType)) <<
115                  "Expected StringsOffset() to align to StringDexCacheType.";
116   DCHECK_ALIGNED(strings, alignof(StringDexCacheType)) <<
117                  "Expected strings to align to StringDexCacheType.";
118   static_assert(alignof(StringDexCacheType) == 8u,
119                 "Expected StringDexCacheType to have align of 8.");
120   if (kIsDebugBuild) {
121     // Sanity check to make sure all the dex cache arrays are empty. b/28992179
122     for (size_t i = 0; i < num_strings; ++i) {
123       CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
124       CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
125     }
126     for (size_t i = 0; i < num_types; ++i) {
127       CHECK_EQ(types[i].load(std::memory_order_relaxed).index, 0u);
128       CHECK(types[i].load(std::memory_order_relaxed).object.IsNull());
129     }
130     for (size_t i = 0; i < num_methods; ++i) {
131       CHECK_EQ(GetNativePairPtrSize(methods, i, image_pointer_size).index, 0u);
132       CHECK(GetNativePairPtrSize(methods, i, image_pointer_size).object == nullptr);
133     }
134     for (size_t i = 0; i < num_fields; ++i) {
135       CHECK_EQ(GetNativePairPtrSize(fields, i, image_pointer_size).index, 0u);
136       CHECK(GetNativePairPtrSize(fields, i, image_pointer_size).object == nullptr);
137     }
138     for (size_t i = 0; i < num_method_types; ++i) {
139       CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
140       CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull());
141     }
142     for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) {
143       CHECK(call_sites[i].IsNull());
144     }
145   }
146   if (strings != nullptr) {
147     mirror::StringDexCachePair::Initialize(strings);
148   }
149   if (types != nullptr) {
150     mirror::TypeDexCachePair::Initialize(types);
151   }
152   if (fields != nullptr) {
153     mirror::FieldDexCachePair::Initialize(fields, image_pointer_size);
154   }
155   if (methods != nullptr) {
156     mirror::MethodDexCachePair::Initialize(methods, image_pointer_size);
157   }
158   if (method_types != nullptr) {
159     mirror::MethodTypeDexCachePair::Initialize(method_types);
160   }
161   dex_cache->Init(dex_file,
162                   location,
163                   strings,
164                   num_strings,
165                   types,
166                   num_types,
167                   methods,
168                   num_methods,
169                   fields,
170                   num_fields,
171                   method_types,
172                   num_method_types,
173                   call_sites,
174                   dex_file->NumCallSiteIds());
175 }
176 
VisitReflectiveTargets(ReflectiveValueVisitor * visitor)177 void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) {
178   bool wrote = false;
179   for (size_t i = 0; i < NumResolvedFields(); i++) {
180     auto pair(GetNativePairPtrSize(GetResolvedFields(), i, kRuntimePointerSize));
181     if (pair.index == FieldDexCachePair::InvalidIndexForSlot(i)) {
182       continue;
183     }
184     ArtField* new_val = visitor->VisitField(
185         pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedField, pair.index, this));
186     if (UNLIKELY(new_val != pair.object)) {
187       if (new_val == nullptr) {
188         pair = FieldDexCachePair(nullptr, FieldDexCachePair::InvalidIndexForSlot(i));
189       } else {
190         pair.object = new_val;
191       }
192       SetNativePairPtrSize(GetResolvedFields(), i, pair, kRuntimePointerSize);
193       wrote = true;
194     }
195   }
196   for (size_t i = 0; i < NumResolvedMethods(); i++) {
197     auto pair(GetNativePairPtrSize(GetResolvedMethods(), i, kRuntimePointerSize));
198     if (pair.index == MethodDexCachePair::InvalidIndexForSlot(i)) {
199       continue;
200     }
201     ArtMethod* new_val = visitor->VisitMethod(
202         pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedMethod, pair.index, this));
203     if (UNLIKELY(new_val != pair.object)) {
204       if (new_val == nullptr) {
205         pair = MethodDexCachePair(nullptr, MethodDexCachePair::InvalidIndexForSlot(i));
206       } else {
207         pair.object = new_val;
208       }
209       SetNativePairPtrSize(GetResolvedMethods(), i, pair, kRuntimePointerSize);
210       wrote = true;
211     }
212   }
213   if (wrote) {
214     WriteBarrier::ForEveryFieldWrite(this);
215   }
216 }
217 
AddPreResolvedStringsArray()218 bool DexCache::AddPreResolvedStringsArray() {
219   DCHECK_EQ(NumPreResolvedStrings(), 0u);
220   Thread* const self = Thread::Current();
221   LinearAlloc* linear_alloc = Runtime::Current()->GetLinearAlloc();
222   const size_t num_strings = GetDexFile()->NumStringIds();
223   if (num_strings != 0) {
224     GcRoot<mirror::String>* strings =
225         linear_alloc->AllocArray<GcRoot<mirror::String>>(self, num_strings);
226     if (strings == nullptr) {
227       // Failed to allocate pre-resolved string array (probably due to address fragmentation), bail.
228       return false;
229     }
230     SetField32<false>(NumPreResolvedStringsOffset(), num_strings);
231 
232     CHECK(strings != nullptr);
233     SetPreResolvedStrings(strings);
234     for (size_t i = 0; i < GetDexFile()->NumStringIds(); ++i) {
235       CHECK(GetPreResolvedStrings()[i].Read() == nullptr);
236     }
237   }
238   return true;
239 }
240 
Init(const DexFile * dex_file,ObjPtr<String> location,StringDexCacheType * strings,uint32_t num_strings,TypeDexCacheType * resolved_types,uint32_t num_resolved_types,MethodDexCacheType * resolved_methods,uint32_t num_resolved_methods,FieldDexCacheType * resolved_fields,uint32_t num_resolved_fields,MethodTypeDexCacheType * resolved_method_types,uint32_t num_resolved_method_types,GcRoot<CallSite> * resolved_call_sites,uint32_t num_resolved_call_sites)241 void DexCache::Init(const DexFile* dex_file,
242                     ObjPtr<String> location,
243                     StringDexCacheType* strings,
244                     uint32_t num_strings,
245                     TypeDexCacheType* resolved_types,
246                     uint32_t num_resolved_types,
247                     MethodDexCacheType* resolved_methods,
248                     uint32_t num_resolved_methods,
249                     FieldDexCacheType* resolved_fields,
250                     uint32_t num_resolved_fields,
251                     MethodTypeDexCacheType* resolved_method_types,
252                     uint32_t num_resolved_method_types,
253                     GcRoot<CallSite>* resolved_call_sites,
254                     uint32_t num_resolved_call_sites) {
255   CHECK(dex_file != nullptr);
256   CHECK(location != nullptr);
257   CHECK_EQ(num_strings != 0u, strings != nullptr);
258   CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
259   CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
260   CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
261   CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr);
262   CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr);
263 
264   SetDexFile(dex_file);
265   SetLocation(location);
266   SetStrings(strings);
267   SetResolvedTypes(resolved_types);
268   SetResolvedMethods(resolved_methods);
269   SetResolvedFields(resolved_fields);
270   SetResolvedMethodTypes(resolved_method_types);
271   SetResolvedCallSites(resolved_call_sites);
272   SetField32<false>(NumStringsOffset(), num_strings);
273   SetField32<false>(NumResolvedTypesOffset(), num_resolved_types);
274   SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods);
275   SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields);
276   SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types);
277   SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites);
278 }
279 
SetLocation(ObjPtr<mirror::String> location)280 void DexCache::SetLocation(ObjPtr<mirror::String> location) {
281   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
282 }
283 
SetClassLoader(ObjPtr<ClassLoader> class_loader)284 void DexCache::SetClassLoader(ObjPtr<ClassLoader> class_loader) {
285   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, class_loader_), class_loader);
286 }
287 
288 #if !defined(__aarch64__) && !defined(__x86_64__)
289 static pthread_mutex_t dex_cache_slow_atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
290 
AtomicLoadRelaxed16B(std::atomic<ConversionPair64> * target)291 DexCache::ConversionPair64 DexCache::AtomicLoadRelaxed16B(std::atomic<ConversionPair64>* target) {
292   pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
293   DexCache::ConversionPair64 value = *reinterpret_cast<ConversionPair64*>(target);
294   pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
295   return value;
296 }
297 
AtomicStoreRelease16B(std::atomic<ConversionPair64> * target,ConversionPair64 value)298 void DexCache::AtomicStoreRelease16B(std::atomic<ConversionPair64>* target,
299                                      ConversionPair64 value) {
300   pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
301   *reinterpret_cast<ConversionPair64*>(target) = value;
302   pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
303 }
304 #endif
305 
306 }  // namespace mirror
307 }  // namespace art
308