2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "dex_cache-inl.h"
19 #include "art_method-inl.h"
20 #include "base/logging.h"
21 #include "class_linker.h"
22 #include "gc/accounting/card_table-inl.h"
25 #include "linear_alloc.h"
27 #include "object-inl.h"
28 #include "object_array-inl.h"
32 #include "utils/dex_cache_arrays_layout-inl.h"
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;
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) {
56 raw_arrays = reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
59 mirror::StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr :
60 reinterpret_cast<mirror::StringDexCacheType*>(raw_arrays + layout.StringsOffset());
61 mirror::TypeDexCacheType* types = (dex_file->NumTypeIds() == 0u) ? nullptr :
62 reinterpret_cast<mirror::TypeDexCacheType*>(raw_arrays + layout.TypesOffset());
63 ArtMethod** methods = (dex_file->NumMethodIds() == 0u) ? nullptr :
64 reinterpret_cast<ArtMethod**>(raw_arrays + layout.MethodsOffset());
65 ArtField** fields = (dex_file->NumFieldIds() == 0u) ? nullptr :
66 reinterpret_cast<ArtField**>(raw_arrays + layout.FieldsOffset());
68 size_t num_strings = mirror::DexCache::kDexCacheStringCacheSize;
69 if (dex_file->NumStringIds() < num_strings) {
70 num_strings = dex_file->NumStringIds();
72 size_t num_types = mirror::DexCache::kDexCacheTypeCacheSize;
73 if (dex_file->NumTypeIds() < num_types) {
74 num_types = dex_file->NumTypeIds();
77 // Note that we allocate the method type dex caches regardless of this flag,
78 // and we make sure here that they're not used by the runtime. This is in the
79 // interest of simplicity and to avoid extensive compiler and layout class changes.
81 // If this needs to be mitigated in a production system running this code,
82 // DexCache::kDexCacheMethodTypeCacheSize can be set to zero.
83 mirror::MethodTypeDexCacheType* method_types = nullptr;
84 size_t num_method_types = 0;
86 if (dex_file->NumProtoIds() < mirror::DexCache::kDexCacheMethodTypeCacheSize) {
87 num_method_types = dex_file->NumProtoIds();
89 num_method_types = mirror::DexCache::kDexCacheMethodTypeCacheSize;
92 if (num_method_types > 0) {
93 method_types = reinterpret_cast<mirror::MethodTypeDexCacheType*>(
94 raw_arrays + layout.MethodTypesOffset());
97 GcRoot<mirror::CallSite>* call_sites = (dex_file->NumCallSiteIds() == 0)
99 : reinterpret_cast<GcRoot<mirror::CallSite>*>(raw_arrays + layout.CallSitesOffset());
101 DCHECK_ALIGNED(raw_arrays, alignof(mirror::StringDexCacheType)) <<
102 "Expected raw_arrays to align to StringDexCacheType.";
103 DCHECK_ALIGNED(layout.StringsOffset(), alignof(mirror::StringDexCacheType)) <<
104 "Expected StringsOffset() to align to StringDexCacheType.";
105 DCHECK_ALIGNED(strings, alignof(mirror::StringDexCacheType)) <<
106 "Expected strings to align to StringDexCacheType.";
107 static_assert(alignof(mirror::StringDexCacheType) == 8u,
108 "Expected StringDexCacheType to have align of 8.");
110 // Sanity check to make sure all the dex cache arrays are empty. b/28992179
111 for (size_t i = 0; i < num_strings; ++i) {
112 CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
113 CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
115 for (size_t i = 0; i < num_types; ++i) {
116 CHECK_EQ(types[i].load(std::memory_order_relaxed).index, 0u);
117 CHECK(types[i].load(std::memory_order_relaxed).object.IsNull());
119 for (size_t i = 0; i < dex_file->NumMethodIds(); ++i) {
120 CHECK(mirror::DexCache::GetElementPtrSize(methods, i, image_pointer_size) == nullptr);
122 for (size_t i = 0; i < dex_file->NumFieldIds(); ++i) {
123 CHECK(mirror::DexCache::GetElementPtrSize(fields, i, image_pointer_size) == nullptr);
125 for (size_t i = 0; i < num_method_types; ++i) {
126 CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
127 CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull());
129 for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) {
130 CHECK(call_sites[i].IsNull());
133 if (strings != nullptr) {
134 mirror::StringDexCachePair::Initialize(strings);
136 if (types != nullptr) {
137 mirror::TypeDexCachePair::Initialize(types);
139 if (method_types != nullptr) {
140 mirror::MethodTypeDexCachePair::Initialize(method_types);
142 dex_cache->Init(dex_file,
149 dex_file->NumMethodIds(),
151 dex_file->NumFieldIds(),
155 dex_file->NumCallSiteIds(),
159 void DexCache::Init(const DexFile* dex_file,
160 ObjPtr<String> location,
161 StringDexCacheType* strings,
162 uint32_t num_strings,
163 TypeDexCacheType* resolved_types,
164 uint32_t num_resolved_types,
165 ArtMethod** resolved_methods,
166 uint32_t num_resolved_methods,
167 ArtField** resolved_fields,
168 uint32_t num_resolved_fields,
169 MethodTypeDexCacheType* resolved_method_types,
170 uint32_t num_resolved_method_types,
171 GcRoot<CallSite>* resolved_call_sites,
172 uint32_t num_resolved_call_sites,
173 PointerSize pointer_size) {
174 CHECK(dex_file != nullptr);
175 CHECK(location != nullptr);
176 CHECK_EQ(num_strings != 0u, strings != nullptr);
177 CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
178 CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
179 CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
180 CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr);
181 CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr);
183 SetDexFile(dex_file);
184 SetLocation(location);
186 SetResolvedTypes(resolved_types);
187 SetResolvedMethods(resolved_methods);
188 SetResolvedFields(resolved_fields);
189 SetResolvedMethodTypes(resolved_method_types);
190 SetResolvedCallSites(resolved_call_sites);
191 SetField32<false>(NumStringsOffset(), num_strings);
192 SetField32<false>(NumResolvedTypesOffset(), num_resolved_types);
193 SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods);
194 SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields);
195 SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types);
196 SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites);
198 Runtime* const runtime = Runtime::Current();
199 if (runtime->HasResolutionMethod()) {
200 // Initialize the resolve methods array to contain trampolines for resolution.
201 Fixup(runtime->GetResolutionMethod(), pointer_size);
205 void DexCache::Fixup(ArtMethod* trampoline, PointerSize pointer_size) {
206 // Fixup the resolve methods array to contain trampoline for resolution.
207 CHECK(trampoline != nullptr);
208 CHECK(trampoline->IsRuntimeMethod());
209 auto* resolved_methods = GetResolvedMethods();
210 for (size_t i = 0, length = NumResolvedMethods(); i < length; i++) {
211 if (GetElementPtrSize<ArtMethod*>(resolved_methods, i, pointer_size) == nullptr) {
212 SetElementPtrSize(resolved_methods, i, trampoline, pointer_size);
217 void DexCache::SetLocation(ObjPtr<mirror::String> location) {
218 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
221 } // namespace mirror