diff options
author | Santiago Aboy Solanes <solanes@google.com> | 2024-05-02 15:40:47 +0100 |
---|---|---|
committer | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2024-05-03 15:40:42 +0000 |
commit | a4ac01044c50f4da02c40b8da5520d2eb65b41d9 (patch) | |
tree | cd19c2cf8a0422876df3d70327687229748bd77a | |
parent | 721bbf2bfd6ffe689067df5657059925e038bb0d (diff) | |
download | art-a4ac01044c50f4da02c40b8da5520d2eb65b41d9.tar.gz |
Workaround for b/336842546
Resolve the type if it hasn't been resolved before. Also, change to
use Handles instead of ObjPtr since ResolveType can potentially
suspend.
Bug: 336842546
Bug: 73760543
Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: I8ad77e63d6d9cc76fee8aac88742d4a4b678abf5
-rw-r--r-- | compiler/dex/inline_method_analyser.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 8 | ||||
-rw-r--r-- | dex2oat/linker/oat_writer.cc | 11 | ||||
-rw-r--r-- | runtime/class_linker-inl.h | 25 | ||||
-rw-r--r-- | runtime/class_linker.h | 4 | ||||
-rw-r--r-- | runtime/entrypoints/entrypoint_utils-inl.h | 34 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 7 |
7 files changed, 62 insertions, 32 deletions
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc index 85cf83c099..0567fe12c8 100644 --- a/compiler/dex/inline_method_analyser.cc +++ b/compiler/dex/inline_method_analyser.cc @@ -147,8 +147,11 @@ ArtMethod* GetTargetConstructor(ArtMethod* method, const Instruction* invoke_dir accessor.RegistersSize() - accessor.InsSize()); } uint32_t method_index = invoke_direct->VRegB_35c(); + StackHandleScope<2> hs(Thread::Current()); + Handle<mirror::DexCache> h_dex_cache = hs.NewHandle(method->GetDexCache()); + Handle<mirror::ClassLoader> h_class_loader = hs.NewHandle(method->GetClassLoader()); ArtMethod* target_method = Runtime::Current()->GetClassLinker()->LookupResolvedMethod( - method_index, method->GetDexCache(), method->GetClassLoader()); + method_index, h_dex_cache, h_class_loader); if (kIsDebugBuild && target_method != nullptr) { CHECK(!target_method->IsStatic()); CHECK(target_method->IsConstructor()); diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 45d534a9ec..a75ac9239b 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -1183,14 +1183,14 @@ CompiledMethod* OptimizingCompiler::JniCompile(uint32_t access_flags, const CompilerOptions& compiler_options = GetCompilerOptions(); if (compiler_options.IsBootImage()) { ScopedObjectAccess soa(Thread::Current()); - ArtMethod* method = runtime->GetClassLinker()->LookupResolvedMethod( - method_idx, dex_cache.Get(), /*class_loader=*/ nullptr); + VariableSizedHandleScope handles(soa.Self()); + ScopedNullHandle<mirror::ClassLoader> class_loader; // null means boot class path loader. + ArtMethod* method = + runtime->GetClassLinker()->LookupResolvedMethod(method_idx, dex_cache, class_loader); // Try to compile a fully intrinsified implementation. Do not try to do this for // signature polymorphic methods as the InstructionBuilder cannot handle them; // and it would be useless as they always have a slow path for type conversions. if (method != nullptr && UNLIKELY(method->IsIntrinsic()) && !method->IsSignaturePolymorphic()) { - VariableSizedHandleScope handles(soa.Self()); - ScopedNullHandle<mirror::ClassLoader> class_loader; // null means boot class path loader. Handle<mirror::Class> compiling_class = handles.NewHandle(method->GetDeclaringClass()); DexCompilationUnit dex_compilation_unit( class_loader, diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index 0dbb4bb05b..b1287d9ab3 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -1822,11 +1822,12 @@ class OatWriter::WriteCodeMethodVisitor : public OrderedMethodVisitor { ArtMethod* GetTargetMethod(const LinkerPatch& patch) REQUIRES_SHARED(Locks::mutator_lock_) { MethodReference ref = patch.TargetMethod(); - ObjPtr<mirror::DexCache> dex_cache = - (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache( - Thread::Current(), *ref.dex_file); - ArtMethod* method = - class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_); + StackHandleScope<3> hs(Thread::Current()); + Handle<mirror::DexCache> h_dex_cache = hs.NewHandle(GetDexCache(ref.dex_file)); + // We must save both ObjPtr since they might be obsolete after LookupResolvedMethod. + HandleWrapperObjPtr<mirror::DexCache> h_original_dex_cache(hs.NewHandleWrapper(&dex_cache_)); + HandleWrapperObjPtr<mirror::ClassLoader> h_class_loader(hs.NewHandleWrapper(&class_loader_)); + ArtMethod* method = class_linker_->LookupResolvedMethod(ref.index, h_dex_cache, h_class_loader); CHECK(method != nullptr); return method; } diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h index 6951e35791..1f5272c7ce 100644 --- a/runtime/class_linker-inl.h +++ b/runtime/class_linker-inl.h @@ -271,16 +271,31 @@ inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_c } inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx, - ObjPtr<mirror::DexCache> dex_cache, - ObjPtr<mirror::ClassLoader> class_loader) { - DCHECK(dex_cache->GetClassLoader() == class_loader); + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader) { + DCHECK(dex_cache->GetClassLoader() == class_loader.Get()); ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx); if (resolved == nullptr) { const DexFile& dex_file = *dex_cache->GetDexFile(); const dex::MethodId& method_id = dex_file.GetMethodId(method_idx); - ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader); + ObjPtr<mirror::Class> klass = + LookupResolvedType(method_id.class_idx_, dex_cache.Get(), class_loader.Get()); + + if (UNLIKELY(klass == nullptr)) { + // We normaly should not end up here. However the verifier currently doesn't guarantee + // the invariant of having the klass in the class table. b/73760543 b/336842546 + klass = ResolveType(method_id.class_idx_, dex_cache, class_loader); + if (UNLIKELY(klass == nullptr)) { + // This can only happen if the current thread is not allowed to load + // classes. + DCHECK(!Thread::Current()->CanLoadClasses()); + DCHECK(Thread::Current()->IsExceptionPending()); + return nullptr; + } + } + if (klass != nullptr) { - resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx); + resolved = FindResolvedMethod(klass, dex_cache.Get(), class_loader.Get(), method_idx); } } return resolved; diff --git a/runtime/class_linker.h b/runtime/class_linker.h index eabfb4926a..7f53ca6e93 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -339,8 +339,8 @@ class EXPORT ClassLinker { // Look up a previously resolved method with the given index. ArtMethod* LookupResolvedMethod(uint32_t method_idx, - ObjPtr<mirror::DexCache> dex_cache, - ObjPtr<mirror::ClassLoader> class_loader) + Handle<mirror::DexCache> dex_cache, + Handle<mirror::ClassLoader> class_loader) REQUIRES_SHARED(Locks::mutator_lock_); // Find a method with the given index from class `klass`, and update the dex cache. diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index b0d0ab4b07..e1efa4a0ac 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -131,50 +131,60 @@ inline ArtMethod* GetResolvedMethod(ArtMethod* outer_method, ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); ArtMethod* method = outer_method; for (InlineInfo inline_info : inline_infos) { + StackHandleScope<2> hs(Thread::Current()); + Handle<mirror::DexCache> h_dex_cache; + Handle<mirror::ClassLoader> h_class_loader; DCHECK(!inline_info.EncodesArtMethod()); DCHECK_NE(inline_info.GetDexPc(), static_cast<uint32_t>(-1)); MethodInfo method_info = code_info.GetMethodInfoOf(inline_info); uint32_t method_index = method_info.GetMethodIndex(); const uint32_t dex_file_index = method_info.GetDexFileIndex(); ArtMethod* inlined_method = nullptr; - ObjPtr<mirror::DexCache> dex_cache = nullptr; if (method_info.HasDexFileIndex()) { if (method_info.GetDexFileIndexKind() == MethodInfo::kKindBCP) { ArrayRef<const DexFile* const> bcp_dex_files(class_linker->GetBootClassPath()); DCHECK_LT(dex_file_index, bcp_dex_files.size()) << "OOB access to bcp_dex_files. Dumping info: " - << GetResolvedMethodErrorString( - class_linker, inlined_method, method, outer_method, dex_cache, method_info); + << GetResolvedMethodErrorString(class_linker, + inlined_method, + method, + outer_method, + /*dex_cache=*/ nullptr, + method_info); const DexFile* dex_file = bcp_dex_files[dex_file_index]; DCHECK_NE(dex_file, nullptr); - dex_cache = class_linker->FindDexCache(Thread::Current(), *dex_file); + h_dex_cache = hs.NewHandle(class_linker->FindDexCache(Thread::Current(), *dex_file)); } else { ArrayRef<const OatDexFile* const> oat_dex_files( outer_method->GetDexFile()->GetOatDexFile()->GetOatFile()->GetOatDexFiles()); DCHECK_LT(dex_file_index, oat_dex_files.size()) << "OOB access to oat_dex_files. Dumping info: " - << GetResolvedMethodErrorString( - class_linker, inlined_method, method, outer_method, dex_cache, method_info); + << GetResolvedMethodErrorString(class_linker, + inlined_method, + method, + outer_method, + /*dex_cache=*/ nullptr, + method_info); const OatDexFile* odf = oat_dex_files[dex_file_index]; DCHECK_NE(odf, nullptr); - dex_cache = class_linker->FindDexCache(Thread::Current(), *odf); + h_dex_cache = hs.NewHandle(class_linker->FindDexCache(Thread::Current(), *odf)); } } else { - dex_cache = outer_method->GetDexCache(); + h_dex_cache = hs.NewHandle(outer_method->GetDexCache()); } - inlined_method = - class_linker->LookupResolvedMethod(method_index, dex_cache, dex_cache->GetClassLoader()); + h_class_loader = hs.NewHandle(h_dex_cache->GetClassLoader()); + inlined_method = class_linker->LookupResolvedMethod(method_index, h_dex_cache, h_class_loader); if (UNLIKELY(inlined_method == nullptr)) { LOG(FATAL) << GetResolvedMethodErrorString( - class_linker, inlined_method, method, outer_method, dex_cache, method_info); + class_linker, inlined_method, method, outer_method, h_dex_cache.Get(), method_info); UNREACHABLE(); } DCHECK(!inlined_method->IsRuntimeMethod()); DCHECK_EQ(inlined_method->GetDexFile() == outer_method->GetDexFile(), dex_file_index == MethodInfo::kSameDexFile) << GetResolvedMethodErrorString( - class_linker, inlined_method, method, outer_method, dex_cache, method_info); + class_linker, inlined_method, method, outer_method, h_dex_cache.Get(), method_info); method = inlined_method; } diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index b53339acd9..85e5d4e1f4 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -1114,9 +1114,10 @@ static void DumpB74410240DebugData(ArtMethod** sp) REQUIRES_SHARED(Locks::mutato caller = WellKnownClasses::java_lang_String_charAt; CHECK_EQ(caller->GetDexMethodIndex(), method_index); } else { - ObjPtr<mirror::DexCache> dex_cache = caller->GetDexCache(); - ObjPtr<mirror::ClassLoader> class_loader = caller->GetClassLoader(); - caller = class_linker->LookupResolvedMethod(method_index, dex_cache, class_loader); + StackHandleScope<2> hs(Thread::Current()); + Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(caller->GetDexCache())); + Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(caller->GetClassLoader())); + caller = class_linker->LookupResolvedMethod(method_index, h_dex_cache, h_class_loader); CHECK(caller != nullptr); } } |