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 "base/logging.h"
21 #include "class_linker.h"
22 #include "gc/accounting/card_table-inl.h"
23 #include "gc/heap.h"
24 #include "globals.h"
25 #include "linear_alloc.h"
26 #include "object.h"
27 #include "object-inl.h"
28 #include "object_array-inl.h"
29 #include "runtime.h"
30 #include "string.h"
31 #include "thread.h"
32 #include "utils/dex_cache_arrays_layout-inl.h"
33 
34 namespace art {
35 namespace mirror {
36 
InitializeDexCache(Thread * self,ObjPtr<mirror::DexCache> dex_cache,ObjPtr<mirror::String> location,const DexFile * dex_file,LinearAlloc * linear_alloc,PointerSize image_pointer_size)37 void DexCache::InitializeDexCache(Thread* self,
38                                   ObjPtr<mirror::DexCache> dex_cache,
39                                   ObjPtr<mirror::String> location,
40                                   const DexFile* dex_file,
41                                   LinearAlloc* linear_alloc,
42                                   PointerSize image_pointer_size) {
43   DCHECK(dex_file != nullptr);
44   ScopedAssertNoThreadSuspension sants(__FUNCTION__);
45   DexCacheArraysLayout layout(image_pointer_size, dex_file);
46   uint8_t* raw_arrays = nullptr;
47 
48   const OatDexFile* const oat_dex = dex_file->GetOatDexFile();
49   if (oat_dex != nullptr && oat_dex->GetDexCacheArrays() != nullptr) {
50     raw_arrays = oat_dex->GetDexCacheArrays();
51   } else if (dex_file->NumStringIds() != 0u ||
52              dex_file->NumTypeIds() != 0u ||
53              dex_file->NumMethodIds() != 0u ||
54              dex_file->NumFieldIds() != 0u) {
55     static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8.");
56     DCHECK(layout.Alignment() == 8u || layout.Alignment() == 16u);
57     // Zero-initialized.
58     raw_arrays = (layout.Alignment() == 16u)
59         ? reinterpret_cast<uint8_t*>(linear_alloc->AllocAlign16(self, layout.Size()))
60         : reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
61   }
62 
63   mirror::StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr :
64       reinterpret_cast<mirror::StringDexCacheType*>(raw_arrays + layout.StringsOffset());
65   mirror::TypeDexCacheType* types = (dex_file->NumTypeIds() == 0u) ? nullptr :
66       reinterpret_cast<mirror::TypeDexCacheType*>(raw_arrays + layout.TypesOffset());
67   ArtMethod** methods = (dex_file->NumMethodIds() == 0u) ? nullptr :
68       reinterpret_cast<ArtMethod**>(raw_arrays + layout.MethodsOffset());
69   mirror::FieldDexCacheType* fields = (dex_file->NumFieldIds() == 0u) ? nullptr :
70       reinterpret_cast<mirror::FieldDexCacheType*>(raw_arrays + layout.FieldsOffset());
71 
72   size_t num_strings = kDexCacheStringCacheSize;
73   if (dex_file->NumStringIds() < num_strings) {
74     num_strings = dex_file->NumStringIds();
75   }
76   size_t num_types = kDexCacheTypeCacheSize;
77   if (dex_file->NumTypeIds() < num_types) {
78     num_types = dex_file->NumTypeIds();
79   }
80   size_t num_fields = kDexCacheFieldCacheSize;
81   if (dex_file->NumFieldIds() < num_fields) {
82     num_fields = dex_file->NumFieldIds();
83   }
84 
85   // Note that we allocate the method type dex caches regardless of this flag,
86   // and we make sure here that they're not used by the runtime. This is in the
87   // interest of simplicity and to avoid extensive compiler and layout class changes.
88   //
89   // If this needs to be mitigated in a production system running this code,
90   // DexCache::kDexCacheMethodTypeCacheSize can be set to zero.
91   MethodTypeDexCacheType* method_types = nullptr;
92   size_t num_method_types = 0;
93 
94   if (dex_file->NumProtoIds() < kDexCacheMethodTypeCacheSize) {
95     num_method_types = dex_file->NumProtoIds();
96   } else {
97     num_method_types = kDexCacheMethodTypeCacheSize;
98   }
99 
100   if (num_method_types > 0) {
101     method_types = reinterpret_cast<MethodTypeDexCacheType*>(
102         raw_arrays + layout.MethodTypesOffset());
103   }
104 
105   GcRoot<mirror::CallSite>* call_sites = (dex_file->NumCallSiteIds() == 0)
106       ? nullptr
107       : reinterpret_cast<GcRoot<mirror::CallSite>*>(raw_arrays + layout.CallSitesOffset());
108 
109   DCHECK_ALIGNED(raw_arrays, alignof(StringDexCacheType)) <<
110                  "Expected raw_arrays to align to StringDexCacheType.";
111   DCHECK_ALIGNED(layout.StringsOffset(), alignof(StringDexCacheType)) <<
112                  "Expected StringsOffset() to align to StringDexCacheType.";
113   DCHECK_ALIGNED(strings, alignof(StringDexCacheType)) <<
114                  "Expected strings to align to StringDexCacheType.";
115   static_assert(alignof(StringDexCacheType) == 8u,
116                 "Expected StringDexCacheType to have align of 8.");
117   if (kIsDebugBuild) {
118     // Sanity check to make sure all the dex cache arrays are empty. b/28992179
119     for (size_t i = 0; i < num_strings; ++i) {
120       CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
121       CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
122     }
123     for (size_t i = 0; i < num_types; ++i) {
124       CHECK_EQ(types[i].load(std::memory_order_relaxed).index, 0u);
125       CHECK(types[i].load(std::memory_order_relaxed).object.IsNull());
126     }
127     for (size_t i = 0; i < dex_file->NumMethodIds(); ++i) {
128       CHECK(GetElementPtrSize(methods, i, image_pointer_size) == nullptr);
129     }
130     for (size_t i = 0; i < num_fields; ++i) {
131       CHECK_EQ(GetNativePairPtrSize(fields, i, image_pointer_size).index, 0u);
132       CHECK(GetNativePairPtrSize(fields, i, image_pointer_size).object == nullptr);
133     }
134     for (size_t i = 0; i < num_method_types; ++i) {
135       CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
136       CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull());
137     }
138     for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) {
139       CHECK(call_sites[i].IsNull());
140     }
141   }
142   if (strings != nullptr) {
143     mirror::StringDexCachePair::Initialize(strings);
144   }
145   if (types != nullptr) {
146     mirror::TypeDexCachePair::Initialize(types);
147   }
148   if (fields != nullptr) {
149     mirror::FieldDexCachePair::Initialize(fields, image_pointer_size);
150   }
151   if (method_types != nullptr) {
152     mirror::MethodTypeDexCachePair::Initialize(method_types);
153   }
154   dex_cache->Init(dex_file,
155                   location,
156                   strings,
157                   num_strings,
158                   types,
159                   num_types,
160                   methods,
161                   dex_file->NumMethodIds(),
162                   fields,
163                   num_fields,
164                   method_types,
165                   num_method_types,
166                   call_sites,
167                   dex_file->NumCallSiteIds(),
168                   image_pointer_size);
169 }
170 
Init(const DexFile * dex_file,ObjPtr<String> location,StringDexCacheType * strings,uint32_t num_strings,TypeDexCacheType * resolved_types,uint32_t num_resolved_types,ArtMethod ** 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,PointerSize pointer_size)171 void DexCache::Init(const DexFile* dex_file,
172                     ObjPtr<String> location,
173                     StringDexCacheType* strings,
174                     uint32_t num_strings,
175                     TypeDexCacheType* resolved_types,
176                     uint32_t num_resolved_types,
177                     ArtMethod** resolved_methods,
178                     uint32_t num_resolved_methods,
179                     FieldDexCacheType* resolved_fields,
180                     uint32_t num_resolved_fields,
181                     MethodTypeDexCacheType* resolved_method_types,
182                     uint32_t num_resolved_method_types,
183                     GcRoot<CallSite>* resolved_call_sites,
184                     uint32_t num_resolved_call_sites,
185                     PointerSize pointer_size) {
186   CHECK(dex_file != nullptr);
187   CHECK(location != nullptr);
188   CHECK_EQ(num_strings != 0u, strings != nullptr);
189   CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
190   CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
191   CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
192   CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr);
193   CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr);
194 
195   SetDexFile(dex_file);
196   SetLocation(location);
197   SetStrings(strings);
198   SetResolvedTypes(resolved_types);
199   SetResolvedMethods(resolved_methods);
200   SetResolvedFields(resolved_fields);
201   SetResolvedMethodTypes(resolved_method_types);
202   SetResolvedCallSites(resolved_call_sites);
203   SetField32<false>(NumStringsOffset(), num_strings);
204   SetField32<false>(NumResolvedTypesOffset(), num_resolved_types);
205   SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods);
206   SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields);
207   SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types);
208   SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites);
209 
210   Runtime* const runtime = Runtime::Current();
211   if (runtime->HasResolutionMethod()) {
212     // Initialize the resolve methods array to contain trampolines for resolution.
213     Fixup(runtime->GetResolutionMethod(), pointer_size);
214   }
215 }
216 
Fixup(ArtMethod * trampoline,PointerSize pointer_size)217 void DexCache::Fixup(ArtMethod* trampoline, PointerSize pointer_size) {
218   // Fixup the resolve methods array to contain trampoline for resolution.
219   CHECK(trampoline != nullptr);
220   CHECK(trampoline->IsRuntimeMethod());
221   auto* resolved_methods = GetResolvedMethods();
222   for (size_t i = 0, length = NumResolvedMethods(); i < length; i++) {
223     if (GetElementPtrSize<ArtMethod*>(resolved_methods, i, pointer_size) == nullptr) {
224       SetElementPtrSize(resolved_methods, i, trampoline, pointer_size);
225     }
226   }
227 }
228 
SetLocation(ObjPtr<mirror::String> location)229 void DexCache::SetLocation(ObjPtr<mirror::String> location) {
230   SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
231 }
232 
233 #if !defined(__aarch64__) && !defined(__x86_64__)
234 static pthread_mutex_t dex_cache_slow_atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
235 
AtomicLoadRelaxed16B(std::atomic<ConversionPair64> * target)236 DexCache::ConversionPair64 DexCache::AtomicLoadRelaxed16B(std::atomic<ConversionPair64>* target) {
237   pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
238   DexCache::ConversionPair64 value = *reinterpret_cast<ConversionPair64*>(target);
239   pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
240   return value;
241 }
242 
AtomicStoreRelease16B(std::atomic<ConversionPair64> * target,ConversionPair64 value)243 void DexCache::AtomicStoreRelease16B(std::atomic<ConversionPair64>* target,
244                                      ConversionPair64 value) {
245   pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
246   *reinterpret_cast<ConversionPair64*>(target) = value;
247   pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
248 }
249 #endif
250 
251 }  // namespace mirror
252 }  // namespace art
253