diff options
| -rw-r--r-- | compiler/driver/compiler_driver-inl.h | 8 | ||||
| -rw-r--r-- | compiler/driver/compiler_driver.cc | 30 | ||||
| -rw-r--r-- | compiler/image_writer.cc | 77 | ||||
| -rw-r--r-- | compiler/image_writer.h | 5 | ||||
| -rw-r--r-- | compiler/oat_writer.cc | 2 | ||||
| -rw-r--r-- | compiler/optimizing/reference_type_propagation.cc | 2 | ||||
| -rw-r--r-- | dex2oat/dex2oat.cc | 27 | ||||
| -rw-r--r-- | oatdump/oatdump.cc | 21 | ||||
| -rw-r--r-- | runtime/base/mutex.h | 1 | ||||
| -rw-r--r-- | runtime/class_linker-inl.h | 6 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 166 | ||||
| -rw-r--r-- | runtime/class_linker.h | 23 | ||||
| -rw-r--r-- | runtime/common_runtime_test.cc | 3 | ||||
| -rw-r--r-- | runtime/java_vm_ext.cc | 2 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 4 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 20 | ||||
| -rw-r--r-- | runtime/runtime-inl.h | 1 | ||||
| -rw-r--r-- | runtime/runtime.cc | 10 | ||||
| -rw-r--r-- | runtime/runtime.h | 3 | ||||
| -rw-r--r-- | runtime/trace.cc | 3 | ||||
| -rw-r--r-- | runtime/verifier/method_verifier.cc | 1 |
21 files changed, 201 insertions, 214 deletions
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index 80387f2842..83f391de1a 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -31,7 +31,7 @@ namespace art { inline mirror::DexCache* CompilerDriver::GetDexCache(const DexCompilationUnit* mUnit) { - return mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()); + return mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false); } inline mirror::ClassLoader* CompilerDriver::GetClassLoader(ScopedObjectAccess& soa, @@ -87,7 +87,7 @@ inline ArtField* CompilerDriver::ResolveFieldWithDexFile( } inline mirror::DexCache* CompilerDriver::FindDexCache(const DexFile* dex_file) { - return Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file); + return Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file, false); } inline ArtField* CompilerDriver::ResolveField( @@ -339,7 +339,7 @@ inline int CompilerDriver::IsFastInvoke( // Sharpen a virtual call into a direct call. The method_idx is into referrer's // dex cache, check that this resolved method is where we expect it. CHECK_EQ(target_method->dex_file, mUnit->GetDexFile()); - DCHECK_EQ(dex_cache.Get(), mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile())); + DCHECK_EQ(dex_cache.Get(), mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false)); CHECK_EQ(referrer_class->GetDexCache()->GetResolvedMethod( target_method->dex_method_index, pointer_size), resolved_method) << PrettyMethod(resolved_method); @@ -369,7 +369,7 @@ inline int CompilerDriver::IsFastInvoke( nullptr, kVirtual); } else { StackHandleScope<1> hs(soa.Self()); - auto target_dex_cache(hs.NewHandle(class_linker->FindDexCache(*devirt_target->dex_file))); + auto target_dex_cache(hs.NewHandle(class_linker->RegisterDexFile(*devirt_target->dex_file))); called_method = class_linker->ResolveMethod( *devirt_target->dex_file, devirt_target->dex_method_index, target_dex_cache, class_loader, nullptr, kVirtual); diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index fa25a17481..d38677e62c 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -936,7 +936,7 @@ void CompilerDriver::LoadImageClasses(TimingLogger* timings) { uint16_t exception_type_idx = exception_type.first; const DexFile* dex_file = exception_type.second; StackHandleScope<2> hs2(self); - Handle<mirror::DexCache> dex_cache(hs2.NewHandle(class_linker->FindDexCache(*dex_file))); + Handle<mirror::DexCache> dex_cache(hs2.NewHandle(class_linker->RegisterDexFile(*dex_file))); Handle<mirror::Class> klass(hs2.NewHandle( class_linker->ResolveType(*dex_file, exception_type_idx, dex_cache, NullHandle<mirror::ClassLoader>()))); @@ -1170,7 +1170,8 @@ bool CompilerDriver::CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, u IsImageClass(dex_file.StringDataByIdx(dex_file.GetTypeId(type_idx).descriptor_idx_))) { { ScopedObjectAccess soa(Thread::Current()); - mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache( + dex_file, false); mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); if (resolved_class == nullptr) { // Erroneous class. @@ -1195,9 +1196,9 @@ bool CompilerDriver::CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, // We resolve all const-string strings when building for the image. ScopedObjectAccess soa(Thread::Current()); StackHandleScope<1> hs(soa.Self()); - Handle<mirror::DexCache> dex_cache( - hs.NewHandle(Runtime::Current()->GetClassLinker()->FindDexCache(dex_file))); - Runtime::Current()->GetClassLinker()->ResolveString(dex_file, string_idx, dex_cache); + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file, false))); + class_linker->ResolveString(dex_file, string_idx, dex_cache); result = true; } if (result) { @@ -1222,7 +1223,7 @@ bool CompilerDriver::CanAccessTypeWithoutChecks(uint32_t referrer_idx, const Dex *equals_referrers_class = false; } ScopedObjectAccess soa(Thread::Current()); - mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file, false); // Get type from dex cache assuming it was populated by the verifier mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); if (resolved_class == nullptr) { @@ -1259,7 +1260,8 @@ bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_id const DexFile& dex_file, uint32_t type_idx) { ScopedObjectAccess soa(Thread::Current()); - mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache(dex_file); + mirror::DexCache* dex_cache = Runtime::Current()->GetClassLinker()->FindDexCache( + dex_file, false); // Get type from dex cache assuming it was populated by the verifier. mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); if (resolved_class == nullptr) { @@ -1288,7 +1290,7 @@ bool CompilerDriver::CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_i uintptr_t* direct_type_ptr, bool* out_is_finalizable) { ScopedObjectAccess soa(Thread::Current()); Runtime* runtime = Runtime::Current(); - mirror::DexCache* dex_cache = runtime->GetClassLinker()->FindDexCache(dex_file); + mirror::DexCache* dex_cache = runtime->GetClassLinker()->FindDexCache(dex_file, false); mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx); if (resolved_class == nullptr) { return false; @@ -1417,7 +1419,7 @@ ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, { StackHandleScope<2> hs(soa.Self()); Handle<mirror::DexCache> dex_cache_handle( - hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()))); + hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false))); Handle<mirror::ClassLoader> class_loader_handle( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()))); resolved_field = @@ -1467,7 +1469,7 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila { StackHandleScope<2> hs(soa.Self()); Handle<mirror::DexCache> dex_cache_handle( - hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()))); + hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false))); Handle<mirror::ClassLoader> class_loader_handle( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()))); resolved_field = @@ -1653,7 +1655,7 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui // Try to resolve the method and compiling method's class. StackHandleScope<3> hs(soa.Self()); Handle<mirror::DexCache> dex_cache( - hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile()))); + hs.NewHandle(mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile(), false))); Handle<mirror::ClassLoader> class_loader(hs.NewHandle( soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()))); uint32_t method_idx = target_method->dex_method_index; @@ -1905,7 +1907,7 @@ class ResolveClassFieldsAndMethodsVisitor : public CompilationVisitor { StackHandleScope<2> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader))); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file))); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file, false))); // Resolve the class. mirror::Class* klass = class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache, class_loader); @@ -1998,7 +2000,7 @@ class ResolveTypeVisitor : public CompilationVisitor { ClassLinker* class_linker = manager_->GetClassLinker(); const DexFile& dex_file = *manager_->GetDexFile(); StackHandleScope<2> hs(soa.Self()); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file))); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->RegisterDexFile(dex_file))); Handle<mirror::ClassLoader> class_loader( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(manager_->GetClassLoader()))); mirror::Class* klass = class_linker->ResolveType(dex_file, type_idx, dex_cache, class_loader); @@ -2084,7 +2086,7 @@ class VerifyClassVisitor : public CompilationVisitor { * This is to ensure the class is structurally sound for compilation. An unsound class * will be rejected by the verifier and later skipped during compilation in the compiler. */ - Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file))); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(dex_file, false))); std::string error_msg; if (verifier::MethodVerifier::VerifyClass(soa.Self(), &dex_file, dex_cache, class_loader, &class_def, true, &error_msg) == diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 93897aa228..dbd3366c1b 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -70,7 +70,6 @@ namespace art { // Separate objects into multiple bins to optimize dirty memory use. static constexpr bool kBinObjects = true; -static constexpr bool kComputeEagerResolvedStrings = false; static void CheckNoDexObjectsCallback(Object* obj, void* arg ATTRIBUTE_UNUSED) SHARED_REQUIRES(Locks::mutator_lock_) { @@ -90,11 +89,6 @@ bool ImageWriter::PrepareImageAddressSpace() { PruneNonImageClasses(); // Remove junk ComputeLazyFieldsForImageClasses(); // Add useful information - // Calling this can in theory fill in some resolved strings. However, in practice it seems to - // never resolve any. - if (kComputeEagerResolvedStrings) { - ComputeEagerResolvedStrings(); - } Thread::Current()->TransitionFromRunnableToSuspended(kNative); } gc::Heap* heap = Runtime::Current()->GetHeap(); @@ -302,11 +296,15 @@ void ImageWriter::SetImageBinSlot(mirror::Object* object, BinSlot bin_slot) { void ImageWriter::PrepareDexCacheArraySlots() { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock()); - size_t dex_cache_count = class_linker->GetDexCacheCount(); + Thread* const self = Thread::Current(); + ReaderMutexLock mu(self, *class_linker->DexLock()); uint32_t size = 0u; - for (size_t idx = 0; idx < dex_cache_count; ++idx) { - DexCache* dex_cache = class_linker->GetDexCache(idx); + for (jobject weak_root : class_linker->GetDexCaches()) { + mirror::DexCache* dex_cache = + down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + if (dex_cache == nullptr) { + continue; + } const DexFile* dex_file = dex_cache->GetDexFile(); dex_cache_array_starts_.Put(dex_file, size); DexCacheArraysLayout layout(target_ptr_size_, dex_file); @@ -554,39 +552,6 @@ void ImageWriter::ComputeLazyFieldsForImageClasses() { class_linker->VisitClassesWithoutClassesLock(&visitor); } -void ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg ATTRIBUTE_UNUSED) { - if (!obj->GetClass()->IsStringClass()) { - return; - } - mirror::String* string = obj->AsString(); - const uint16_t* utf16_string = string->GetValue(); - size_t utf16_length = static_cast<size_t>(string->GetLength()); - ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock()); - size_t dex_cache_count = class_linker->GetDexCacheCount(); - for (size_t i = 0; i < dex_cache_count; ++i) { - DexCache* dex_cache = class_linker->GetDexCache(i); - const DexFile& dex_file = *dex_cache->GetDexFile(); - const DexFile::StringId* string_id; - if (UNLIKELY(utf16_length == 0)) { - string_id = dex_file.FindStringId(""); - } else { - string_id = dex_file.FindStringId(utf16_string, utf16_length); - } - if (string_id != nullptr) { - // This string occurs in this dex file, assign the dex cache entry. - uint32_t string_idx = dex_file.GetIndexForStringId(*string_id); - if (dex_cache->GetResolvedString(string_idx) == nullptr) { - dex_cache->SetResolvedString(string_idx, string); - } - } - } -} - -void ImageWriter::ComputeEagerResolvedStrings() { - Runtime::Current()->GetHeap()->VisitObjects(ComputeEagerResolvedStringsCallback, this); -} - bool ImageWriter::IsImageClass(Class* klass) { if (klass == nullptr) { return false; @@ -631,16 +596,14 @@ void ImageWriter::PruneNonImageClasses() { // Clear references to removed classes from the DexCaches. const ArtMethod* resolution_method = runtime->GetResolutionMethod(); - size_t dex_cache_count; - { - ReaderMutexLock mu(self, *class_linker->DexLock()); - dex_cache_count = class_linker->GetDexCacheCount(); - } - for (size_t idx = 0; idx < dex_cache_count; ++idx) { - DexCache* dex_cache; - { - ReaderMutexLock mu(self, *class_linker->DexLock()); - dex_cache = class_linker->GetDexCache(idx); + + ScopedAssertNoThreadSuspension sa(self, __FUNCTION__); + ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); // For ClassInClassTable + ReaderMutexLock mu2(self, *class_linker->DexLock()); + for (jobject weak_root : class_linker->GetDexCaches()) { + mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + if (dex_cache == nullptr) { + continue; } for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { Class* klass = dex_cache->GetResolvedType(i); @@ -762,8 +725,12 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { ReaderMutexLock mu(self, *class_linker->DexLock()); CHECK_EQ(dex_cache_count, class_linker->GetDexCacheCount()) << "The number of dex caches changed."; - for (size_t i = 0; i < dex_cache_count; ++i) { - dex_caches->Set<false>(i, class_linker->GetDexCache(i)); + size_t i = 0; + for (jobject weak_root : class_linker->GetDexCaches()) { + mirror::DexCache* dex_cache = + down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + dex_caches->Set<false>(i, dex_cache); + ++i; } } diff --git a/compiler/image_writer.h b/compiler/image_writer.h index c8aa82dc32..778521c606 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -225,11 +225,6 @@ class ImageWriter FINAL { void ComputeLazyFieldsForImageClasses() SHARED_REQUIRES(Locks::mutator_lock_); - // Wire dex cache resolved strings to strings in the image to avoid runtime resolution. - void ComputeEagerResolvedStrings() SHARED_REQUIRES(Locks::mutator_lock_); - static void ComputeEagerResolvedStringsCallback(mirror::Object* obj, void* arg) - SHARED_REQUIRES(Locks::mutator_lock_); - // Remove unwanted classes from various roots. void PruneNonImageClasses() SHARED_REQUIRES(Locks::mutator_lock_); diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 64e748776d..0e0b224578 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -691,6 +691,8 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { OatClass* oat_class = writer_->oat_classes_[oat_class_index_]; const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); + // No thread suspension since dex_cache_ that may get invalidated if that occurs. + ScopedAssertNoThreadSuspension tsc(Thread::Current(), __FUNCTION__); if (compiled_method != nullptr) { // ie. not an abstract method size_t file_offset = file_offset_; OutputStream* out = out_; diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 97b9972001..824f28eb7c 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -362,7 +362,7 @@ void RTPVisitor::SetClassAsTypeInfo(HInstruction* instr, if (kIsDebugBuild) { ScopedObjectAccess soa(Thread::Current()); ClassLinker* cl = Runtime::Current()->GetClassLinker(); - mirror::DexCache* dex_cache = cl->FindDexCache(instr->AsInvoke()->GetDexFile()); + mirror::DexCache* dex_cache = cl->FindDexCache(instr->AsInvoke()->GetDexFile(), false); ArtMethod* method = dex_cache->GetResolvedMethod( instr->AsInvoke()->GetDexMethodIndex(), cl->GetImagePointerSize()); DCHECK(method != nullptr); diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 99736e95d0..07cf88c44a 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1207,6 +1207,14 @@ class Dex2Oat FINAL { oat_file_.reset(); } + void Shutdown() { + ScopedObjectAccess soa(Thread::Current()); + for (jobject dex_cache : dex_caches_) { + soa.Env()->DeleteLocalRef(dex_cache); + } + dex_caches_.clear(); + } + // Set up the environment for compilation. Includes starting the runtime and loading/opening the // boot class path. bool Setup() { @@ -1320,8 +1328,9 @@ class Dex2Oat FINAL { compiled_methods_.reset(nullptr); // By default compile everything. } + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); if (boot_image_option_.empty()) { - dex_files_ = Runtime::Current()->GetClassLinker()->GetBootClassPath(); + dex_files_ = class_linker->GetBootClassPath(); } else { if (dex_filenames_.empty()) { ATRACE_BEGIN("Opening zip archive from file descriptor"); @@ -1374,11 +1383,15 @@ class Dex2Oat FINAL { } } } - // Ensure opened dex files are writable for dex-to-dex transformations. + // Ensure opened dex files are writable for dex-to-dex transformations. Also ensure that + // the dex caches stay live since we don't want class unloading to occur during compilation. for (const auto& dex_file : dex_files_) { if (!dex_file->EnableWrite()) { PLOG(ERROR) << "Failed to make .dex file writeable '" << dex_file->GetLocation() << "'\n"; } + ScopedObjectAccess soa(self); + dex_caches_.push_back(soa.AddLocalReference<jobject>( + class_linker->RegisterDexFile(*dex_file))); } // If we use a swap file, ensure we are above the threshold to make it necessary. @@ -1423,6 +1436,7 @@ class Dex2Oat FINAL { // Handle and ClassLoader creation needs to come after Runtime::Create jobject class_loader = nullptr; Thread* self = Thread::Current(); + if (!boot_image_option_.empty()) { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); OpenClassPathFiles(runtime_->GetClassPathString(), dex_files_, &class_path_files_); @@ -1957,6 +1971,7 @@ class Dex2Oat FINAL { bool is_host_; std::string android_root_; std::vector<const DexFile*> dex_files_; + std::vector<jobject> dex_caches_; std::vector<std::unique_ptr<const DexFile>> opened_dex_files_; std::unique_ptr<CompilerDriver> driver_; std::vector<std::string> verbose_methods_; @@ -2107,11 +2122,15 @@ static int dex2oat(int argc, char** argv) { return EXIT_FAILURE; } + bool result; if (dex2oat.IsImage()) { - return CompileImage(dex2oat); + result = CompileImage(dex2oat); } else { - return CompileApp(dex2oat); + result = CompileApp(dex2oat); } + + dex2oat.Shutdown(); + return result; } } // namespace art diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index 44b78ff0a3..1950d56419 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -812,11 +812,15 @@ class OatDumper { DumpDexCode(vios->Stream(), dex_file, code_item); } + std::unique_ptr<StackHandleScope<1>> hs; std::unique_ptr<verifier::MethodVerifier> verifier; if (Runtime::Current() != nullptr) { + // We need to have the handle scope stay live until after the verifier since the verifier has + // a handle to the dex cache from hs. + hs.reset(new StackHandleScope<1>(Thread::Current())); vios->Stream() << "VERIFIER TYPE ANALYSIS:\n"; ScopedIndentation indent2(vios); - verifier.reset(DumpVerifier(vios, + verifier.reset(DumpVerifier(vios, hs.get(), dex_method_idx, &dex_file, class_def, code_item, method_access_flags)); } @@ -1389,6 +1393,7 @@ class OatDumper { } verifier::MethodVerifier* DumpVerifier(VariableIndentationOutputStream* vios, + StackHandleScope<1>* hs, uint32_t dex_method_idx, const DexFile* dex_file, const DexFile::ClassDef& class_def, @@ -1396,9 +1401,8 @@ class OatDumper { uint32_t method_access_flags) { if ((method_access_flags & kAccNative) == 0) { ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<1> hs(soa.Self()); Handle<mirror::DexCache> dex_cache( - hs.NewHandle(Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file))); + hs->NewHandle(Runtime::Current()->GetClassLinker()->RegisterDexFile(*dex_file))); DCHECK(options_.class_loader_ != nullptr); return verifier::MethodVerifier::VerifyMethodAndDump( soa.Self(), vios, dex_method_idx, dex_file, dex_cache, *options_.class_loader_, @@ -1599,10 +1603,13 @@ class ImageDumper { dex_cache_arrays_.clear(); { ReaderMutexLock mu(self, *class_linker->DexLock()); - for (size_t i = 0; i < class_linker->GetDexCacheCount(); ++i) { - auto* dex_cache = class_linker->GetDexCache(i); - dex_cache_arrays_.insert(dex_cache->GetResolvedFields()); - dex_cache_arrays_.insert(dex_cache->GetResolvedMethods()); + for (jobject weak_root : class_linker->GetDexCaches()) { + mirror::DexCache* dex_cache = + down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + if (dex_cache != nullptr) { + dex_cache_arrays_.insert(dex_cache->GetResolvedFields()); + dex_cache_arrays_.insert(dex_cache->GetResolvedMethods()); + } } } ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h index 848c904fe6..5f2caef651 100644 --- a/runtime/base/mutex.h +++ b/runtime/base/mutex.h @@ -64,6 +64,7 @@ enum LockLevel { kJdwpSocketLock, kRegionSpaceRegionLock, kTransactionLogLock, + kJniWeakGlobalsLock, kReferenceQueueSoftReferencesLock, kReferenceQueuePhantomReferencesLock, kReferenceQueueFinalizerReferencesLock, diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 11901b3bef..d2dbff634e 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -195,12 +195,6 @@ inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) return klass; } -inline mirror::DexCache* ClassLinker::GetDexCache(size_t idx) { - dex_lock_.AssertSharedHeld(Thread::Current()); - DCHECK(idx < dex_caches_.size()); - return dex_caches_[idx].Read(); -} - } // namespace art #endif // ART_RUNTIME_CLASS_LINKER_INL_H_ diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index b074deccf7..3b505e6bf9 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -273,7 +273,6 @@ ClassLinker::ClassLinker(InternTable* intern_table) array_iftable_(nullptr), find_array_class_cache_next_victim_(0), init_done_(false), - log_new_dex_caches_roots_(false), log_new_class_table_roots_(false), intern_table_(intern_table), quick_resolution_trampoline_(nullptr), @@ -332,6 +331,12 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b java_lang_Class->SetSuperClass(java_lang_Object.Get()); mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusLoaded, self); + java_lang_Object->SetObjectSize(sizeof(mirror::Object)); + runtime->SetSentinel(heap->AllocObject<true>(self, + java_lang_Object.Get(), + java_lang_Object->GetObjectSize(), + VoidFunctor())); + // Object[] next to hold class roots. Handle<mirror::Class> object_array_class(hs.NewHandle( AllocClass(self, java_lang_Class.Get(), @@ -1143,11 +1148,11 @@ void ClassLinker::InitFromImage() { quick_imt_conflict_trampoline_ = oat_file.GetOatHeader().GetQuickImtConflictTrampoline(); quick_generic_jni_trampoline_ = oat_file.GetOatHeader().GetQuickGenericJniTrampoline(); quick_to_interpreter_bridge_trampoline_ = oat_file.GetOatHeader().GetQuickToInterpreterBridge(); + StackHandleScope<2> hs(self); mirror::Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); - mirror::ObjectArray<mirror::DexCache>* dex_caches = - dex_caches_object->AsObjectArray<mirror::DexCache>(); + Handle<mirror::ObjectArray<mirror::DexCache>> dex_caches( + hs.NewHandle(dex_caches_object->AsObjectArray<mirror::DexCache>())); - StackHandleScope<1> hs(self); Handle<mirror::ObjectArray<mirror::Class>> class_roots(hs.NewHandle( space->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)-> AsObjectArray<mirror::Class>())); @@ -1157,6 +1162,13 @@ void ClassLinker::InitFromImage() { // as being Strings or not mirror::String::SetClass(GetClassRoot(kJavaLangString)); + mirror::Class* java_lang_Object = GetClassRoot(kJavaLangObject); + java_lang_Object->SetObjectSize(sizeof(mirror::Object)); + Runtime::Current()->SetSentinel(Runtime::Current()->GetHeap()->AllocObject<true>(self, + java_lang_Object, + java_lang_Object->GetObjectSize(), + VoidFunctor())); + CHECK_EQ(oat_file.GetOatHeader().GetDexFileCount(), static_cast<uint32_t>(dex_caches->GetLength())); for (int32_t i = 0; i < dex_caches->GetLength(); i++) { @@ -1250,7 +1262,6 @@ void ClassLinker::InitFromImage() { } bool ClassLinker::ClassInClassTable(mirror::Class* klass) { - ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); ClassTable* const class_table = ClassTableForClassLoader(klass->GetClassLoader()); return class_table != nullptr && class_table->Contains(klass); } @@ -1307,27 +1318,6 @@ void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) { // mapped image. void ClassLinker::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) { class_roots_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); - Thread* const self = Thread::Current(); - { - ReaderMutexLock mu(self, dex_lock_); - if ((flags & kVisitRootFlagAllRoots) != 0) { - for (GcRoot<mirror::DexCache>& dex_cache : dex_caches_) { - dex_cache.VisitRoot(visitor, RootInfo(kRootVMInternal)); - } - } else if ((flags & kVisitRootFlagNewRoots) != 0) { - for (size_t index : new_dex_cache_roots_) { - dex_caches_[index].VisitRoot(visitor, RootInfo(kRootVMInternal)); - } - } - if ((flags & kVisitRootFlagClearRootLog) != 0) { - new_dex_cache_roots_.clear(); - } - if ((flags & kVisitRootFlagStartLoggingNewRoots) != 0) { - log_new_dex_caches_roots_ = true; - } else if ((flags & kVisitRootFlagStopLoggingNewRoots) != 0) { - log_new_dex_caches_roots_ = false; - } - } VisitClassRoots(visitor, flags); array_iftable_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); for (GcRoot<mirror::Class>& root : find_array_class_cache_) { @@ -1702,7 +1692,6 @@ bool ClassLinker::FindClassInPathClassLoader(ScopedObjectAccessAlreadyRunnable& long_array->GetWithoutChecks(j))); const DexFile::ClassDef* dex_class_def = cp_dex_file->FindClassDef(descriptor, hash); if (dex_class_def != nullptr) { - RegisterDexFile(*cp_dex_file); mirror::Class* klass = DefineClass(self, descriptor, hash, class_loader, *cp_dex_file, *dex_class_def); if (klass == nullptr) { @@ -1848,7 +1837,7 @@ mirror::Class* ClassLinker::DefineClass(Thread* self, const char* descriptor, si CHECK(self->IsExceptionPending()); // Expect an OOME. return nullptr; } - klass->SetDexCache(FindDexCache(dex_file)); + klass->SetDexCache(RegisterDexFile(dex_file)); SetupClass(dex_file, dex_class_def, klass, class_loader.Get()); @@ -2482,58 +2471,52 @@ void ClassLinker::AppendToBootClassPath(const DexFile& dex_file, RegisterDexFile(dex_file, dex_cache); } -bool ClassLinker::IsDexFileRegisteredLocked(const DexFile& dex_file) { - dex_lock_.AssertSharedHeld(Thread::Current()); - for (GcRoot<mirror::DexCache>& root : dex_caches_) { - mirror::DexCache* dex_cache = root.Read(); - if (dex_cache->GetDexFile() == &dex_file) { - return true; - } - } - return false; -} - -bool ClassLinker::IsDexFileRegistered(const DexFile& dex_file) { - ReaderMutexLock mu(Thread::Current(), dex_lock_); - return IsDexFileRegisteredLocked(dex_file); -} - void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache) { - dex_lock_.AssertExclusiveHeld(Thread::Current()); + Thread* const self = Thread::Current(); + dex_lock_.AssertExclusiveHeld(self); CHECK(dex_cache.Get() != nullptr) << dex_file.GetLocation(); CHECK(dex_cache->GetLocation()->Equals(dex_file.GetLocation())) << dex_cache->GetLocation()->ToModifiedUtf8() << " " << dex_file.GetLocation(); - dex_caches_.push_back(GcRoot<mirror::DexCache>(dex_cache.Get())); - dex_cache->SetDexFile(&dex_file); - if (log_new_dex_caches_roots_) { - // TODO: This is not safe if we can remove dex caches. - new_dex_cache_roots_.push_back(dex_caches_.size() - 1); + // Clean up pass to remove null dex caches. + // Null dex caches can occur due to class unloading and we are lazily removing null entries. + JavaVMExt* const vm = self->GetJniEnv()->vm; + for (auto it = dex_caches_.begin(); it != dex_caches_.end();) { + mirror::Object* dex_cache_root = self->DecodeJObject(*it); + if (dex_cache_root == nullptr) { + vm->DeleteWeakGlobalRef(self, *it); + it = dex_caches_.erase(it); + } else { + ++it; + } } + dex_caches_.push_back(vm->AddWeakGlobalRef(self, dex_cache.Get())); + dex_cache->SetDexFile(&dex_file); } -void ClassLinker::RegisterDexFile(const DexFile& dex_file) { +mirror::DexCache* ClassLinker::RegisterDexFile(const DexFile& dex_file) { Thread* self = Thread::Current(); { ReaderMutexLock mu(self, dex_lock_); - if (IsDexFileRegisteredLocked(dex_file)) { - return; + mirror::DexCache* dex_cache = FindDexCacheLocked(dex_file, true); + if (dex_cache != nullptr) { + return dex_cache; } } // 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> dex_cache(hs.NewHandle(AllocDexCache(self, dex_file))); - CHECK(dex_cache.Get() != nullptr) << "Failed to allocate dex cache for " - << dex_file.GetLocation(); - { - WriterMutexLock mu(self, dex_lock_); - if (IsDexFileRegisteredLocked(dex_file)) { - return; - } - RegisterDexFileLocked(dex_file, dex_cache); + Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(AllocDexCache(self, dex_file))); + CHECK(h_dex_cache.Get() != nullptr) << "Failed to allocate dex cache for " + << dex_file.GetLocation(); + WriterMutexLock mu(self, dex_lock_); + mirror::DexCache* dex_cache = FindDexCacheLocked(dex_file, true); + if (dex_cache != nullptr) { + return dex_cache; } + RegisterDexFileLocked(dex_file, h_dex_cache); + return h_dex_cache.Get(); } void ClassLinker::RegisterDexFile(const DexFile& dex_file, @@ -2542,36 +2525,44 @@ void ClassLinker::RegisterDexFile(const DexFile& dex_file, RegisterDexFileLocked(dex_file, dex_cache); } -mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) { - ReaderMutexLock mu(Thread::Current(), dex_lock_); +mirror::DexCache* ClassLinker::FindDexCache(const DexFile& dex_file, bool allow_failure) { + Thread* const self = Thread::Current(); + ReaderMutexLock mu(self, dex_lock_); + return FindDexCacheLocked(dex_file, allow_failure); +} + +mirror::DexCache* ClassLinker::FindDexCacheLocked(const DexFile& dex_file, bool allow_failure) { + Thread* const self = Thread::Current(); // Search assuming unique-ness of dex file. - for (size_t i = 0; i != dex_caches_.size(); ++i) { - mirror::DexCache* dex_cache = GetDexCache(i); - if (dex_cache->GetDexFile() == &dex_file) { + for (jobject weak_root : dex_caches_) { + mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + if (dex_cache != nullptr && dex_cache->GetDexFile() == &dex_file) { return dex_cache; } } - // Search matching by location name. - std::string location(dex_file.GetLocation()); - for (size_t i = 0; i != dex_caches_.size(); ++i) { - mirror::DexCache* dex_cache = GetDexCache(i); - if (dex_cache->GetDexFile()->GetLocation() == location) { - return dex_cache; - } + if (allow_failure) { + return nullptr; } + std::string location(dex_file.GetLocation()); // Failure, dump diagnostic and abort. - for (size_t i = 0; i != dex_caches_.size(); ++i) { - mirror::DexCache* dex_cache = GetDexCache(i); - LOG(ERROR) << "Registered dex file " << i << " = " << dex_cache->GetDexFile()->GetLocation(); + for (jobject weak_root : dex_caches_) { + mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + if (dex_cache != nullptr) { + LOG(ERROR) << "Registered dex file " << dex_cache->GetDexFile()->GetLocation(); + } } LOG(FATAL) << "Failed to find DexCache for DexFile " << location; UNREACHABLE(); } void ClassLinker::FixupDexCaches(ArtMethod* resolution_method) { - ReaderMutexLock mu(Thread::Current(), dex_lock_); - for (auto& dex_cache : dex_caches_) { - dex_cache.Read()->Fixup(resolution_method, image_pointer_size_); + Thread* const self = Thread::Current(); + ReaderMutexLock mu(self, dex_lock_); + for (jobject weak_root : dex_caches_) { + mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + if (dex_cache != nullptr) { + dex_cache->Fixup(resolution_method, image_pointer_size_); + } } } @@ -3407,11 +3398,13 @@ ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, ArtMethod DCHECK(proxy_class->IsProxyClass()); DCHECK(proxy_method->IsProxyMethod()); { - ReaderMutexLock mu(Thread::Current(), dex_lock_); + Thread* const self = Thread::Current(); + ReaderMutexLock mu(self, dex_lock_); // Locate the dex cache of the original interface/Object - for (const GcRoot<mirror::DexCache>& root : dex_caches_) { - auto* dex_cache = root.Read(); - if (proxy_method->HasSameDexCacheResolvedTypes(dex_cache->GetResolvedTypes())) { + for (jobject weak_root : dex_caches_) { + mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(weak_root)); + if (dex_cache != nullptr && + proxy_method->HasSameDexCacheResolvedTypes(dex_cache->GetResolvedTypes())) { ArtMethod* resolved_method = dex_cache->GetResolvedMethod( proxy_method->GetDexMethodIndex(), image_pointer_size_); CHECK(resolved_method != nullptr); @@ -5878,11 +5871,6 @@ jobject ClassLinker::CreatePathClassLoader(Thread* self, std::vector<const DexFi // We could move the jobject to the callers, but all call-sites do this... ScopedObjectAccessUnchecked soa(self); - // Register the dex files. - for (const DexFile* dex_file : dex_files) { - RegisterDexFile(*dex_file); - } - // For now, create a libcore-level DexFile for each ART DexFile. This "explodes" multidex. StackHandleScope<10> hs(self); diff --git a/runtime/class_linker.h b/runtime/class_linker.h index fbf4035842..cc56e8b570 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -278,7 +278,7 @@ class ClassLinker { void RunRootClinits() SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!dex_lock_, !Roles::uninterruptible_); - void RegisterDexFile(const DexFile& dex_file) + mirror::DexCache* RegisterDexFile(const DexFile& dex_file) REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_); void RegisterDexFile(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache) REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_); @@ -309,9 +309,7 @@ class ClassLinker { void VisitRoots(RootVisitor* visitor, VisitRootFlags flags) REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_); - mirror::DexCache* FindDexCache(const DexFile& dex_file) - REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_); - bool IsDexFileRegistered(const DexFile& dex_file) + mirror::DexCache* FindDexCache(const DexFile& dex_file, bool allow_failure = false) REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_); void FixupDexCaches(ArtMethod* resolution_method) REQUIRES(!dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_); @@ -471,7 +469,7 @@ class ClassLinker { // Used by image writer for checking. bool ClassInClassTable(mirror::Class* klass) - REQUIRES(!Locks::classlinker_classes_lock_) + REQUIRES(Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_); ArtMethod* CreateRuntimeMethod(); @@ -561,8 +559,9 @@ class ClassLinker { void RegisterDexFileLocked(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache) REQUIRES(dex_lock_) SHARED_REQUIRES(Locks::mutator_lock_); - bool IsDexFileRegisteredLocked(const DexFile& dex_file) - SHARED_REQUIRES(dex_lock_, Locks::mutator_lock_); + mirror::DexCache* FindDexCacheLocked(const DexFile& dex_file, bool allow_failure) + REQUIRES(dex_lock_) + SHARED_REQUIRES(Locks::mutator_lock_); bool InitializeClass(Thread* self, Handle<mirror::Class> klass, bool can_run_clinit, bool can_init_parents) @@ -631,7 +630,9 @@ class ClassLinker { size_t GetDexCacheCount() SHARED_REQUIRES(Locks::mutator_lock_, dex_lock_) { return dex_caches_.size(); } - mirror::DexCache* GetDexCache(size_t idx) SHARED_REQUIRES(Locks::mutator_lock_, dex_lock_); + const std::list<jobject>& GetDexCaches() SHARED_REQUIRES(Locks::mutator_lock_, dex_lock_) { + return dex_caches_; + } const OatFile* FindOpenedOatFileFromOatLocation(const std::string& oat_location) REQUIRES(!dex_lock_); @@ -702,8 +703,9 @@ class ClassLinker { std::vector<std::unique_ptr<const DexFile>> opened_dex_files_; mutable ReaderWriterMutex dex_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; - std::vector<size_t> new_dex_cache_roots_ GUARDED_BY(dex_lock_); - std::vector<GcRoot<mirror::DexCache>> dex_caches_ GUARDED_BY(dex_lock_); + // JNI weak globals to allow dex caches to get unloaded. We lazily delete weak globals when we + // register new dex files. + std::list<jobject> dex_caches_ GUARDED_BY(dex_lock_); std::vector<const OatFile*> oat_files_ GUARDED_BY(dex_lock_); // This contains the class laoders which have class tables. It is populated by @@ -736,7 +738,6 @@ class ClassLinker { size_t find_array_class_cache_next_victim_; bool init_done_; - bool log_new_dex_caches_roots_ GUARDED_BY(dex_lock_); bool log_new_class_table_roots_ GUARDED_BY(Locks::classlinker_classes_lock_); InternTable* intern_table_; diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc index 5f9e413ed2..56c5d1a2c3 100644 --- a/runtime/common_runtime_test.cc +++ b/runtime/common_runtime_test.cc @@ -551,7 +551,8 @@ jobject CommonRuntimeTest::LoadDex(const char* dex_name) { } Thread* self = Thread::Current(); - jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self, class_path); + jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self, + class_path); self->SetClassLoaderOverride(class_loader); return class_loader; } diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index 9d41018c1b..2fd0517061 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -373,7 +373,7 @@ JavaVMExt::JavaVMExt(Runtime* runtime, const RuntimeArgumentMap& runtime_options globals_(gGlobalsInitial, gGlobalsMax, kGlobal), libraries_(new Libraries), unchecked_functions_(&gJniInvokeInterface), - weak_globals_lock_("JNI weak global reference table lock"), + weak_globals_lock_("JNI weak global reference table lock", kJniWeakGlobalsLock), weak_globals_(kWeakGlobalsInitial, kWeakGlobalsMax, kWeakGlobal), allow_new_weak_globals_(true), weak_globals_add_condition_("weak globals add condition", weak_globals_lock_) { diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index 4f97d20d6c..9bd320cf07 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -171,7 +171,7 @@ static jobject DexFile_openDexFileNative( if (array == nullptr) { ScopedObjectAccess soa(env); for (auto& dex_file : dex_files) { - if (Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) { + if (Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file, true) != nullptr) { dex_file.release(); } } @@ -209,7 +209,7 @@ static void DexFile_closeDexFile(JNIEnv* env, jclass, jobject cookie) { // TODO: The Runtime should support unloading of classes and freeing of the // dex files for those unloaded classes rather than leaking dex files here. for (auto& dex_file : *dex_files) { - if (!Runtime::Current()->GetClassLinker()->IsDexFileRegistered(*dex_file)) { + if (Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file, true) == nullptr) { delete dex_file; } } diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 9ea339a6bd..5a9c43bd22 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -425,14 +425,16 @@ static void PreloadDexCachesStatsTotal(DexCacheStats* total) { static void PreloadDexCachesStatsFilled(DexCacheStats* filled) SHARED_REQUIRES(Locks::mutator_lock_) { if (!kPreloadDexCachesCollectStats) { - return; + return; } - ClassLinker* linker = Runtime::Current()->GetClassLinker(); - const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath(); - for (size_t i = 0; i< boot_class_path.size(); i++) { - const DexFile* dex_file = boot_class_path[i]; + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); + for (const DexFile* dex_file : class_linker->GetBootClassPath()) { CHECK(dex_file != nullptr); - mirror::DexCache* dex_cache = linker->FindDexCache(*dex_file); + mirror::DexCache* const dex_cache = class_linker->FindDexCache(*dex_file, true); + // If dex cache was deallocated, just continue. + if (dex_cache == nullptr) { + continue; + } for (size_t j = 0; j < dex_cache->NumStrings(); j++) { mirror::String* string = dex_cache->GetResolvedString(j); if (string != nullptr) { @@ -446,7 +448,7 @@ static void PreloadDexCachesStatsFilled(DexCacheStats* filled) } } for (size_t j = 0; j < dex_cache->NumResolvedFields(); j++) { - ArtField* field = linker->GetResolvedField(j, dex_cache); + ArtField* field = class_linker->GetResolvedField(j, dex_cache); if (field != nullptr) { filled->num_fields++; } @@ -490,11 +492,11 @@ static void VMRuntime_preloadDexCaches(JNIEnv* env, jobject) { } const std::vector<const DexFile*>& boot_class_path = linker->GetBootClassPath(); - for (size_t i = 0; i< boot_class_path.size(); i++) { + for (size_t i = 0; i < boot_class_path.size(); i++) { 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->FindDexCache(*dex_file))); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->RegisterDexFile(*dex_file))); if (kPreloadDexCachesStrings) { for (size_t j = 0; j < dex_cache->NumStrings(); j++) { diff --git a/runtime/runtime-inl.h b/runtime/runtime-inl.h index 380e72b5dd..bfa8c549bf 100644 --- a/runtime/runtime-inl.h +++ b/runtime/runtime-inl.h @@ -20,6 +20,7 @@ #include "runtime.h" #include "art_method.h" +#include "class_linker.h" #include "read_barrier-inl.h" namespace art { diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 1912314d17..49451ade94 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -791,6 +791,12 @@ static size_t OpenDexFiles(const std::vector<std::string>& dex_filenames, return failure_count; } +void Runtime::SetSentinel(mirror::Object* sentinel) { + CHECK(sentinel_.Read() == nullptr); + CHECK(sentinel != nullptr); + sentinel_ = GcRoot<mirror::Object>(sentinel); +} + bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) { ATRACE_BEGIN("Runtime::Init"); CHECK_EQ(sysconf(_SC_PAGE_SIZE), kPageSize); @@ -1054,10 +1060,6 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) CHECK(class_linker_ != nullptr); - // Initialize the special sentinel_ value early. - sentinel_ = GcRoot<mirror::Object>(class_linker_->AllocObject(self)); - CHECK(sentinel_.Read() != nullptr); - verifier::MethodVerifier::Init(); if (runtime_options.Exists(Opt::MethodTrace)) { diff --git a/runtime/runtime.h b/runtime/runtime.h index 4577b75397..bd21db16c4 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -568,6 +568,9 @@ class Runtime { return fingerprint_; } + // Called from class linker. + void SetSentinel(mirror::Object* sentinel) SHARED_REQUIRES(Locks::mutator_lock_); + private: static void InitPlatformSignalHandlers(); diff --git a/runtime/trace.cc b/runtime/trace.cc index 439343068c..7579d8d0e0 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -640,7 +640,8 @@ static void GetVisitedMethodsFromBitSets( ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); for (auto& e : seen_methods) { DexIndexBitSet* bit_set = e.second; - mirror::DexCache* dex_cache = class_linker->FindDexCache(*e.first); + // TODO: Visit trace methods as roots. + mirror::DexCache* dex_cache = class_linker->FindDexCache(*e.first, false); for (uint32_t i = 0; i < bit_set->size(); ++i) { if ((*bit_set)[i]) { visited_methods->insert(dex_cache->GetResolvedMethod(i, sizeof(void*))); diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index efefa8ba75..5b73f10e6d 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -3379,6 +3379,7 @@ const RegType& MethodVerifier::GetCaughtExceptionType() { ArtMethod* MethodVerifier::ResolveMethodAndCheckAccess( uint32_t dex_method_idx, MethodType method_type) { const DexFile::MethodId& method_id = dex_file_->GetMethodId(dex_method_idx); + // LOG(INFO) << dex_file_->NumTypeIds() << " " << dex_file_->NumClassDefs(); const RegType& klass_type = ResolveClassAndCheckAccess(method_id.class_idx_); if (klass_type.IsConflict()) { std::string append(" in attempt to access method "); |