blob: 0f6acab7e1afe4e6da2e6443e5e4f184dcc5d0aa [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"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070026#include "object.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080027#include "object-inl.h"
28#include "object_array-inl.h"
29#include "runtime.h"
30#include "string.h"
Andreas Gampecc1b5352016-12-01 16:58:38 -080031#include "thread.h"
32#include "utils/dex_cache_arrays_layout-inl.h"
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070033
34namespace art {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080035namespace mirror {
Brian Carlstrom7e49dca2011-07-22 18:07:34 -070036
Andreas Gampecc1b5352016-12-01 16:58:38 -080037void 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 // Zero-initialized.
Vladimir Marko6374c582017-03-13 14:51:19 +000056 raw_arrays = reinterpret_cast<uint8_t*>(linear_alloc->Alloc(self, layout.Size()));
Andreas Gampecc1b5352016-12-01 16:58:38 -080057 }
58
59 mirror::StringDexCacheType* strings = (dex_file->NumStringIds() == 0u) ? nullptr :
60 reinterpret_cast<mirror::StringDexCacheType*>(raw_arrays + layout.StringsOffset());
Vladimir Marko0b66d612017-03-13 14:50:04 +000061 GcRoot<mirror::Class>* types = (dex_file->NumTypeIds() == 0u) ? nullptr :
62 reinterpret_cast<GcRoot<mirror::Class>*>(raw_arrays + layout.TypesOffset());
Andreas Gampecc1b5352016-12-01 16:58:38 -080063 ArtMethod** methods = (dex_file->NumMethodIds() == 0u) ? nullptr :
64 reinterpret_cast<ArtMethod**>(raw_arrays + layout.MethodsOffset());
Vladimir Marko6374c582017-03-13 14:51:19 +000065 ArtField** fields = (dex_file->NumFieldIds() == 0u) ? nullptr :
66 reinterpret_cast<ArtField**>(raw_arrays + layout.FieldsOffset());
Andreas Gampecc1b5352016-12-01 16:58:38 -080067
Vladimir Marko6374c582017-03-13 14:51:19 +000068 size_t num_strings = mirror::DexCache::kDexCacheStringCacheSize;
Andreas Gampecc1b5352016-12-01 16:58:38 -080069 if (dex_file->NumStringIds() < num_strings) {
70 num_strings = dex_file->NumStringIds();
71 }
72
73 // Note that we allocate the method type dex caches regardless of this flag,
74 // and we make sure here that they're not used by the runtime. This is in the
75 // interest of simplicity and to avoid extensive compiler and layout class changes.
76 //
77 // If this needs to be mitigated in a production system running this code,
78 // DexCache::kDexCacheMethodTypeCacheSize can be set to zero.
Vladimir Marko6374c582017-03-13 14:51:19 +000079 mirror::MethodTypeDexCacheType* method_types = nullptr;
Andreas Gampecc1b5352016-12-01 16:58:38 -080080 size_t num_method_types = 0;
81
Vladimir Marko6374c582017-03-13 14:51:19 +000082 if (dex_file->NumProtoIds() < mirror::DexCache::kDexCacheMethodTypeCacheSize) {
Andreas Gampecc1b5352016-12-01 16:58:38 -080083 num_method_types = dex_file->NumProtoIds();
84 } else {
Vladimir Marko6374c582017-03-13 14:51:19 +000085 num_method_types = mirror::DexCache::kDexCacheMethodTypeCacheSize;
Andreas Gampecc1b5352016-12-01 16:58:38 -080086 }
87
88 if (num_method_types > 0) {
Vladimir Marko6374c582017-03-13 14:51:19 +000089 method_types = reinterpret_cast<mirror::MethodTypeDexCacheType*>(
Andreas Gampecc1b5352016-12-01 16:58:38 -080090 raw_arrays + layout.MethodTypesOffset());
91 }
92
Orion Hodsonc069a302017-01-18 09:23:12 +000093 GcRoot<mirror::CallSite>* call_sites = (dex_file->NumCallSiteIds() == 0)
94 ? nullptr
95 : reinterpret_cast<GcRoot<mirror::CallSite>*>(raw_arrays + layout.CallSitesOffset());
96
Vladimir Marko6374c582017-03-13 14:51:19 +000097 DCHECK_ALIGNED(raw_arrays, alignof(mirror::StringDexCacheType)) <<
Andreas Gampecc1b5352016-12-01 16:58:38 -080098 "Expected raw_arrays to align to StringDexCacheType.";
Vladimir Marko6374c582017-03-13 14:51:19 +000099 DCHECK_ALIGNED(layout.StringsOffset(), alignof(mirror::StringDexCacheType)) <<
Andreas Gampecc1b5352016-12-01 16:58:38 -0800100 "Expected StringsOffset() to align to StringDexCacheType.";
Vladimir Marko6374c582017-03-13 14:51:19 +0000101 DCHECK_ALIGNED(strings, alignof(mirror::StringDexCacheType)) <<
Andreas Gampecc1b5352016-12-01 16:58:38 -0800102 "Expected strings to align to StringDexCacheType.";
Vladimir Marko6374c582017-03-13 14:51:19 +0000103 static_assert(alignof(mirror::StringDexCacheType) == 8u,
Andreas Gampecc1b5352016-12-01 16:58:38 -0800104 "Expected StringDexCacheType to have align of 8.");
105 if (kIsDebugBuild) {
106 // Sanity check to make sure all the dex cache arrays are empty. b/28992179
107 for (size_t i = 0; i < num_strings; ++i) {
108 CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u);
109 CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull());
110 }
Vladimir Marko0b66d612017-03-13 14:50:04 +0000111 for (size_t i = 0; i < dex_file->NumTypeIds(); ++i) {
112 CHECK(types[i].IsNull());
Andreas Gampecc1b5352016-12-01 16:58:38 -0800113 }
114 for (size_t i = 0; i < dex_file->NumMethodIds(); ++i) {
Vladimir Marko6374c582017-03-13 14:51:19 +0000115 CHECK(mirror::DexCache::GetElementPtrSize(methods, i, image_pointer_size) == nullptr);
Andreas Gampecc1b5352016-12-01 16:58:38 -0800116 }
Vladimir Marko6374c582017-03-13 14:51:19 +0000117 for (size_t i = 0; i < dex_file->NumFieldIds(); ++i) {
118 CHECK(mirror::DexCache::GetElementPtrSize(fields, i, image_pointer_size) == nullptr);
Andreas Gampecc1b5352016-12-01 16:58:38 -0800119 }
120 for (size_t i = 0; i < num_method_types; ++i) {
121 CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u);
122 CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull());
123 }
Orion Hodsonc069a302017-01-18 09:23:12 +0000124 for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) {
125 CHECK(call_sites[i].IsNull());
126 }
Andreas Gampecc1b5352016-12-01 16:58:38 -0800127 }
128 if (strings != nullptr) {
129 mirror::StringDexCachePair::Initialize(strings);
130 }
131 if (method_types != nullptr) {
132 mirror::MethodTypeDexCachePair::Initialize(method_types);
133 }
134 dex_cache->Init(dex_file,
135 location,
136 strings,
137 num_strings,
138 types,
Vladimir Marko0b66d612017-03-13 14:50:04 +0000139 dex_file->NumTypeIds(),
Andreas Gampecc1b5352016-12-01 16:58:38 -0800140 methods,
141 dex_file->NumMethodIds(),
142 fields,
Vladimir Marko6374c582017-03-13 14:51:19 +0000143 dex_file->NumFieldIds(),
Andreas Gampecc1b5352016-12-01 16:58:38 -0800144 method_types,
145 num_method_types,
Orion Hodsonc069a302017-01-18 09:23:12 +0000146 call_sites,
147 dex_file->NumCallSiteIds(),
Andreas Gampecc1b5352016-12-01 16:58:38 -0800148 image_pointer_size);
149}
150
Vladimir Marko05792b92015-08-03 11:56:49 +0100151void DexCache::Init(const DexFile* dex_file,
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700152 ObjPtr<String> location,
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700153 StringDexCacheType* strings,
Vladimir Marko05792b92015-08-03 11:56:49 +0100154 uint32_t num_strings,
Vladimir Marko0b66d612017-03-13 14:50:04 +0000155 GcRoot<Class>* resolved_types,
Vladimir Marko05792b92015-08-03 11:56:49 +0100156 uint32_t num_resolved_types,
157 ArtMethod** resolved_methods,
158 uint32_t num_resolved_methods,
Vladimir Marko6374c582017-03-13 14:51:19 +0000159 ArtField** resolved_fields,
Vladimir Marko05792b92015-08-03 11:56:49 +0100160 uint32_t num_resolved_fields,
Narayan Kamath25352fc2016-08-03 12:46:58 +0100161 MethodTypeDexCacheType* resolved_method_types,
162 uint32_t num_resolved_method_types,
Orion Hodsonc069a302017-01-18 09:23:12 +0000163 GcRoot<CallSite>* resolved_call_sites,
164 uint32_t num_resolved_call_sites,
Andreas Gampe542451c2016-07-26 09:02:02 -0700165 PointerSize pointer_size) {
Ian Rogers5ddb4102014-01-07 08:58:46 -0800166 CHECK(dex_file != nullptr);
167 CHECK(location != nullptr);
Vladimir Marko05792b92015-08-03 11:56:49 +0100168 CHECK_EQ(num_strings != 0u, strings != nullptr);
169 CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr);
170 CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr);
171 CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100172 CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr);
Orion Hodsonc069a302017-01-18 09:23:12 +0000173 CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr);
Mathieu Chartier66f19252012-09-18 08:57:04 -0700174
Mathieu Chartierc7853442015-03-27 14:35:38 -0700175 SetDexFile(dex_file);
Mathieu Chartier76172162016-01-26 14:54:06 -0800176 SetLocation(location);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800177 SetStrings(strings);
178 SetResolvedTypes(resolved_types);
179 SetResolvedMethods(resolved_methods);
180 SetResolvedFields(resolved_fields);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100181 SetResolvedMethodTypes(resolved_method_types);
Orion Hodsonc069a302017-01-18 09:23:12 +0000182 SetResolvedCallSites(resolved_call_sites);
Vladimir Marko05792b92015-08-03 11:56:49 +0100183 SetField32<false>(NumStringsOffset(), num_strings);
184 SetField32<false>(NumResolvedTypesOffset(), num_resolved_types);
185 SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods);
186 SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields);
Narayan Kamath25352fc2016-08-03 12:46:58 +0100187 SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types);
Orion Hodsonc069a302017-01-18 09:23:12 +0000188 SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites);
Brian Carlstromaded5f72011-10-07 17:15:04 -0700189
Mathieu Chartiere401d142015-04-22 13:56:20 -0700190 Runtime* const runtime = Runtime::Current();
Ian Rogers19846512012-02-24 11:42:47 -0800191 if (runtime->HasResolutionMethod()) {
192 // Initialize the resolve methods array to contain trampolines for resolution.
Mathieu Chartiere401d142015-04-22 13:56:20 -0700193 Fixup(runtime->GetResolutionMethod(), pointer_size);
Ian Rogers19846512012-02-24 11:42:47 -0800194 }
195}
196
Andreas Gampe542451c2016-07-26 09:02:02 -0700197void DexCache::Fixup(ArtMethod* trampoline, PointerSize pointer_size) {
Ian Rogers19846512012-02-24 11:42:47 -0800198 // Fixup the resolve methods array to contain trampoline for resolution.
Ian Rogers5ddb4102014-01-07 08:58:46 -0800199 CHECK(trampoline != nullptr);
Mathieu Chartiere401d142015-04-22 13:56:20 -0700200 CHECK(trampoline->IsRuntimeMethod());
201 auto* resolved_methods = GetResolvedMethods();
Vladimir Marko05792b92015-08-03 11:56:49 +0100202 for (size_t i = 0, length = NumResolvedMethods(); i < length; i++) {
203 if (GetElementPtrSize<ArtMethod*>(resolved_methods, i, pointer_size) == nullptr) {
204 SetElementPtrSize(resolved_methods, i, trampoline, pointer_size);
Brian Carlstromaded5f72011-10-07 17:15:04 -0700205 }
206 }
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700207}
208
Mathieu Chartier28357fa2016-10-18 16:27:40 -0700209void DexCache::SetLocation(ObjPtr<mirror::String> location) {
Mathieu Chartier76172162016-01-26 14:54:06 -0800210 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location);
211}
212
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800213} // namespace mirror
Brian Carlstrom7e49dca2011-07-22 18:07:34 -0700214} // namespace art