diff options
Diffstat (limited to 'runtime/class_linker.cc')
| -rw-r--r-- | runtime/class_linker.cc | 77 |
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); |