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.cc77
1 files changed, 60 insertions, 17 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 343bc8fb7b..fe7448fa25 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1348,7 +1348,8 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
for (int32_t j = 0; j < static_cast<int32_t>(num_types); j++) {
// The image space is not yet added to the heap, avoid read barriers.
mirror::Class* klass = types[j].Read();
- if (klass != nullptr) {
+ // There may also be boot image classes,
+ if (space->HasAddress(klass)) {
DCHECK_NE(klass->GetStatus(), mirror::Class::kStatusError);
// Update the class loader from the one in the image class loader to the one that loaded
// the app image.
@@ -1387,6 +1388,9 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
VLOG(image) << PrettyMethod(&m);
}
}
+ } else {
+ DCHECK(klass == nullptr || heap->ObjectIsInBootImageSpace(klass))
+ << klass << " " << PrettyClass(klass);
}
}
}
@@ -1394,10 +1398,10 @@ bool ClassLinker::UpdateAppImageClassLoadersAndDexCaches(
for (int32_t j = 0; j < static_cast<int32_t>(num_types); j++) {
// The image space is not yet added to the heap, avoid read barriers.
mirror::Class* klass = types[j].Read();
- if (klass != nullptr) {
+ if (space->HasAddress(klass)) {
DCHECK_NE(klass->GetStatus(), mirror::Class::kStatusError);
if (kIsDebugBuild) {
- if (new_class_set != nullptr) {
+ if (new_class_set != nullptr) {
auto it = new_class_set->Find(GcRoot<mirror::Class>(klass));
DCHECK(it != new_class_set->end());
DCHECK_EQ(it->Read(), klass);
@@ -1662,6 +1666,10 @@ bool ClassLinker::AddImageSpace(
// resolve the same way, simply flatten the hierarchy in the way the resolution order would be,
// and check that the dex file names are the same.
for (mirror::ClassLoader* image_class_loader : image_class_loaders) {
+ if (IsBootClassLoader(soa, image_class_loader)) {
+ // The dex cache can reference types from the boot class loader.
+ continue;
+ }
std::list<mirror::String*> image_dex_file_names;
std::string temp_error_msg;
if (!FlattenPathClassLoader(image_class_loader, &image_dex_file_names, &temp_error_msg)) {
@@ -2084,6 +2092,21 @@ mirror::DexCache* ClassLinker::AllocDexCache(Thread* self,
reinterpret_cast<ArtMethod**>(raw_arrays + layout.MethodsOffset());
ArtField** fields = (dex_file.NumFieldIds() == 0u) ? nullptr :
reinterpret_cast<ArtField**>(raw_arrays + layout.FieldsOffset());
+ if (kIsDebugBuild) {
+ // Sanity check to make sure all the dex cache arrays are empty. b/28992179
+ for (size_t i = 0; i < dex_file.NumStringIds(); ++i) {
+ CHECK(strings[i].Read<kWithoutReadBarrier>() == nullptr);
+ }
+ for (size_t i = 0; i < dex_file.NumTypeIds(); ++i) {
+ CHECK(types[i].Read<kWithoutReadBarrier>() == nullptr);
+ }
+ for (size_t i = 0; i < dex_file.NumMethodIds(); ++i) {
+ CHECK(mirror::DexCache::GetElementPtrSize(methods, i, image_pointer_size_) == nullptr);
+ }
+ for (size_t i = 0; i < dex_file.NumFieldIds(); ++i) {
+ CHECK(mirror::DexCache::GetElementPtrSize(fields, i, image_pointer_size_) == nullptr);
+ }
+ }
dex_cache->Init(&dex_file,
location.Get(),
strings,
@@ -2445,9 +2468,7 @@ mirror::Class* ClassLinker::DefineClass(Thread* self,
self->AssertPendingOOMException();
return nullptr;
}
- mirror::DexCache* dex_cache = RegisterDexFile(
- dex_file,
- GetOrCreateAllocatorForClassLoader(class_loader.Get()));
+ mirror::DexCache* dex_cache = RegisterDexFile(dex_file, class_loader.Get());
if (dex_cache == nullptr) {
self->AssertPendingOOMException();
return nullptr;
@@ -3206,7 +3227,8 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file,
dex_caches_.push_back(data);
}
-mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file, LinearAlloc* linear_alloc) {
+mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file,
+ mirror::ClassLoader* class_loader) {
Thread* self = Thread::Current();
{
ReaderMutexLock mu(self, dex_lock_);
@@ -3215,21 +3237,31 @@ mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file, LinearAl
return dex_cache;
}
}
+ LinearAlloc* const linear_alloc = GetOrCreateAllocatorForClassLoader(class_loader);
+ DCHECK(linear_alloc != nullptr);
+ ClassTable* table;
+ {
+ WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
+ table = InsertClassTableForClassLoader(class_loader);
+ }
// Don't alloc while holding the lock, since allocation may need to
// 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, linear_alloc)));
- WriterMutexLock mu(self, dex_lock_);
- mirror::DexCache* dex_cache = FindDexCacheLocked(self, dex_file, true);
- if (dex_cache != nullptr) {
- return dex_cache;
- }
- if (h_dex_cache.Get() == nullptr) {
- self->AssertPendingOOMException();
- return nullptr;
+ {
+ WriterMutexLock mu(self, dex_lock_);
+ mirror::DexCache* dex_cache = FindDexCacheLocked(self, dex_file, true);
+ if (dex_cache != nullptr) {
+ return dex_cache;
+ }
+ if (h_dex_cache.Get() == nullptr) {
+ self->AssertPendingOOMException();
+ return nullptr;
+ }
+ RegisterDexFileLocked(dex_file, h_dex_cache);
}
- RegisterDexFileLocked(dex_file, h_dex_cache);
+ table->InsertStrongRoot(h_dex_cache.Get());
return h_dex_cache.Get();
}
@@ -4918,6 +4950,7 @@ bool ClassLinker::EnsureInitialized(Thread* self, Handle<mirror::Class> c, bool
DCHECK(c.Get() != nullptr);
if (c->IsInitialized()) {
EnsureSkipAccessChecksMethods(c);
+ self->AssertNoPendingException();
return true;
}
const bool success = InitializeClass(self, c, can_init_fields, can_init_parents);
@@ -7922,6 +7955,16 @@ void ClassLinker::DropFindArrayClassCache() {
find_array_class_cache_next_victim_ = 0;
}
+void ClassLinker::ClearClassTableStrongRoots() const {
+ Thread* const self = Thread::Current();
+ WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
+ for (const ClassLoaderData& data : class_loaders_) {
+ if (data.class_table != nullptr) {
+ data.class_table->ClearStrongRoots();
+ }
+ }
+}
+
void ClassLinker::VisitClassLoaders(ClassLoaderVisitor* visitor) const {
Thread* const self = Thread::Current();
for (const ClassLoaderData& data : class_loaders_) {
@@ -7940,7 +7983,7 @@ void ClassLinker::InsertDexFileInToClassLoader(mirror::Object* dex_file,
WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
ClassTable* const table = ClassTableForClassLoader(class_loader);
DCHECK(table != nullptr);
- if (table->InsertDexFile(dex_file) && class_loader != nullptr) {
+ if (table->InsertStrongRoot(dex_file) && class_loader != nullptr) {
// It was not already inserted, perform the write barrier to let the GC know the class loader's
// class table was modified.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader);