summaryrefslogtreecommitdiff
path: root/runtime/mirror/dex_cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/mirror/dex_cache.cc')
-rw-r--r--runtime/mirror/dex_cache.cc167
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;