summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc110
1 files changed, 42 insertions, 68 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 6b9c8aa353..bc8a9f4936 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1318,8 +1318,9 @@ void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) {
boot_class_table_.VisitRoots(buffered_visitor);
// TODO: Avoid marking these to enable class unloading.
JavaVMExt* const vm = Runtime::Current()->GetJavaVM();
- for (const ClassLoaderData& data : class_loaders_) {
- mirror::Object* class_loader = vm->DecodeWeakGlobal(self, data.weak_root);
+ for (jweak weak_root : class_loaders_) {
+ mirror::Object* class_loader =
+ down_cast<mirror::ClassLoader*>(vm->DecodeWeakGlobal(self, weak_root));
// Don't need to update anything since the class loaders will be updated by SweepSystemWeaks.
visitor->VisitRootIfNonNull(&class_loader, RootInfo(kRootVMInternal));
}
@@ -1502,10 +1503,13 @@ ClassLinker::~ClassLinker() {
STLDeleteElements(&oat_files_);
Thread* const self = Thread::Current();
JavaVMExt* const vm = Runtime::Current()->GetJavaVM();
- for (const ClassLoaderData& data : class_loaders_) {
- vm->DecodeWeakGlobalDuringShutdown(self, data.weak_root);
- delete data.allocator;
- delete data.class_table;
+ for (jweak weak_root : class_loaders_) {
+ auto* const class_loader = down_cast<mirror::ClassLoader*>(
+ vm->DecodeWeakGlobalDuringShutdown(self, weak_root));
+ if (class_loader != nullptr) {
+ delete class_loader->GetClassTable();
+ }
+ vm->DeleteWeakGlobalRef(self, weak_root);
}
class_loaders_.clear();
}
@@ -2371,25 +2375,21 @@ void ClassLinker::LoadClass(Thread* self,
}
}
-LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self,
- LinearAlloc* allocator,
- size_t length) {
+LengthPrefixedArray<ArtField>* ClassLinker::AllocArtFieldArray(Thread* self, size_t length) {
if (length == 0) {
return nullptr;
}
// If the ArtField alignment changes, review all uses of LengthPrefixedArray<ArtField>.
static_assert(alignof(ArtField) == 4, "ArtField alignment is expected to be 4.");
size_t storage_size = LengthPrefixedArray<ArtField>::ComputeSize(length);
- void* array_storage = allocator->Alloc(self, storage_size);
+ void* array_storage = Runtime::Current()->GetLinearAlloc()->Alloc(self, storage_size);
auto* ret = new(array_storage) LengthPrefixedArray<ArtField>(length);
CHECK(ret != nullptr);
std::uninitialized_fill_n(&ret->At(0), length, ArtField());
return ret;
}
-LengthPrefixedArray<ArtMethod>* ClassLinker::AllocArtMethodArray(Thread* self,
- LinearAlloc* allocator,
- size_t length) {
+LengthPrefixedArray<ArtMethod>* ClassLinker::AllocArtMethodArray(Thread* self, size_t length) {
if (length == 0) {
return nullptr;
}
@@ -2397,7 +2397,7 @@ LengthPrefixedArray<ArtMethod>* ClassLinker::AllocArtMethodArray(Thread* self,
const size_t method_size = ArtMethod::Size(image_pointer_size_);
const size_t storage_size =
LengthPrefixedArray<ArtMethod>::ComputeSize(length, method_size, method_alignment);
- void* array_storage = allocator->Alloc(self, storage_size);
+ void* array_storage = Runtime::Current()->GetLinearAlloc()->Alloc(self, storage_size);
auto* ret = new (array_storage) LengthPrefixedArray<ArtMethod>(length);
CHECK(ret != nullptr);
for (size_t i = 0; i < length; ++i) {
@@ -2406,15 +2406,6 @@ LengthPrefixedArray<ArtMethod>* ClassLinker::AllocArtMethodArray(Thread* self,
return ret;
}
-LinearAlloc* ClassLinker::GetAllocatorForClassLoader(mirror::ClassLoader* class_loader) {
- if (class_loader == nullptr) {
- return Runtime::Current()->GetLinearAlloc();
- }
- LinearAlloc* allocator = class_loader->GetAllocator();
- DCHECK(allocator != nullptr);
- return allocator;
-}
-
void ClassLinker::LoadClassMembers(Thread* self,
const DexFile& dex_file,
const uint8_t* class_data,
@@ -2427,11 +2418,8 @@ void ClassLinker::LoadClassMembers(Thread* self,
// Load static fields.
// We allow duplicate definitions of the same field in a class_data_item
// but ignore the repeated indexes here, b/21868015.
- LinearAlloc* const allocator = GetAllocatorForClassLoader(klass->GetClassLoader());
ClassDataItemIterator it(dex_file, class_data);
- LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self,
- allocator,
- it.NumStaticFields());
+ LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, it.NumStaticFields());
size_t num_sfields = 0;
uint32_t last_field_idx = 0u;
for (; it.HasNextStaticField(); it.Next()) {
@@ -2447,9 +2435,7 @@ void ClassLinker::LoadClassMembers(Thread* self,
klass->SetSFieldsPtr(sfields);
DCHECK_EQ(klass->NumStaticFields(), num_sfields);
// Load instance fields.
- LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self,
- allocator,
- it.NumInstanceFields());
+ LengthPrefixedArray<ArtField>* ifields = AllocArtFieldArray(self, it.NumInstanceFields());
size_t num_ifields = 0u;
last_field_idx = 0u;
for (; it.HasNextInstanceField(); it.Next()) {
@@ -2472,8 +2458,8 @@ void ClassLinker::LoadClassMembers(Thread* self,
klass->SetIFieldsPtr(ifields);
DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
// Load methods.
- klass->SetDirectMethodsPtr(AllocArtMethodArray(self, allocator, it.NumDirectMethods()));
- klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, allocator, it.NumVirtualMethods()));
+ klass->SetDirectMethodsPtr(AllocArtMethodArray(self, it.NumDirectMethods()));
+ klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, it.NumVirtualMethods()));
size_t class_def_method_index = 0;
uint32_t last_dex_method_index = DexFile::kDexNoIndex;
size_t last_class_def_method_index = 0;
@@ -3045,7 +3031,7 @@ void ClassLinker::MoveClassTableToPreZygote() {
WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_);
boot_class_table_.FreezeSnapshot();
MoveClassTableToPreZygoteVisitor visitor;
- VisitClassLoaders(&visitor);
+ VisitClassLoadersAndRemoveClearedLoaders(&visitor);
}
mirror::Class* ClassLinker::LookupClassFromImage(const char* descriptor) {
@@ -3428,12 +3414,9 @@ 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);
+ LengthPrefixedArray<ArtField>* sfields = AllocArtFieldArray(self, num_fields);
klass->SetSFieldsPtr(sfields);
// 1. Create a static field 'interfaces' that holds the _declared_ interfaces implemented by
@@ -3450,7 +3433,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
throws_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
// Proxies have 1 direct method, the constructor
- LengthPrefixedArray<ArtMethod>* directs = AllocArtMethodArray(self, allocator, 1);
+ LengthPrefixedArray<ArtMethod>* directs = AllocArtMethodArray(self, 1);
// Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
// want to throw OOM in the future.
if (UNLIKELY(directs == nullptr)) {
@@ -3465,7 +3448,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
<< PrettyClass(h_methods->GetClass());
const size_t num_virtual_methods = h_methods->GetLength();
- auto* virtuals = AllocArtMethodArray(self, allocator, num_virtual_methods);
+ auto* virtuals = AllocArtMethodArray(self, num_virtual_methods);
// Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
// want to throw OOM in the future.
if (UNLIKELY(virtuals == nullptr)) {
@@ -4183,14 +4166,9 @@ ClassTable* ClassLinker::InsertClassTableForClassLoader(mirror::ClassLoader* cla
if (class_table == nullptr) {
class_table = new ClassTable;
Thread* const self = Thread::Current();
- 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);
+ class_loaders_.push_back(self->GetJniEnv()->vm->AddWeakGlobalRef(self, class_loader));
// Don't already have a class table, add it to the class loader.
- class_loader->SetClassTable(data.class_table);
- class_loader->SetAllocator(data.allocator);
+ class_loader->SetClassTable(class_table);
}
return class_table;
}
@@ -6180,10 +6158,7 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi
ArtMethod* ClassLinker::CreateRuntimeMethod() {
const size_t method_alignment = ArtMethod::Alignment(image_pointer_size_);
const size_t method_size = ArtMethod::Size(image_pointer_size_);
- LengthPrefixedArray<ArtMethod>* method_array = AllocArtMethodArray(
- Thread::Current(),
- Runtime::Current()->GetLinearAlloc(),
- 1);
+ LengthPrefixedArray<ArtMethod>* method_array = AllocArtMethodArray(Thread::Current(), 1);
ArtMethod* method = &method_array->At(0, method_size, method_alignment);
CHECK(method != nullptr);
method->SetDexMethodIndex(DexFile::kDexNoIndex);
@@ -6196,34 +6171,33 @@ void ClassLinker::DropFindArrayClassCache() {
find_array_class_cache_next_victim_ = 0;
}
-void ClassLinker::VisitClassLoaders(ClassLoaderVisitor* visitor) const {
+void ClassLinker::VisitClassLoadersAndRemoveClearedLoaders(ClassLoaderVisitor* visitor) {
Thread* const self = Thread::Current();
+ Locks::classlinker_classes_lock_->AssertExclusiveHeld(self);
JavaVMExt* const vm = self->GetJniEnv()->vm;
- for (const ClassLoaderData& data : class_loaders_) {
- auto* const class_loader = down_cast<mirror::ClassLoader*>(
- vm->DecodeWeakGlobal(self, data.weak_root));
+ for (auto it = class_loaders_.begin(); it != class_loaders_.end();) {
+ const jweak weak_root = *it;
+ mirror::ClassLoader* const class_loader = down_cast<mirror::ClassLoader*>(
+ vm->DecodeWeakGlobal(self, weak_root));
if (class_loader != nullptr) {
visitor->Visit(class_loader);
+ ++it;
+ } else {
+ // Remove the cleared weak reference from the array.
+ vm->DeleteWeakGlobalRef(self, weak_root);
+ it = class_loaders_.erase(it);
}
}
}
-void ClassLinker::CleanupClassLoaders() {
+void ClassLinker::VisitClassLoaders(ClassLoaderVisitor* visitor) const {
Thread* const self = Thread::Current();
- WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
- JavaVMExt* const vm = Runtime::Current()->GetJavaVM();
- for (auto it = class_loaders_.begin(); it != class_loaders_.end(); ) {
- const ClassLoaderData& data = *it;
- auto* const class_loader = down_cast<mirror::ClassLoader*>(
- vm->DecodeWeakGlobal(self, data.weak_root));
+ JavaVMExt* const vm = self->GetJniEnv()->vm;
+ for (jweak weak_root : class_loaders_) {
+ mirror::ClassLoader* const class_loader = down_cast<mirror::ClassLoader*>(
+ vm->DecodeWeakGlobal(self, weak_root));
if (class_loader != nullptr) {
- ++it;
- } else {
- // Weak reference was cleared, delete the data associated with this class loader.
- delete data.class_table;
- delete data.allocator;
- vm->DeleteWeakGlobalRef(self, data.weak_root);
- it = class_loaders_.erase(it);
+ visitor->Visit(class_loader);
}
}
}