1 /* 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 */ 16 17 #include "dex_cache-inl.h" 18 19 #include "art_method-inl.h" 20 #include "base/logging.h" 21 #include "class_linker.h" 22 #include "gc/accounting/card_table-inl.h" 23 #include "gc/heap.h" 24 #include "globals.h" 25 #include "linear_alloc.h" 26 #include "oat_file.h" 27 #include "object.h" 28 #include "object-inl.h" 29 #include "object_array-inl.h" 30 #include "runtime.h" 31 #include "string.h" 32 #include "thread.h" 33 #include "utils/dex_cache_arrays_layout-inl.h" 34 35 namespace art { 36 namespace mirror { 37 38 void 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) { 56 static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8."); 57 DCHECK(layout.Alignment() == 8u || layout.Alignment() == 16u); 58 // Zero-initialized. 59 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())); 62 } 63 64 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()); 72 73 size_t num_strings = kDexCacheStringCacheSize; 74 if (dex_file->NumStringIds() < num_strings) { 75 num_strings = dex_file->NumStringIds(); 76 } 77 size_t num_types = kDexCacheTypeCacheSize; 78 if (dex_file->NumTypeIds() < num_types) { 79 num_types = dex_file->NumTypeIds(); 80 } 81 size_t num_fields = kDexCacheFieldCacheSize; 82 if (dex_file->NumFieldIds() < num_fields) { 83 num_fields = dex_file->NumFieldIds(); 84 } 85 size_t num_methods = kDexCacheMethodCacheSize; 86 if (dex_file->NumMethodIds() < num_methods) { 87 num_methods = dex_file->NumMethodIds(); 88 } 89 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. 96 MethodTypeDexCacheType* method_types = nullptr; 97 size_t num_method_types = 0; 98 99 if (dex_file->NumProtoIds() < kDexCacheMethodTypeCacheSize) { 100 num_method_types = dex_file->NumProtoIds(); 101 } else { 102 num_method_types = kDexCacheMethodTypeCacheSize; 103 } 104 105 if (num_method_types > 0) { 106 method_types = reinterpret_cast<MethodTypeDexCacheType*>( 107 raw_arrays + layout.MethodTypesOffset()); 108 } 109 110 GcRoot<mirror::CallSite>* call_sites = (dex_file->NumCallSiteIds() == 0) 111 ? nullptr 112 : reinterpret_cast<GcRoot<CallSite>*>(raw_arrays + layout.CallSitesOffset()); 113 114 DCHECK_ALIGNED(raw_arrays, alignof(StringDexCacheType)) << 115 "Expected raw_arrays to align to StringDexCacheType."; 116 DCHECK_ALIGNED(layout.StringsOffset(), alignof(StringDexCacheType)) << 117 "Expected StringsOffset() to align to StringDexCacheType."; 118 DCHECK_ALIGNED(strings, alignof(StringDexCacheType)) << 119 "Expected strings to align to StringDexCacheType."; 120 static_assert(alignof(StringDexCacheType) == 8u, 121 "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 } 128 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()); 131 } 132 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); 135 } 136 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); 139 } 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 } 144 for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) { 145 CHECK(call_sites[i].IsNull()); 146 } 147 } 148 if (strings != nullptr) { 149 mirror::StringDexCachePair::Initialize(strings); 150 } 151 if (types != nullptr) { 152 mirror::TypeDexCachePair::Initialize(types); 153 } 154 if (fields != nullptr) { 155 mirror::FieldDexCachePair::Initialize(fields, image_pointer_size); 156 } 157 if (methods != nullptr) { 158 mirror::MethodDexCachePair::Initialize(methods, image_pointer_size); 159 } 160 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, 168 num_types, 169 methods, 170 num_methods, 171 fields, 172 num_fields, 173 method_types, 174 num_method_types, 175 call_sites, 176 dex_file->NumCallSiteIds()); 177 } 178 179 void DexCache::Init(const DexFile* dex_file, 180 ObjPtr<String> location, 181 StringDexCacheType* strings, 182 uint32_t num_strings, 183 TypeDexCacheType* resolved_types, 184 uint32_t num_resolved_types, 185 MethodDexCacheType* resolved_methods, 186 uint32_t num_resolved_methods, 187 FieldDexCacheType* resolved_fields, 188 uint32_t num_resolved_fields, 189 MethodTypeDexCacheType* resolved_method_types, 190 uint32_t num_resolved_method_types, 191 GcRoot<CallSite>* resolved_call_sites, 192 uint32_t num_resolved_call_sites) { 193 CHECK(dex_file != nullptr); 194 CHECK(location != nullptr); 195 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); 199 CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr); 200 CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr); 201 202 SetDexFile(dex_file); 203 SetLocation(location); 204 SetStrings(strings); 205 SetResolvedTypes(resolved_types); 206 SetResolvedMethods(resolved_methods); 207 SetResolvedFields(resolved_fields); 208 SetResolvedMethodTypes(resolved_method_types); 209 SetResolvedCallSites(resolved_call_sites); 210 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); 214 SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types); 215 SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites); 216 } 217 218 void DexCache::SetLocation(ObjPtr<mirror::String> location) { 219 SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, location_), location); 220 } 221 222 #if !defined(__aarch64__) && !defined(__x86_64__) 223 static pthread_mutex_t dex_cache_slow_atomic_mutex = PTHREAD_MUTEX_INITIALIZER; 224 225 DexCache::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 232 void 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 240 } // namespace mirror 241 } // namespace art 242