diff options
Diffstat (limited to 'runtime/mirror/dex_cache.cc')
-rw-r--r-- | runtime/mirror/dex_cache.cc | 167 |
1 files changed, 148 insertions, 19 deletions
diff --git a/runtime/mirror/dex_cache.cc b/runtime/mirror/dex_cache.cc index fda827d59e..1b9558e6df 100644 --- a/runtime/mirror/dex_cache.cc +++ b/runtime/mirror/dex_cache.cc @@ -35,7 +35,15 @@ namespace art { namespace mirror { -void DexCache::Initialize(const DexFile* dex_file, ObjPtr<ClassLoader> class_loader) { +template<typename T> +static T* AllocArray(Thread* self, LinearAlloc* alloc, size_t num) { + if (num == 0) { + return nullptr; + } + return reinterpret_cast<T*>(alloc->AllocAlign16(self, RoundUp(num * sizeof(T), 16))); +} + +void DexCache::InitializeNativeFields(const DexFile* dex_file, LinearAlloc* linear_alloc) { DCHECK(GetDexFile() == nullptr); DCHECK(GetStrings() == nullptr); DCHECK(GetResolvedTypes() == nullptr); @@ -45,9 +53,94 @@ void DexCache::Initialize(const DexFile* dex_file, ObjPtr<ClassLoader> class_loa DCHECK(GetResolvedCallSites() == nullptr); ScopedAssertNoThreadSuspension sants(__FUNCTION__); + Thread* self = Thread::Current(); + + size_t num_strings = std::min<size_t>(kDexCacheStringCacheSize, dex_file->NumStringIds()); + size_t num_types = std::min<size_t>(kDexCacheTypeCacheSize, dex_file->NumTypeIds()); + size_t num_fields = std::min<size_t>(kDexCacheFieldCacheSize, dex_file->NumFieldIds()); + size_t num_methods = std::min<size_t>(kDexCacheMethodCacheSize, dex_file->NumMethodIds()); + size_t num_method_types = std::min<size_t>(kDexCacheMethodTypeCacheSize, dex_file->NumProtoIds()); + size_t num_call_sites = dex_file->NumCallSiteIds(); // Full size. + static_assert(ArenaAllocator::kAlignment == 8, "Expecting arena alignment of 8."); + StringDexCacheType* strings = + AllocArray<StringDexCacheType>(self, linear_alloc, num_strings); + TypeDexCacheType* types = + AllocArray<TypeDexCacheType>(self, linear_alloc, num_types); + MethodDexCacheType* methods = + AllocArray<MethodDexCacheType>(self, linear_alloc, num_methods); + FieldDexCacheType* fields = + AllocArray<FieldDexCacheType>(self, linear_alloc, num_fields); + MethodTypeDexCacheType* method_types = + AllocArray<MethodTypeDexCacheType>(self, linear_alloc, num_method_types); + GcRoot<mirror::CallSite>* call_sites = + AllocArray<GcRoot<CallSite>>(self, linear_alloc, num_call_sites); + + DCHECK_ALIGNED(types, alignof(StringDexCacheType)) << + "Expected StringsOffset() to align to StringDexCacheType."; + DCHECK_ALIGNED(strings, alignof(StringDexCacheType)) << + "Expected strings to align to StringDexCacheType."; + static_assert(alignof(StringDexCacheType) == 8u, + "Expected StringDexCacheType to have align of 8."); + if (kIsDebugBuild) { + // Consistency check to make sure all the dex cache arrays are empty. b/28992179 + for (size_t i = 0; i < num_strings; ++i) { + CHECK_EQ(strings[i].load(std::memory_order_relaxed).index, 0u); + CHECK(strings[i].load(std::memory_order_relaxed).object.IsNull()); + } + for (size_t i = 0; i < num_types; ++i) { + CHECK_EQ(types[i].load(std::memory_order_relaxed).index, 0u); + CHECK(types[i].load(std::memory_order_relaxed).object.IsNull()); + } + for (size_t i = 0; i < num_methods; ++i) { + CHECK_EQ(GetNativePair(methods, i).index, 0u); + CHECK(GetNativePair(methods, i).object == nullptr); + } + for (size_t i = 0; i < num_fields; ++i) { + CHECK_EQ(GetNativePair(fields, i).index, 0u); + CHECK(GetNativePair(fields, i).object == nullptr); + } + for (size_t i = 0; i < num_method_types; ++i) { + CHECK_EQ(method_types[i].load(std::memory_order_relaxed).index, 0u); + CHECK(method_types[i].load(std::memory_order_relaxed).object.IsNull()); + } + for (size_t i = 0; i < dex_file->NumCallSiteIds(); ++i) { + CHECK(call_sites[i].IsNull()); + } + } + if (strings != nullptr) { + mirror::StringDexCachePair::Initialize(strings); + } + if (types != nullptr) { + mirror::TypeDexCachePair::Initialize(types); + } + if (fields != nullptr) { + mirror::FieldDexCachePair::Initialize(fields); + } + if (methods != nullptr) { + mirror::MethodDexCachePair::Initialize(methods); + } + if (method_types != nullptr) { + mirror::MethodTypeDexCachePair::Initialize(method_types); + } SetDexFile(dex_file); - SetClassLoader(class_loader); + SetNativeArrays(strings, + num_strings, + types, + num_types, + methods, + num_methods, + fields, + num_fields, + method_types, + num_method_types, + call_sites, + num_call_sites); +} + +void DexCache::ResetNativeFields() { + SetDexFile(nullptr); + SetNativeArrays(nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0, nullptr, 0); } void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) { @@ -91,19 +184,59 @@ void DexCache::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) { } } -void DexCache::ResetNativeArrays() { - SetStrings(nullptr); - SetResolvedTypes(nullptr); - SetResolvedMethods(nullptr); - SetResolvedFields(nullptr); - SetResolvedMethodTypes(nullptr); - SetResolvedCallSites(nullptr); - SetField32<false>(NumStringsOffset(), 0); - SetField32<false>(NumResolvedTypesOffset(), 0); - SetField32<false>(NumResolvedMethodsOffset(), 0); - SetField32<false>(NumResolvedFieldsOffset(), 0); - SetField32<false>(NumResolvedMethodTypesOffset(), 0); - SetField32<false>(NumResolvedCallSitesOffset(), 0); +bool DexCache::AddPreResolvedStringsArray() { + DCHECK_EQ(NumPreResolvedStrings(), 0u); + Thread* const self = Thread::Current(); + LinearAlloc* linear_alloc = Runtime::Current()->GetLinearAlloc(); + const size_t num_strings = GetDexFile()->NumStringIds(); + if (num_strings != 0) { + GcRoot<mirror::String>* strings = + linear_alloc->AllocArray<GcRoot<mirror::String>>(self, num_strings); + if (strings == nullptr) { + // Failed to allocate pre-resolved string array (probably due to address fragmentation), bail. + return false; + } + SetField32<false>(NumPreResolvedStringsOffset(), num_strings); + + CHECK(strings != nullptr); + SetPreResolvedStrings(strings); + for (size_t i = 0; i < GetDexFile()->NumStringIds(); ++i) { + CHECK(GetPreResolvedStrings()[i].Read() == nullptr); + } + } + return true; +} + +void DexCache::SetNativeArrays(StringDexCacheType* strings, + uint32_t num_strings, + TypeDexCacheType* resolved_types, + uint32_t num_resolved_types, + MethodDexCacheType* resolved_methods, + uint32_t num_resolved_methods, + FieldDexCacheType* resolved_fields, + uint32_t num_resolved_fields, + MethodTypeDexCacheType* resolved_method_types, + uint32_t num_resolved_method_types, + GcRoot<CallSite>* resolved_call_sites, + uint32_t num_resolved_call_sites) { + CHECK_EQ(num_strings != 0u, strings != nullptr); + CHECK_EQ(num_resolved_types != 0u, resolved_types != nullptr); + CHECK_EQ(num_resolved_methods != 0u, resolved_methods != nullptr); + CHECK_EQ(num_resolved_fields != 0u, resolved_fields != nullptr); + CHECK_EQ(num_resolved_method_types != 0u, resolved_method_types != nullptr); + CHECK_EQ(num_resolved_call_sites != 0u, resolved_call_sites != nullptr); + SetStrings(strings); + SetResolvedTypes(resolved_types); + SetResolvedMethods(resolved_methods); + SetResolvedFields(resolved_fields); + SetResolvedMethodTypes(resolved_method_types); + SetResolvedCallSites(resolved_call_sites); + SetField32<false>(NumStringsOffset(), num_strings); + SetField32<false>(NumResolvedTypesOffset(), num_resolved_types); + SetField32<false>(NumResolvedMethodsOffset(), num_resolved_methods); + SetField32<false>(NumResolvedFieldsOffset(), num_resolved_fields); + SetField32<false>(NumResolvedMethodTypesOffset(), num_resolved_method_types); + SetField32<false>(NumResolvedCallSitesOffset(), num_resolved_call_sites); } void DexCache::SetLocation(ObjPtr<mirror::String> location) { @@ -114,10 +247,6 @@ void DexCache::SetClassLoader(ObjPtr<ClassLoader> class_loader) { SetFieldObject<false>(OFFSET_OF_OBJECT_MEMBER(DexCache, class_loader_), class_loader); } -ObjPtr<ClassLoader> DexCache::GetClassLoader() { - return GetFieldObject<ClassLoader>(OFFSET_OF_OBJECT_MEMBER(DexCache, class_loader_)); -} - #if !defined(__aarch64__) && !defined(__x86_64__) static pthread_mutex_t dex_cache_slow_atomic_mutex = PTHREAD_MUTEX_INITIALIZER; |