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