blob: f6f20ba3ab6be7d58eabbaaaef49b38bda0ee2e9 [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"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080020#include "base/logging.h"
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -070021#include "class_linker.h"
Ian Rogers1d54e732013-05-02 21:10:01 -070022#include "gc/accounting/card_table-inl.h"
23#include "gc/heap.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070024#include "globals.h"
Andreas Gampecc1b5352016-12-01 16:58:38 -080025#include "linear_alloc.h"
Andreas Gampe2ff3b972017-06-05 18:14:53 -070026#include "oat_file.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080027#include "object-inl.h"
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070028#include "object.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029#include "object_array-inl.h"
30#include "runtime.h"
31#include "string.h"
Andreas Gampecc1b5352016-12-01 16:58:38 -080032#include "thread.h"
33#include "utils/dex_cache_arrays_layout-inl.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
Andreas Gampecc1b5352016-12-01 16:58:38 -080038void DexCache::InitializeDexCache(Thread* self,
39 ObjPtr<mirror::DexCache> dex_cache,
40 ObjPtr<mirror::String> location,
41 const DexFile* dex_file,
42 LinearAlloc* linear_alloc,
43 PointerSize image_pointer_size) {
44 DCHECK(dex_file != nullptr);
45 ScopedAssertNoThreadSuspension sants(__FUNCTION__);
46 DexCacheArraysLayout layout(image_pointer_size, dex_file);
47 uint8_t* raw_arrays = nullptr;
48
49 const OatDexFile* const oat_dex = dex_file->GetOatDexFile();
50 if (oat_dex != nullptr && oat_dex->GetDexCacheArrays() != nullptr) {
51 raw_arrays = oat_dex->GetDexCacheArrays();
52 } else if (dex_file->NumStringIds() != 0u ||
53 dex_file->NumTypeIds() != 0u ||
54 dex_file->NumMethodIds() != 0u ||
55 dex_file->NumFieldIds() != 0u) {
Vladimir Markof44d36c2017-03-14 14:18:46 +000056 static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8.");
57 DCHECK(layout.Alignment() == 8u || layout.Alignment() == 16u);
Andreas Gampecc1b5352016-12-01 16:58:38 -080058 // Zero-initialized.
Vladimir Markof44d36c2017-03-14 14:18:46 +000059 raw_arrays = (layout.Alignment() == 16u)
60 ? reinterpret_cast<uint8_t*>(linear_alloc->AllocAlign16(self, layout.Size()))
61 : reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
Andreas Gampecc1b5352016-12-01 16:58:38 -080062 }
63
Vladimir Marko07bfbac2017-07-06 14:55:02 +010064 StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr :
65 reinterpret_cast<StringDexCacheType*>(raw_arrays + layout.StringsOffset());
66 TypeDexCacheType* types = (dex_file->NumTypeIds() == 0u) ? nullptr :
67 reinterpret_cast<TypeDexCacheType*>(raw_arrays + layout.TypesOffset());
68 MethodDexCacheType* methods = (dex_file->NumMethodIds() == 0u) ? nullptr :
69 reinterpret_cast<MethodDexCacheType*>(raw_arrays + layout.MethodsOffset());
70 FieldDexCacheType* fields = (dex_file->NumFieldIds() == 0u) ? nullptr :
71 reinterpret_cast<FieldDexCacheType*>(raw_arrays + layout.FieldsOffset());
Andreas Gampecc1b5352016-12-01 16:58:38 -080072
Vladimir Markof44d36c2017-03-14 14:18:46 +000073 size_t num_strings = kDexCacheStringCacheSize;
Andreas Gampecc1b5352016-12-01 16:58:38 -080074 if (dex_file->NumStringIds() < num_strings) {
75 num_strings = dex_file->NumStringIds();
76 }
Vladimir Markof44d36c2017-03-14 14:18:46 +000077 size_t num_types = kDexCacheTypeCacheSize;
Vladimir Marko8d6768d2017-03-14 10:13:21 +000078 if (dex_file->NumTypeIds() < num_types) {
79 num_types = dex_file->NumTypeIds();
80 }
Vladimir Markof44d36c2017-03-14 14:18:46 +000081 size_t num_fields = kDexCacheFieldCacheSize;
82 if (dex_file->NumFieldIds() < num_fields) {
83 num_fields = dex_file->NumFieldIds();
84 }
Vladimir Marko07bfbac2017-07-06 14:55:02 +010085 size_t num_methods = kDexCacheMethodCacheSize;
86 if (dex_file->NumMethodIds() < num_methods) {
87 num_methods = dex_file->NumMethodIds();
88 }
Andreas Gampecc1b5352016-12-01 16:58:38 -080089
90 // Note that we allocate the method type dex caches regardless of this flag,
91 // and we make sure here that they're not used by the runtime. This is in the
92 // interest of simplicity and to avoid extensive compiler and layout class changes.
93 //
94 // If this needs to be mitigated in a production system running this code,
95 // DexCache::kDexCacheMethodTypeCacheSize can be set to zero.
Vladimir Markof44d36c2017-03-14 14:18:46 +000096 MethodTypeDexCacheType* method_types = nullptr;
Andreas Gampecc1b5352016-12-01 16:58:38 -080097 size_t num_method_types = 0;
98
Vladimir Markof44d36c2017-03-14 14:18:46 +000099 if (dex_file->NumProtoIds() < kDexCacheMethodTypeCacheSize) {
Andreas Gampecc1b5352016-12-01 16:58:38 -0800100 num_method_types = dex_file->NumProtoIds();
101 } else {
Vladimir Markof44d36c2017-03-14 14:18:46 +0000102 num_method_types = kDexCacheMethodTypeCacheSize;
Andreas Gampecc1b5352016-12-01 16:58:38 -0800103 }
104
105 if (num_method_types > 0) {
Vladimir Markof44d36c2017-03-14 14:18:46 +0000106 method_types = reinterpret_cast<MethodTypeDexCacheType*>(
Andreas Gampecc1b5352016-12-01 16:58:38 -0800107 raw_arrays + layout.MethodTypesOffset());
108 }
109
Orion Hodsonc069a302017-01-18 09:23:12 +0000110 GcRoot<mirror::CallSite>* call_sites = (dex_file->NumCallSiteIds() == 0)
111 ? nullptr
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100112 : reinterpret_cast<GcRoot<CallSite>*>(raw_arrays + layout.CallSitesOffset());
Orion Hodsonc069a302017-01-18 09:23:12 +0000113
Vladimir Markof44d36c2017-03-14 14:18:46 +0000114 DCHECK_ALIGNED(raw_arrays, alignof(StringDexCacheType)) <<
Andreas Gampecc1b5352016-12-01 16:58:38 -0800115 "Expected raw_arrays to align to StringDexCacheType.";
Vladimir Markof44d36c2017-03-14 14:18:46 +0000116 DCHECK_ALIGNED(layout.StringsOffset(), alignof(StringDexCacheType)) <<
Andreas Gampecc1b5352016-12-01 16:58:38 -0800117 "Expected StringsOffset() to align to StringDexCacheType.";
Vladimir Markof44d36c2017-03-14 14:18:46 +0000118 DCHECK_ALIGNED(strings, alignof(StringDexCacheType)) <<
Andreas Gampecc1b5352016-12-01 16:58:38 -0800119 "Expected strings to align to StringDexCacheType.";
Vladimir Markof44d36c2017-03-14 14:18:46 +0000120 static_assert(alignof(StringDexCacheType) == 8u,
Andreas Gampecc1b5352016-12-01 16:58:38 -0800121 "Expected StringDexCacheType to have align of 8.");
122 if (kIsDebugBuild) {
123 // Sanity check to make sure all the dex cache arrays are empty. b/28992179
124 for (size_t i = 0; i < num_strings; ++i) {
125 CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
126 CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
127 }
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000128 for (size_t i = 0; i < num_types; ++i) {
129 CHECK_EQ(types[i].load(std::memory_order_relaxed).index, 0u);
130 CHECK(types[i].load(std::memory_order_relaxed).object.IsNull());
Andreas Gampecc1b5352016-12-01 16:58:38 -0800131 }
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100132 for (size_t i = 0; i < num_methods; ++i) {
133 CHECK_EQ(GetNativePairPtrSize(methods, i, image_pointer_size).index, 0u);
134 CHECK(GetNativePairPtrSize(methods, i, image_pointer_size).object == nullptr);
Andreas Gampecc1b5352016-12-01 16:58:38 -0800135 }
Vladimir Markof44d36c2017-03-14 14:18:46 +0000136 for (size_t i = 0; i < num_fields; ++i) {
137 CHECK_EQ(GetNativePairPtrSize(fields, i, image_pointer_size).index, 0u);
138 CHECK(GetNativePairPtrSize(fields, i, image_pointer_size).object == nullptr);
Andreas Gampecc1b5352016-12-01 16:58:38 -0800139 }
140 for (size_t i = 0; i < num_method_types; ++i) {
141 CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
142 CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull());
143 }
Orion Hodsonc069a302017-01-18 09:23:12 +0000144 for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) {
145 CHECK(call_sites[i].IsNull());
146 }
Andreas Gampecc1b5352016-12-01 16:58:38 -0800147 }
148 if (strings != nullptr) {
149 mirror::StringDexCachePair::Initialize(strings);
150 }
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000151 if (types != nullptr) {
152 mirror::TypeDexCachePair::Initialize(types);
153 }
Vladimir Markof44d36c2017-03-14 14:18:46 +0000154 if (fields != nullptr) {
155 mirror::FieldDexCachePair::Initialize(fields, image_pointer_size);
156 }
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100157 if (methods != nullptr) {
158 mirror::MethodDexCachePair::Initialize(methods, image_pointer_size);
159 }
Andreas Gampecc1b5352016-12-01 16:58:38 -0800160 if (method_types != nullptr) {
161 mirror::MethodTypeDexCachePair::Initialize(method_types);
162 }
163 dex_cache->Init(dex_file,
164 location,
165 strings,
166 num_strings,
167 types,
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000168 num_types,
Andreas Gampecc1b5352016-12-01 16:58:38 -0800169 methods,
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100170 num_methods,
Andreas Gampecc1b5352016-12-01 16:58:38 -0800171 fields,
Vladimir Markof44d36c2017-03-14 14:18:46 +0000172 num_fields,
Andreas Gampecc1b5352016-12-01 16:58:38 -0800173 method_types,
174 num_method_types,
Orion Hodsonc069a302017-01-18 09:23:12 +0000175 call_sites,
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100176 dex_file->NumCallSiteIds());
Andreas Gampecc1b5352016-12-01 16:58:38 -0800177}
178
Vladimir Marko05792b92015-08-03 11:56:49 +0100179void DexCache::Init(const DexFile* dex_file,
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700180 ObjPtr<String> location,
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700181 StringDexCacheType* strings,
Vladimir Marko05792b92015-08-03 11:56:49 +0100182 uint32_t num_strings,
Vladimir Marko8d6768d2017-03-14 10:13:21 +0000183 TypeDexCacheType* resolved_types,
Vladimir Marko05792b92015-08-03 11:56:49 +0100184 uint32_t num_resolved_types,
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100185 MethodDexCacheType* resolved_methods,
Vladimir Marko05792b92015-08-03 11:56:49 +0100186 uint32_t num_resolved_methods,
Vladimir Markof44d36c2017-03-14 14:18:46 +0000187 FieldDexCacheType* resolved_fields,
Vladimir Marko05792b92015-08-03 11:56:49 +0100188 uint32_t num_resolved_fields,
Narayan Kamath25352fc2016-08-03 12:46:58 +0100189 MethodTypeDexCacheType* resolved_method_types,
190 uint32_t num_resolved_method_types,
Orion Hodsonc069a302017-01-18 09:23:12 +0000191 GcRoot<CallSite>* resolved_call_sites,
Vladimir Marko07bfbac2017-07-06 14:55:02 +0100192 uint32_t num_resolved_call_sites) {
Ian Rogers5ddb4102014-01-07 08:58:46 -0800193 CHECK(dex_file != nullptr);
194 CHECK(location != nullptr);
Vladimir Marko05792b92015-08-03 11:56:49 +0100195 CHECK_EQ(num_strings != 0u, strings != nullptr);
196 CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
197 CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
198 CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100199 CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr);
Orion Hodsonc069a302017-01-18 09:23:12 +0000200 CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr);
Mathieu Chartier66f19252012-09-18 08:57:04 -0700201
Mathieu Chartierc7853442015-03-27 14:35:38 -0700202 SetDexFile(dex_file);
Mathieu Chartier76172162016-01-26 14:54:06 -0800203 SetLocation(location);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800204 SetStrings(strings);
205 SetResolvedTypes(resolved_types);
206 SetResolvedMethods(resolved_methods);
207 SetResolvedFields(resolved_fields);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100208 SetResolvedMethodTypes(resolved_method_types);
Orion Hodsonc069a302017-01-18 09:23:12 +0000209 SetResolvedCallSites(resolved_call_sites);
Vladimir Marko05792b92015-08-03 11:56:49 +0100210 SetField32<false>(NumStringsOffset(), num_strings);
211 SetField32<false>(NumResolvedTypesOffset(), num_resolved_types);
212 SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods);
213 SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100214 SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types);
Orion Hodsonc069a302017-01-18 09:23:12 +0000215 SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites);
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700216}
217
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700218void DexCache::SetLocation(ObjPtr<mirror::String> location) {
Mathieu Chartier76172162016-01-26 14:54:06 -0800219 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
220}
221
Alexey Frunze279cfba2017-07-22 00:24:43 -0700222#if !defined(__aarch64__) && !defined(__x86_64__) && !defined(__mips__)
Vladimir Markof44d36c2017-03-14 14:18:46 +0000223static pthread_mutex_t dex_cache_slow_atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
224
225DexCache::ConversionPair64 DexCache::AtomicLoadRelaxed16B(std::atomic<ConversionPair64>* target) {
226 pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
227 DexCache::ConversionPair64 value = *reinterpret_cast<ConversionPair64*>(target);
228 pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
229 return value;
230}
231
232void DexCache::AtomicStoreRelease16B(std::atomic<ConversionPair64>* target,
233 ConversionPair64 value) {
234 pthread_mutex_lock(&dex_cache_slow_atomic_mutex);
235 *reinterpret_cast<ConversionPair64*>(target) = value;
236 pthread_mutex_unlock(&dex_cache_slow_atomic_mutex);
237}
238#endif
239
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800240} // namespace mirror
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700241} // namespace art