summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSantiago Aboy Solanes <solanes@google.com>2024-05-02 15:40:47 +0100
committerTreehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com>2024-05-03 15:40:42 +0000
commita4ac01044c50f4da02c40b8da5520d2eb65b41d9 (patch)
treecd19c2cf8a0422876df3d70327687229748bd77a
parent721bbf2bfd6ffe689067df5657059925e038bb0d (diff)
downloadart-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.cc5
-rw-r--r--compiler/optimizing/optimizing_compiler.cc8
-rw-r--r--dex2oat/linker/oat_writer.cc11
-rw-r--r--runtime/class_linker-inl.h25
-rw-r--r--runtime/class_linker.h4
-rw-r--r--runtime/entrypoints/entrypoint_utils-inl.h34
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc7
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);
}
}