blob: bef3ad29a326efb0788e258a5c8f79f9595e35de [file] [log] [blame]
Ian Rogers39ebcb82013-05-30 16:57:23 -07001/*
2 * Copyright (C) 2013 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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_
18#define ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_
Ian Rogers39ebcb82013-05-30 16:57:23 -070019
20#include "dex_cache.h"
21
Mathieu Chartierc7853442015-03-27 14:35:38 -070022#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070023#include "art_method-inl.h"
Vladimir Marko05792b92015-08-03 11:56:49 +010024#include "base/casts.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070025#include "base/enums.h"
Andreas Gampeaa910d52014-07-30 18:59:05 -070026#include "base/logging.h"
Narayan Kamathd08e39b2016-10-19 14:16:35 +010027#include "gc_root.h"
Andreas Gampeaa910d52014-07-30 18:59:05 -070028#include "mirror/class.h"
Narayan Kamath25352fc2016-08-03 12:46:58 +010029#include "mirror/method_type.h"
Mathieu Chartierbc56fc32014-06-03 15:37:03 -070030#include "runtime.h"
Mathieu Chartier31e88222016-10-14 18:43:19 -070031#include "obj_ptr.h"
Mathieu Chartierbc56fc32014-06-03 15:37:03 -070032
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -070033#include <atomic>
34
Ian Rogers39ebcb82013-05-30 16:57:23 -070035namespace art {
36namespace mirror {
37
Andreas Gampe542451c2016-07-26 09:02:02 -070038inline uint32_t DexCache::ClassSize(PointerSize pointer_size) {
Vladimir Markoc1363122015-04-09 14:13:13 +010039 uint32_t vtable_entries = Object::kVTableLength + 5;
Mathieu Chartiere401d142015-04-22 13:56:20 -070040 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
Ian Rogers39ebcb82013-05-30 16:57:23 -070041}
42
Vladimir Markoec786222016-12-20 16:24:13 +000043inline uint32_t DexCache::StringSlotIndex(dex::StringIndex string_idx) {
Andreas Gampe8a0128a2016-11-28 07:38:35 -080044 DCHECK_LT(string_idx.index_, GetDexFile()->NumStringIds());
Vladimir Markoec786222016-12-20 16:24:13 +000045 const uint32_t slot_idx = string_idx.index_ % kDexCacheStringCacheSize;
46 DCHECK_LT(slot_idx, NumStrings());
47 return slot_idx;
Andreas Gampeaa910d52014-07-30 18:59:05 -070048}
49
Vladimir Markoec786222016-12-20 16:24:13 +000050inline String* DexCache::GetResolvedString(dex::StringIndex string_idx) {
51 return GetStrings()[StringSlotIndex(string_idx)].load(
52 std::memory_order_relaxed).GetObjectForIndex(string_idx.index_);
53}
54
55inline void DexCache::SetResolvedString(dex::StringIndex string_idx, ObjPtr<String> resolved) {
56 DCHECK(resolved != nullptr);
57 GetStrings()[StringSlotIndex(string_idx)].store(
58 StringDexCachePair(resolved, string_idx.index_), std::memory_order_relaxed);
Mathieu Chartierbb816d62016-09-07 10:17:46 -070059 Runtime* const runtime = Runtime::Current();
60 if (UNLIKELY(runtime->IsActiveTransaction())) {
61 DCHECK(runtime->IsAotCompiler());
62 runtime->RecordResolveString(this, string_idx);
63 }
Vladimir Marko05792b92015-08-03 11:56:49 +010064 // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
Mathieu Chartierbb816d62016-09-07 10:17:46 -070065 runtime->GetHeap()->WriteBarrierEveryFieldOf(this);
66}
67
Andreas Gampe8a0128a2016-11-28 07:38:35 -080068inline void DexCache::ClearString(dex::StringIndex string_idx) {
Mathieu Chartierbb816d62016-09-07 10:17:46 -070069 DCHECK(Runtime::Current()->IsAotCompiler());
Vladimir Markoec786222016-12-20 16:24:13 +000070 uint32_t slot_idx = StringSlotIndex(string_idx);
Mathieu Chartierbb816d62016-09-07 10:17:46 -070071 StringDexCacheType* slot = &GetStrings()[slot_idx];
72 // This is racy but should only be called from the transactional interpreter.
Andreas Gampe8a0128a2016-11-28 07:38:35 -080073 if (slot->load(std::memory_order_relaxed).index == string_idx.index_) {
Vladimir Markoec786222016-12-20 16:24:13 +000074 StringDexCachePair cleared(nullptr, StringDexCachePair::InvalidIndexForSlot(slot_idx));
Mathieu Chartierbb816d62016-09-07 10:17:46 -070075 slot->store(cleared, std::memory_order_relaxed);
76 }
Vladimir Marko05792b92015-08-03 11:56:49 +010077}
78
Vladimir Markoec786222016-12-20 16:24:13 +000079inline uint32_t DexCache::TypeSlotIndex(dex::TypeIndex type_idx) {
80 DCHECK_LT(type_idx.index_, GetDexFile()->NumTypeIds());
81 const uint32_t slot_idx = type_idx.index_ % kDexCacheTypeCacheSize;
82 DCHECK_LT(slot_idx, NumResolvedTypes());
83 return slot_idx;
84}
85
Andreas Gampea5b09a62016-11-17 15:21:22 -080086inline Class* DexCache::GetResolvedType(dex::TypeIndex type_idx) {
Mathieu Chartier5df32d32016-12-06 16:02:27 -080087 // It is theorized that a load acquire is not required since obtaining the resolved class will
Mathieu Chartierdb70ce52016-12-12 11:06:59 -080088 // always have an address dependency or a lock.
Vladimir Markoec786222016-12-20 16:24:13 +000089 return GetResolvedTypes()[TypeSlotIndex(type_idx)].load(
90 std::memory_order_relaxed).GetObjectForIndex(type_idx.index_);
Vladimir Marko05792b92015-08-03 11:56:49 +010091}
92
Andreas Gampea5b09a62016-11-17 15:21:22 -080093inline void DexCache::SetResolvedType(dex::TypeIndex type_idx, ObjPtr<Class> resolved) {
Vladimir Markoec786222016-12-20 16:24:13 +000094 DCHECK(resolved != nullptr);
Vladimir Marko05792b92015-08-03 11:56:49 +010095 // TODO default transaction support.
Mathieu Chartier5df32d32016-12-06 16:02:27 -080096 // Use a release store for SetResolvedType. This is done to prevent other threads from seeing a
97 // class but not necessarily seeing the loaded members like the static fields array.
98 // See b/32075261.
Vladimir Markoec786222016-12-20 16:24:13 +000099 GetResolvedTypes()[TypeSlotIndex(type_idx)].store(
100 TypeDexCachePair(resolved, type_idx.index_), std::memory_order_release);
Vladimir Marko05792b92015-08-03 11:56:49 +0100101 // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
102 Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
103}
104
Vladimir Markoec786222016-12-20 16:24:13 +0000105inline void DexCache::ClearResolvedType(dex::TypeIndex type_idx) {
106 DCHECK(Runtime::Current()->IsAotCompiler());
107 uint32_t slot_idx = TypeSlotIndex(type_idx);
108 TypeDexCacheType* slot = &GetResolvedTypes()[slot_idx];
109 // This is racy but should only be called from the single-threaded ImageWriter and tests.
110 if (slot->load(std::memory_order_relaxed).index == type_idx.index_) {
111 TypeDexCachePair cleared(nullptr, TypeDexCachePair::InvalidIndexForSlot(slot_idx));
112 slot->store(cleared, std::memory_order_relaxed);
113 }
114}
115
116inline uint32_t DexCache::MethodTypeSlotIndex(uint32_t proto_idx) {
Narayan Kamath25352fc2016-08-03 12:46:58 +0100117 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
118 DCHECK_LT(proto_idx, GetDexFile()->NumProtoIds());
Vladimir Markoec786222016-12-20 16:24:13 +0000119 const uint32_t slot_idx = proto_idx % kDexCacheMethodTypeCacheSize;
120 DCHECK_LT(slot_idx, NumResolvedMethodTypes());
121 return slot_idx;
122}
123
124inline MethodType* DexCache::GetResolvedMethodType(uint32_t proto_idx) {
125 return GetResolvedMethodTypes()[MethodTypeSlotIndex(proto_idx)].load(
126 std::memory_order_relaxed).GetObjectForIndex(proto_idx);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100127}
128
129inline void DexCache::SetResolvedMethodType(uint32_t proto_idx, MethodType* resolved) {
Vladimir Markoec786222016-12-20 16:24:13 +0000130 DCHECK(resolved != nullptr);
131 GetResolvedMethodTypes()[MethodTypeSlotIndex(proto_idx)].store(
132 MethodTypeDexCachePair(resolved, proto_idx), std::memory_order_relaxed);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100133 // TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
134 Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
135}
136
Andreas Gampe542451c2016-07-26 09:02:02 -0700137inline ArtField* DexCache::GetResolvedField(uint32_t field_idx, PointerSize ptr_size) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700138 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
Vladimir Marko05792b92015-08-03 11:56:49 +0100139 DCHECK_LT(field_idx, NumResolvedFields()); // NOTE: Unchecked, i.e. not throwing AIOOB.
140 ArtField* field = GetElementPtrSize(GetResolvedFields(), field_idx, ptr_size);
Mathieu Chartierc7853442015-03-27 14:35:38 -0700141 if (field == nullptr || field->GetDeclaringClass()->IsErroneous()) {
142 return nullptr;
143 }
144 return field;
145}
146
Andreas Gampe542451c2016-07-26 09:02:02 -0700147inline void DexCache::SetResolvedField(uint32_t field_idx, ArtField* field, PointerSize ptr_size) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700148 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
Vladimir Marko05792b92015-08-03 11:56:49 +0100149 DCHECK_LT(field_idx, NumResolvedFields()); // NOTE: Unchecked, i.e. not throwing AIOOB.
150 SetElementPtrSize(GetResolvedFields(), field_idx, field, ptr_size);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700151}
152
Andreas Gampe542451c2016-07-26 09:02:02 -0700153inline ArtMethod* DexCache::GetResolvedMethod(uint32_t method_idx, PointerSize ptr_size) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700154 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
Vladimir Marko05792b92015-08-03 11:56:49 +0100155 DCHECK_LT(method_idx, NumResolvedMethods()); // NOTE: Unchecked, i.e. not throwing AIOOB.
156 ArtMethod* method = GetElementPtrSize<ArtMethod*>(GetResolvedMethods(), method_idx, ptr_size);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700157 // Hide resolution trampoline methods from the caller
158 if (method != nullptr && method->IsRuntimeMethod()) {
159 DCHECK_EQ(method, Runtime::Current()->GetResolutionMethod());
160 return nullptr;
Mathieu Chartierc7853442015-03-27 14:35:38 -0700161 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700162 return method;
163}
164
Andreas Gampe542451c2016-07-26 09:02:02 -0700165inline void DexCache::SetResolvedMethod(uint32_t method_idx,
166 ArtMethod* method,
167 PointerSize ptr_size) {
Mathieu Chartiere401d142015-04-22 13:56:20 -0700168 DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), ptr_size);
Vladimir Marko05792b92015-08-03 11:56:49 +0100169 DCHECK_LT(method_idx, NumResolvedMethods()); // NOTE: Unchecked, i.e. not throwing AIOOB.
170 SetElementPtrSize(GetResolvedMethods(), method_idx, method, ptr_size);
171}
172
173template <typename PtrType>
Andreas Gampe542451c2016-07-26 09:02:02 -0700174inline PtrType DexCache::GetElementPtrSize(PtrType* ptr_array, size_t idx, PointerSize ptr_size) {
175 if (ptr_size == PointerSize::k64) {
Vladimir Marko05792b92015-08-03 11:56:49 +0100176 uint64_t element = reinterpret_cast<const uint64_t*>(ptr_array)[idx];
177 return reinterpret_cast<PtrType>(dchecked_integral_cast<uintptr_t>(element));
178 } else {
Vladimir Marko05792b92015-08-03 11:56:49 +0100179 uint32_t element = reinterpret_cast<const uint32_t*>(ptr_array)[idx];
180 return reinterpret_cast<PtrType>(dchecked_integral_cast<uintptr_t>(element));
181 }
182}
183
184template <typename PtrType>
185inline void DexCache::SetElementPtrSize(PtrType* ptr_array,
186 size_t idx,
187 PtrType ptr,
Andreas Gampe542451c2016-07-26 09:02:02 -0700188 PointerSize ptr_size) {
189 if (ptr_size == PointerSize::k64) {
Vladimir Marko05792b92015-08-03 11:56:49 +0100190 reinterpret_cast<uint64_t*>(ptr_array)[idx] =
191 dchecked_integral_cast<uint64_t>(reinterpret_cast<uintptr_t>(ptr));
192 } else {
Vladimir Marko05792b92015-08-03 11:56:49 +0100193 reinterpret_cast<uint32_t*>(ptr_array)[idx] =
194 dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>(ptr));
195 }
196}
197
Narayan Kamathd08e39b2016-10-19 14:16:35 +0100198template <typename T,
199 ReadBarrierOption kReadBarrierOption,
200 typename Visitor>
201inline void VisitDexCachePairs(std::atomic<DexCachePair<T>>* pairs,
202 size_t num_pairs,
203 const Visitor& visitor)
204 REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) {
205 for (size_t i = 0; i < num_pairs; ++i) {
206 DexCachePair<T> source = pairs[i].load(std::memory_order_relaxed);
207 // NOTE: We need the "template" keyword here to avoid a compilation
208 // failure. GcRoot<T> is a template argument-dependent type and we need to
209 // tell the compiler to treat "Read" as a template rather than a field or
210 // function. Otherwise, on encountering the "<" token, the compiler would
211 // treat "Read" as a field.
Mathieu Chartier6b4c2872016-11-01 14:45:26 -0700212 T* const before = source.object.template Read<kReadBarrierOption>();
213 visitor.VisitRootIfNonNull(source.object.AddressWithoutBarrier());
214 if (source.object.template Read<kReadBarrierOption>() != before) {
Narayan Kamathd08e39b2016-10-19 14:16:35 +0100215 pairs[i].store(source, std::memory_order_relaxed);
216 }
217 }
218}
219
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800220template <bool kVisitNativeRoots,
221 VerifyObjectFlags kVerifyFlags,
222 ReadBarrierOption kReadBarrierOption,
223 typename Visitor>
Mathieu Chartier31e88222016-10-14 18:43:19 -0700224inline void DexCache::VisitReferences(ObjPtr<Class> klass, const Visitor& visitor) {
Vladimir Marko05792b92015-08-03 11:56:49 +0100225 // Visit instance fields first.
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800226 VisitInstanceFieldsReferences<kVerifyFlags, kReadBarrierOption>(klass, visitor);
Vladimir Marko05792b92015-08-03 11:56:49 +0100227 // Visit arrays after.
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800228 if (kVisitNativeRoots) {
Vladimir Markoec786222016-12-20 16:24:13 +0000229 VisitDexCachePairs<String, kReadBarrierOption, Visitor>(
Narayan Kamathd08e39b2016-10-19 14:16:35 +0100230 GetStrings(), NumStrings(), visitor);
231
Vladimir Markoec786222016-12-20 16:24:13 +0000232 VisitDexCachePairs<Class, kReadBarrierOption, Visitor>(
233 GetResolvedTypes(), NumResolvedTypes(), visitor);
Narayan Kamathd08e39b2016-10-19 14:16:35 +0100234
Vladimir Markoec786222016-12-20 16:24:13 +0000235 VisitDexCachePairs<MethodType, kReadBarrierOption, Visitor>(
Narayan Kamathd08e39b2016-10-19 14:16:35 +0100236 GetResolvedMethodTypes(), NumResolvedMethodTypes(), visitor);
Vladimir Marko05792b92015-08-03 11:56:49 +0100237 }
Mathieu Chartierc7853442015-03-27 14:35:38 -0700238}
239
Mathieu Chartier60bc39c2016-01-27 18:37:48 -0800240template <ReadBarrierOption kReadBarrierOption, typename Visitor>
Vladimir Markoec786222016-12-20 16:24:13 +0000241inline void DexCache::FixupStrings(StringDexCacheType* dest, const Visitor& visitor) {
242 StringDexCacheType* src = GetStrings();
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800243 for (size_t i = 0, count = NumStrings(); i < count; ++i) {
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700244 StringDexCachePair source = src[i].load(std::memory_order_relaxed);
Vladimir Markoec786222016-12-20 16:24:13 +0000245 String* ptr = source.object.Read<kReadBarrierOption>();
246 String* new_source = visitor(ptr);
Narayan Kamathc38a6f82016-09-29 17:07:20 +0100247 source.object = GcRoot<String>(new_source);
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700248 dest[i].store(source, std::memory_order_relaxed);
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800249 }
250}
251
Mathieu Chartier60bc39c2016-01-27 18:37:48 -0800252template <ReadBarrierOption kReadBarrierOption, typename Visitor>
Vladimir Markoec786222016-12-20 16:24:13 +0000253inline void DexCache::FixupResolvedTypes(TypeDexCacheType* dest, const Visitor& visitor) {
254 TypeDexCacheType* src = GetResolvedTypes();
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800255 for (size_t i = 0, count = NumResolvedTypes(); i < count; ++i) {
Vladimir Markoec786222016-12-20 16:24:13 +0000256 TypeDexCachePair source = src[i].load(std::memory_order_relaxed);
257 Class* ptr = source.object.Read<kReadBarrierOption>();
258 Class* new_source = visitor(ptr);
259 source.object = GcRoot<Class>(new_source);
260 dest[i].store(source, std::memory_order_relaxed);
Mathieu Chartier4b00d342015-11-13 10:42:08 -0800261 }
262}
263
Narayan Kamath7fe56582016-10-14 18:49:12 +0100264template <ReadBarrierOption kReadBarrierOption, typename Visitor>
Vladimir Markoec786222016-12-20 16:24:13 +0000265inline void DexCache::FixupResolvedMethodTypes(MethodTypeDexCacheType* dest,
Narayan Kamath7fe56582016-10-14 18:49:12 +0100266 const Visitor& visitor) {
Vladimir Markoec786222016-12-20 16:24:13 +0000267 MethodTypeDexCacheType* src = GetResolvedMethodTypes();
Narayan Kamath7fe56582016-10-14 18:49:12 +0100268 for (size_t i = 0, count = NumResolvedMethodTypes(); i < count; ++i) {
269 MethodTypeDexCachePair source = src[i].load(std::memory_order_relaxed);
Vladimir Markoec786222016-12-20 16:24:13 +0000270 MethodType* ptr = source.object.Read<kReadBarrierOption>();
271 MethodType* new_source = visitor(ptr);
Narayan Kamath7fe56582016-10-14 18:49:12 +0100272 source.object = GcRoot<MethodType>(new_source);
273 dest[i].store(source, std::memory_order_relaxed);
274 }
275}
276
Ian Rogers39ebcb82013-05-30 16:57:23 -0700277} // namespace mirror
278} // namespace art
279
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700280#endif // ART_RUNTIME_MIRROR_DEX_CACHE_INL_H_