diff options
Diffstat (limited to 'runtime')
| -rw-r--r-- | runtime/class_linker.cc | 63 | ||||
| -rw-r--r-- | runtime/class_linker.h | 12 | ||||
| -rw-r--r-- | runtime/mirror/dex_cache_test.cc | 25 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 4 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 3 |
5 files changed, 75 insertions, 32 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 02f2e0b207..27fcfb0a02 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -1189,7 +1189,9 @@ mirror::PointerArray* ClassLinker::AllocPointerArray(Thread* self, size_t length static_cast<mirror::Array*>(mirror::IntArray::Alloc(self, length))); } -mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_file) { +mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, + const DexFile& dex_file, + LinearAlloc* linear_alloc) { StackHandleScope<6> hs(self); auto dex_cache(hs.NewHandle(down_cast<mirror::DexCache*>( GetClassRoot(kJavaLangDexCache)->AllocObject(self)))); @@ -1208,18 +1210,13 @@ mirror::DexCache* ClassLinker::AllocDexCache(Thread* self, const DexFile& dex_fi dex_file.NumMethodIds() != 0u || dex_file.NumFieldIds() != 0u) { // NOTE: We "leak" the raw_arrays because we never destroy the dex cache. DCHECK(image_pointer_size_ == 4u || image_pointer_size_ == 8u); - if (sizeof(void*) == 8u && image_pointer_size_ == 4u) { - // When cross-compiling for a 32-bit target on a 64-bit host, we need these arrays - // in the low 4GiB address space so that we can store pointers in 32-bit fields. - // This is conveniently provided by the linear allocator. - raw_arrays = reinterpret_cast<uint8_t*>( - Runtime::Current()->GetLinearAlloc()->Alloc(self, layout.Size())); // Zero-initialized. - } else { - raw_arrays = reinterpret_cast<uint8_t*>(calloc(layout.Size(), 1u)); // Zero-initialized. - if (raw_arrays == nullptr) { - return nullptr; - } - } + // When cross-compiling for a 32-bit target on a 64-bit host, we need these arrays + // in the low 4GiB address space so that we can store pointers in 32-bit fields. + // This is conveniently provided by the linear allocator. + raw_arrays = reinterpret_cast<uint8_t*>( + (sizeof(void*) == 8u && image_pointer_size_ == 4u) + ? Runtime::Current()->GetLinearAlloc()->Alloc(self, layout.Size()) // Zero-initialized. + : linear_alloc->Alloc(self, layout.Size())); // Zero-initialized. } GcRoot<mirror::String>* strings = (dex_file.NumStringIds() == 0u) ? nullptr : reinterpret_cast<GcRoot<mirror::String>*>(raw_arrays + layout.StringsOffset()); @@ -1590,7 +1587,9 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, self->AssertPendingOOMException(); return nullptr; } - mirror::DexCache* dex_cache = RegisterDexFile(dex_file); + mirror::DexCache* dex_cache = RegisterDexFile( + dex_file, + GetOrCreateAllocatorForClassLoader(class_loader.Get())); if (dex_cache == nullptr) { self->AssertPendingOOMException(); return nullptr; @@ -2093,6 +2092,19 @@ LinearAlloc* ClassLinker::GetAllocatorForClassLoader(mirror::ClassLoader* class_ return allocator; } +LinearAlloc* ClassLinker::GetOrCreateAllocatorForClassLoader(mirror::ClassLoader* class_loader) { + if (class_loader == nullptr) { + return Runtime::Current()->GetLinearAlloc(); + } + WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); + LinearAlloc* allocator = class_loader->GetAllocator(); + if (allocator == nullptr) { + allocator = Runtime::Current()->CreateLinearAlloc(); + class_loader->SetAllocator(allocator); + } + return allocator; +} + void ClassLinker::LoadClassMembers(Thread* self, const DexFile& dex_file, const uint8_t* class_data, @@ -2251,7 +2263,10 @@ void ClassLinker::LoadMethod(Thread* self, void ClassLinker::AppendToBootClassPath(Thread* self, const DexFile& dex_file) { StackHandleScope<1> hs(self); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(AllocDexCache(self, dex_file))); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(AllocDexCache( + self, + dex_file, + Runtime::Current()->GetLinearAlloc()))); CHECK(dex_cache.Get() != nullptr) << "Failed to allocate dex cache for " << dex_file.GetLocation(); AppendToBootClassPath(dex_file, dex_cache); @@ -2287,7 +2302,7 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, dex_cache->SetDexFile(&dex_file); } -mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file) { +mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file, LinearAlloc* linear_alloc) { Thread* self = Thread::Current(); { ReaderMutexLock mu(self, dex_lock_); @@ -2300,7 +2315,7 @@ mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file) { // suspend all threads and another thread may need the dex_lock_ to // get to a suspend point. StackHandleScope<1> hs(self); - Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(AllocDexCache(self, dex_file))); + Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(AllocDexCache(self, dex_file, linear_alloc))); WriterMutexLock mu(self, dex_lock_); mirror::DexCache* dex_cache = FindDexCacheLocked(self, dex_file, true); if (dex_cache != nullptr) { @@ -3097,6 +3112,9 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& std::string descriptor(GetDescriptorForProxy(klass.Get())); const size_t hash = ComputeModifiedUtf8Hash(descriptor.c_str()); + // Needs to be before we insert the class so that the allocator field is set. + LinearAlloc* const allocator = GetOrCreateAllocatorForClassLoader(klass->GetClassLoader()); + // Insert the class before loading the fields as the field roots // (ArtField::declaring_class_) are only visited from the class // table. There can't be any suspend points between inserting the @@ -3104,9 +3122,6 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable& mirror::Class* existing = InsertClass(descriptor.c_str(), klass.Get(), hash); CHECK(existing == nullptr); - // Needs to be after we insert the class so that the allocator field is set. - LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader()); - // Instance fields are inherited, but we add a couple of static fields... const size_t num_fields = 2; LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, allocator, num_fields); @@ -3945,13 +3960,13 @@ ClassTable* ClassLinker::InsertClassTableForClassLoader(mirror::ClassLoader* cla ClassLoaderData data; data.weak_root = self->GetJniEnv()->vm->AddWeakGlobalRef(self, class_loader); data.class_table = class_table; - data.allocator = Runtime::Current()->CreateLinearAlloc(); - class_loaders_.push_back(data); // Don't already have a class table, add it to the class loader. CHECK(class_loader->GetClassTable() == nullptr); - CHECK(class_loader->GetAllocator() == nullptr); class_loader->SetClassTable(data.class_table); - class_loader->SetAllocator(data.allocator); + // Should have been set when we registered the dex file. + data.allocator = class_loader->GetAllocator(); + CHECK(data.allocator != nullptr); + class_loaders_.push_back(data); } return class_table; } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 93161f7bb7..a70967d49b 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -319,7 +319,7 @@ class ClassLinker { SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!dex_lock_, !Roles::uninterruptible_); - mirror::DexCache* RegisterDexFile(const DexFile& dex_file) + mirror::DexCache* RegisterDexFile(const DexFile& dex_file, LinearAlloc* linear_alloc) REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_); void RegisterDexFile(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache) @@ -532,6 +532,12 @@ class ClassLinker { static LinearAlloc* GetAllocatorForClassLoader(mirror::ClassLoader* class_loader) SHARED_REQUIRES(Locks::mutator_lock_); + // Return the linear alloc for a class loader if it is already allocated, otherwise allocate and + // set it. TODO: Consider using a lock other than classlinker_classes_lock_. + static LinearAlloc* GetOrCreateAllocatorForClassLoader(mirror::ClassLoader* class_loader) + SHARED_REQUIRES(Locks::mutator_lock_) + REQUIRES(!Locks::classlinker_classes_lock_); + private: struct ClassLoaderData { jweak weak_root; // Weak root to enable class unloading. @@ -570,7 +576,9 @@ class ClassLinker { mirror::Class* AllocClass(Thread* self, uint32_t class_size) SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); - mirror::DexCache* AllocDexCache(Thread* self, const DexFile& dex_file) + mirror::DexCache* AllocDexCache(Thread* self, + const DexFile& dex_file, + LinearAlloc* linear_alloc) SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); diff --git a/runtime/mirror/dex_cache_test.cc b/runtime/mirror/dex_cache_test.cc index 8fb860fa6b..48f2ca59e8 100644 --- a/runtime/mirror/dex_cache_test.cc +++ b/runtime/mirror/dex_cache_test.cc @@ -20,9 +20,8 @@ #include "class_linker.h" #include "common_runtime_test.h" -#include "gc/heap.h" -#include "mirror/object_array-inl.h" -#include "mirror/object-inl.h" +#include "linear_alloc.h" +#include "mirror/class_loader-inl.h" #include "handle_scope-inl.h" #include "scoped_thread_state_change.h" @@ -36,7 +35,9 @@ TEST_F(DexCacheTest, Open) { StackHandleScope<1> hs(soa.Self()); ASSERT_TRUE(java_lang_dex_file_ != nullptr); Handle<DexCache> dex_cache( - hs.NewHandle(class_linker_->AllocDexCache(soa.Self(), *java_lang_dex_file_))); + hs.NewHandle(class_linker_->AllocDexCache(soa.Self(), + *java_lang_dex_file_, + Runtime::Current()->GetLinearAlloc()))); ASSERT_TRUE(dex_cache.Get() != nullptr); EXPECT_EQ(java_lang_dex_file_->NumStringIds(), dex_cache->NumStrings()); @@ -45,5 +46,21 @@ TEST_F(DexCacheTest, Open) { EXPECT_EQ(java_lang_dex_file_->NumFieldIds(), dex_cache->NumResolvedFields()); } +TEST_F(DexCacheTest, LinearAlloc) { + ScopedObjectAccess soa(Thread::Current()); + jobject jclass_loader(LoadDex("Main")); + ASSERT_TRUE(jclass_loader != nullptr); + Runtime* const runtime = Runtime::Current(); + ClassLinker* const class_linker = runtime->GetClassLinker(); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle( + soa.Decode<mirror::ClassLoader*>(jclass_loader))); + mirror::Class* klass = class_linker->FindClass(soa.Self(), "LMain;", class_loader); + ASSERT_TRUE(klass != nullptr); + LinearAlloc* const linear_alloc = klass->GetClassLoader()->GetAllocator(); + EXPECT_NE(linear_alloc, runtime->GetLinearAlloc()); + EXPECT_TRUE(linear_alloc->Contains(klass->GetDexCache()->GetResolvedMethods())); +} + } // namespace mirror } // namespace art diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index e9ce02bd0d..9fb5d0db6e 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -264,10 +264,12 @@ static jclass DexFile_defineClassNative(JNIEnv* env, if (dex_class_def != nullptr) { ScopedObjectAccess soa(env); ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - class_linker->RegisterDexFile(*dex_file); StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader))); + class_linker->RegisterDexFile( + *dex_file, + class_linker->GetOrCreateAllocatorForClassLoader(class_loader.Get())); mirror::Class* result = class_linker->DefineClass(soa.Self(), descriptor.c_str(), hash, diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 4f957233c4..4c5dc3ad25 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -497,7 +497,8 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) { const DexFile* dex_file = boot_class_path[i]; CHECK(dex_file != nullptr); StackHandleScope<1> hs(soa.Self()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->RegisterDexFile(*dex_file))); + Handle<mirror::DexCache> dex_cache( + hs.NewHandle(linker->RegisterDexFile(*dex_file, runtime->GetLinearAlloc()))); if (kPreloadDexCachesStrings) { for (size_t j = 0; j < dex_cache->NumStrings(); j++) { |