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