summaryrefslogtreecommitdiff
path: root/compiler/optimizing/instruction_builder.cc
diff options
context:
space:
mode:
author Almaz Mingaleev <mingaleev@google.com> 2024-12-09 15:49:25 +0000
committer Almaz Mingaleev <mingaleev@google.com> 2025-01-06 12:20:05 +0000
commitbdf31e2ff958067b228009d5166e23baab96bd99 (patch)
treee45c30c9bde53c6aeafd3e7a778ab72a61443e3f /compiler/optimizing/instruction_builder.cc
parent26040bb0286ca351158c675dcedd32bc85dd6dd1 (diff)
Handle invoke-virtual targeting invokeExact gracefully.
The interpreter handles such invoke-virtual as if they are native method and executes MethodHandle_invokeExact, which throws UOE. Bug: 383057088 Test: ./art/test/testrunner/testrunner.py --host --64 -b --optimizing Test: ./art/test/testrunner/testrunner.py --host --64 -b --interpreter Change-Id: I4dd4dea46eddd2b26e5866c80548b530a603d9c9
Diffstat (limited to 'compiler/optimizing/instruction_builder.cc')
-rw-r--r--compiler/optimizing/instruction_builder.cc42
1 files changed, 39 insertions, 3 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 8226987968..ba426b5694 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -32,6 +32,7 @@
#include "handle_cache-inl.h"
#include "imtable-inl.h"
#include "intrinsics.h"
+#include "intrinsics_enum.h"
#include "intrinsics_utils.h"
#include "jit/jit.h"
#include "jit/profiling_info.h"
@@ -1051,6 +1052,23 @@ static ArtMethod* ResolveMethod(uint16_t method_idx,
return resolved_method;
}
+static bool IsSignaturePolymorphic(ArtMethod* method) {
+ if (!method->IsIntrinsic()) {
+ return false;
+ }
+ Intrinsics intrinsic = method->GetIntrinsic();
+
+ switch (intrinsic) {
+#define IS_POLYMOPHIC(Name, ...) \
+ case Intrinsics::k ## Name:
+ ART_SIGNATURE_POLYMORPHIC_INTRINSICS_LIST(IS_POLYMOPHIC)
+#undef IS_POLYMOPHIC
+ return true;
+ default:
+ return false;
+ }
+}
+
bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
uint32_t dex_pc,
uint32_t method_idx,
@@ -1078,10 +1096,28 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
&is_string_constructor);
MethodReference method_reference(&graph_->GetDexFile(), method_idx);
- if (UNLIKELY(resolved_method == nullptr)) {
+
+ // In the wild there are apps which have invoke-virtual targeting signature polymorphic methods
+ // like MethodHandle.invokeExact. It never worked in the first place: such calls were dispatched
+ // to the JNI implementation, which throws UOE.
+ // Now, when a signature-polymorphic method is implemented as an intrinsic, compiler's attempt to
+ // devirtualize such ill-formed virtual calls can lead to compiler crashes as an intrinsic
+ // (like MethodHandle.invokeExact) might expect arguments to be set up in a different manner than
+ // it's done for virtual calls.
+ // Create HInvokeUnresolved to make sure that such invoke-virtual calls are not devirtualized
+ // and are treated as native method calls.
+ if (kIsDebugBuild && resolved_method != nullptr) {
+ ScopedObjectAccess soa(Thread::Current());
+ CHECK_EQ(IsSignaturePolymorphic(resolved_method), resolved_method->IsSignaturePolymorphic());
+ }
+
+ if (UNLIKELY(resolved_method == nullptr ||
+ (invoke_type != kPolymorphic && IsSignaturePolymorphic(resolved_method)))) {
DCHECK(!Thread::Current()->IsExceptionPending());
- MaybeRecordStat(compilation_stats_,
- MethodCompilationStat::kUnresolvedMethod);
+ if (resolved_method == nullptr) {
+ MaybeRecordStat(compilation_stats_,
+ MethodCompilationStat::kUnresolvedMethod);
+ }
HInvoke* invoke = new (allocator_) HInvokeUnresolved(allocator_,
number_of_arguments,
operands.GetNumberOfOperands(),