blob: 1b9558e6df5ef43151496f75e3d372c8f15d224d [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070016
Vladimir Marko05792b92015-08-03 11:56:49 +010017#include "dex_cache-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080018
Brian Carlstromea46f952013-07-30 01:26:50 -070019#include "art_method-inl.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070020#include "class_linker.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070021#include "gc/accounting/card_table-inl.h"
22#include "gc/heap.h"
Andreas Gampecc1b5352016-12-01 16:58:38 -080023#include "linear_alloc.h"
Andreas Gampe2ff3b972017-06-05 18:14:53 -070024#include "oat_file.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080025#include "object-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070026#include "object.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080027#include "object_array-inl.h"
Alex Lightc18eba32019-09-24 14:36:27 -070028#include "reflective_value_visitor.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029#include "runtime.h"
Andreas Gampe5a0430d2019-01-04 14:33:57 -080030#include "runtime_globals.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080031#include "string.h"
Andreas Gampecc1b5352016-12-01 16:58:38 -080032#include "thread.h"
Alex Lighte61f16a2019-11-20 13:49:19 -080033#include "write_barrier.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070034
35namespace art {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080036namespace mirror {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070037
Orion Hodsonb9b7d912021-02-24 09:24:47 +000038template<typename T>
39static T* AllocArray(Thread* self, LinearAlloc* alloc, size_t num) {
40 if (num == 0) {
41 return nullptr;
42 }
43 return reinterpret_cast<T*>(alloc->AllocAlign16(self, RoundUp(num * sizeof(T), 16)));
44}
45
46void DexCache::InitializeNativeFields(const DexFile* dex_file, LinearAlloc* linear_alloc) {
David Srbecky86d6cd52020-12-02 18:13:10 +000047 DCHECK(GetDexFile() == nullptr);
48 DCHECK(GetStrings() == nullptr);
49 DCHECK(GetResolvedTypes() == nullptr);
50 DCHECK(GetResolvedMethods() == nullptr);
51 DCHECK(GetResolvedFields() == nullptr);
52 DCHECK(GetResolvedMethodTypes() == nullptr);
53 DCHECK(GetResolvedCallSites() == nullptr);
54
Andreas Gampecc1b5352016-12-01 16:58:38 -080055 ScopedAssertNoThreadSuspension sants(__FUNCTION__);
Orion Hodsonb9b7d912021-02-24 09:24:47 +000056 Thread* self = Thread::Current();
Andreas Gampecc1b5352016-12-01 16:58:38 -080057
Orion Hodsonb9b7d912021-02-24 09:24:47 +000058 size_t num_strings = std::min<size_t>(kDexCacheStringCacheSize, dex_file->NumStringIds());
59 size_t num_types = std::min<size_t>(kDexCacheTypeCacheSize, dex_file->NumTypeIds());
60 size_t num_fields = std::min<size_t>(kDexCacheFieldCacheSize, dex_file->NumFieldIds());
61 size_t num_methods = std::min<size_t>(kDexCacheMethodCacheSize, dex_file->NumMethodIds());
62 size_t num_method_types = std::min<size_t>(kDexCacheMethodTypeCacheSize, dex_file->NumProtoIds());
63 size_t num_call_sites = dex_file->NumCallSiteIds(); // Full size.
64
65 static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8.");
66 StringDexCacheType* strings =
67 AllocArray<StringDexCacheType>(self, linear_alloc, num_strings);
68 TypeDexCacheType* types =
69 AllocArray<TypeDexCacheType>(self, linear_alloc, num_types);
70 MethodDexCacheType* methods =
71 AllocArray<MethodDexCacheType>(self, linear_alloc, num_methods);
72 FieldDexCacheType* fields =
73 AllocArray<FieldDexCacheType>(self, linear_alloc, num_fields);
74 MethodTypeDexCacheType* method_types =
75 AllocArray<MethodTypeDexCacheType>(self, linear_alloc, num_method_types);
76 GcRoot<mirror::CallSite>* call_sites =
77 AllocArray<GcRoot<CallSite>>(self, linear_alloc, num_call_sites);
78
79 DCHECK_ALIGNED(types, alignof(StringDexCacheType)) <<
80 "Expected StringsOffset() to align to StringDexCacheType.";
81 DCHECK_ALIGNED(strings, alignof(StringDexCacheType)) <<
82 "Expected strings to align to StringDexCacheType.";
83 static_assert(alignof(StringDexCacheType) == 8u,
84 "Expected StringDexCacheType to have align of 8.");
85 if (kIsDebugBuild) {
86 // Consistency check to make sure all the dex cache arrays are empty. b/28992179
87 for (size_t i = 0; i < num_strings; ++i) {
88 CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
89 CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
90 }
91 for (size_t i = 0; i < num_types; ++i) {
92 CHECK_EQ(types[i].load(std::memory_order_relaxed).index, 0u);
93 CHECK(types[i].load(std::memory_order_relaxed).object.IsNull());
94 }
95 for (size_t i = 0; i < num_methods; ++i) {
96 CHECK_EQ(GetNativePair(methods, i).index, 0u);
97 CHECK(GetNativePair(methods, i).object == nullptr);
98 }
99 for (size_t i = 0; i < num_fields; ++i) {
100 CHECK_EQ(GetNativePair(fields, i).index, 0u);
101 CHECK(GetNativePair(fields, i).object == nullptr);
102 }
103 for (size_t i = 0; i < num_method_types; ++i) {
104 CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
105 CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull());
106 }
107 for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) {
108 CHECK(call_sites[i].IsNull());
109 }
110 }
111 if (strings != nullptr) {
112 mirror::StringDexCachePair::Initialize(strings);
113 }
114 if (types != nullptr) {
115 mirror::TypeDexCachePair::Initialize(types);
116 }
117 if (fields != nullptr) {
118 mirror::FieldDexCachePair::Initialize(fields);
119 }
120 if (methods != nullptr) {
121 mirror::MethodDexCachePair::Initialize(methods);
122 }
123 if (method_types != nullptr) {
124 mirror::MethodTypeDexCachePair::Initialize(method_types);
125 }
David Srbecky86d6cd52020-12-02 18:13:10 +0000126 SetDexFile(dex_file);
Orion Hodsonb9b7d912021-02-24 09:24:47 +0000127 SetNativeArrays(strings,
128 num_strings,
129 types,
130 num_types,
131 methods,
132 num_methods,
133 fields,
134 num_fields,
135 method_types,
136 num_method_types,
137 call_sites,
138 num_call_sites);
139}
140
141void DexCache::ResetNativeFields() {
142 SetDexFile(nullptr);
143 SetNativeArrays(nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0);
Andreas Gampecc1b5352016-12-01 16:58:38 -0800144}
145
Alex Lightc18eba32019-09-24 14:36:27 -0700146void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) {
Alex Lighte61f16a2019-11-20 13:49:19 -0800147 bool wrote = false;
Alex Lightc18eba32019-09-24 14:36:27 -0700148 for (size_t i = 0; i < NumResolvedFields(); i++) {
David Srbecky5de5efe2021-02-15 21:23:00 +0000149 auto pair(GetNativePair(GetResolvedFields(), i));
Alex Light28b6efe2019-11-06 12:49:41 -0800150 if (pair.index == FieldDexCachePair::InvalidIndexForSlot(i)) {
151 continue;
152 }
Alex Lightc18eba32019-09-24 14:36:27 -0700153 ArtField* new_val = visitor->VisitField(
154 pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedField, pair.index, this));
155 if (UNLIKELY(new_val != pair.object)) {
Alex Light24627892019-11-06 10:28:21 -0800156 if (new_val == nullptr) {
157 pair = FieldDexCachePair(nullptr, FieldDexCachePair::InvalidIndexForSlot(i));
158 } else {
159 pair.object = new_val;
160 }
David Srbecky5de5efe2021-02-15 21:23:00 +0000161 SetNativePair(GetResolvedFields(), i, pair);
Alex Lighte61f16a2019-11-20 13:49:19 -0800162 wrote = true;
Alex Lightc18eba32019-09-24 14:36:27 -0700163 }
164 }
165 for (size_t i = 0; i < NumResolvedMethods(); i++) {
David Srbecky5de5efe2021-02-15 21:23:00 +0000166 auto pair(GetNativePair(GetResolvedMethods(), i));
Alex Light28b6efe2019-11-06 12:49:41 -0800167 if (pair.index == MethodDexCachePair::InvalidIndexForSlot(i)) {
168 continue;
169 }
Alex Lightc18eba32019-09-24 14:36:27 -0700170 ArtMethod* new_val = visitor->VisitMethod(
171 pair.object, DexCacheSourceInfo(kSourceDexCacheResolvedMethod, pair.index, this));
172 if (UNLIKELY(new_val != pair.object)) {
Alex Light24627892019-11-06 10:28:21 -0800173 if (new_val == nullptr) {
174 pair = MethodDexCachePair(nullptr, MethodDexCachePair::InvalidIndexForSlot(i));
175 } else {
176 pair.object = new_val;
177 }
David Srbecky5de5efe2021-02-15 21:23:00 +0000178 SetNativePair(GetResolvedMethods(), i, pair);
Alex Lighte61f16a2019-11-20 13:49:19 -0800179 wrote = true;
Alex Lightc18eba32019-09-24 14:36:27 -0700180 }
181 }
Alex Lighte61f16a2019-11-20 13:49:19 -0800182 if (wrote) {
183 WriteBarrier::ForEveryFieldWrite(this);
184 }
Alex Lightc18eba32019-09-24 14:36:27 -0700185}
186
Orion Hodsonb9b7d912021-02-24 09:24:47 +0000187bool DexCache::AddPreResolvedStringsArray() {
188 DCHECK_EQ(NumPreResolvedStrings(), 0u);
189 Thread* const self = Thread::Current();
190 LinearAlloc* linear_alloc = Runtime::Current()->GetLinearAlloc();
191 const size_t num_strings = GetDexFile()->NumStringIds();
192 if (num_strings != 0) {
193 GcRoot<mirror::String>* strings =
194 linear_alloc->AllocArray<GcRoot<mirror::String>>(self, num_strings);
195 if (strings == nullptr) {
196 // Failed to allocate pre-resolved string array (probably due to address fragmentation), bail.
197 return false;
198 }
199 SetField32<false>(NumPreResolvedStringsOffset(), num_strings);
200
201 CHECK(strings != nullptr);
202 SetPreResolvedStrings(strings);
203 for (size_t i = 0; i < GetDexFile()->NumStringIds(); ++i) {
204 CHECK(GetPreResolvedStrings()[i].Read() == nullptr);
205 }
206 }
207 return true;
208}
209
210void DexCache::SetNativeArrays(StringDexCacheType* strings,
211 uint32_t num_strings,
212 TypeDexCacheType* resolved_types,
213 uint32_t num_resolved_types,
214 MethodDexCacheType* resolved_methods,
215 uint32_t num_resolved_methods,
216 FieldDexCacheType* resolved_fields,
217 uint32_t num_resolved_fields,
218 MethodTypeDexCacheType* resolved_method_types,
219 uint32_t num_resolved_method_types,
220 GcRoot<CallSite>* resolved_call_sites,
221 uint32_t num_resolved_call_sites) {
222 CHECK_EQ(num_strings != 0u, strings != nullptr);
223 CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
224 CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
225 CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
226 CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr);
227 CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr);
228 SetStrings(strings);
229 SetResolvedTypes(resolved_types);
230 SetResolvedMethods(resolved_methods);
231 SetResolvedFields(resolved_fields);
232 SetResolvedMethodTypes(resolved_method_types);
233 SetResolvedCallSites(resolved_call_sites);
234 SetField32<false>(NumStringsOffset(), num_strings);
235 SetField32<false>(NumResolvedTypesOffset(), num_resolved_types);
236 SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods);
237 SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields);
238 SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types);
239 SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700240}
241
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700242void DexCache::SetLocation(ObjPtr<mirror::String> location) {
Mathieu Chartier76172162016-01-26 14:54:06 -0800243 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
244}
245
Andreas Gampe8a1a0f72020-03-03 16:07:45 -0800246void DexCache::SetClassLoader(ObjPtr<ClassLoader> class_loader) {
247 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, class_loader_), class_loader);
248}
249
Vladimir Marko41b605c2020-02-12 10:52:22 +0000250#if !defined(__aarch64__) && !defined(__x86_64__)
Vladimir Markof44d36c2017-03-14 14:18:46 +0000251static pthread_mutex_t dex_cache_slow_atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
252
253DexCache::ConversionPair64 DexCache::AtomicLoadRelaxed16B(std::atomic<ConversionPair64>* target) {
254 pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
255 DexCache::ConversionPair64 value = *reinterpret_cast<ConversionPair64*>(target);
256 pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
257 return value;
258}
259
260void DexCache::AtomicStoreRelease16B(std::atomic<ConversionPair64>* target,
261 ConversionPair64 value) {
262 pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
263 *reinterpret_cast<ConversionPair64*>(target) = value;
264 pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
265}
266#endif
267
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800268} // namespace mirror
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700269} // namespace art