diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs index 101978434bd612..bb27891a8c6627 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs @@ -1,7 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.ExceptionServices; using System.Runtime.Versioning; namespace System.Runtime.InteropServices.ObjectiveC @@ -39,6 +41,16 @@ private static partial IntPtr CreateReferenceTrackingHandleInternal( out int memInSizeT, out IntPtr mem); + [StackTraceHidden] + internal static void ThrowPendingExceptionObject() + { + Exception? ex = System.StubHelpers.StubHelpers.GetPendingExceptionObject(); + if (ex is not null) + { + ExceptionDispatchInfo.Throw(ex); + } + } + [UnmanagedCallersOnly] internal static unsafe void* InvokeUnhandledExceptionPropagation(Exception* pExceptionArg, IntPtr methodDesc, IntPtr* pContext, Exception* pException) { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 547458296fd024..1630c59b451f13 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -22,6 +22,7 @@ using ILCompiler.ReadyToRun; using ILCompiler.Reflection.ReadyToRun; using Internal.TypeSystem.Ecma; +using Internal.TypeSystem.Interop; using ILCompiler.ReadyToRun.TypeSystem; namespace ILCompiler @@ -701,6 +702,7 @@ public void PrepareForCompilationRetry(MethodWithGCInfo methodToBeRecompiled, IE private ManualResetEventSlim _compilationSessionComplete = new ManualResetEventSlim(); private bool _hasCreatedCompilationThreads = false; private bool _hasAddedAsyncReferences = false; + private bool _hasAddedObjectiveCMarshalReferences = false; protected override void ComputeDependencyNodeDependencies(List> obj) { @@ -737,6 +739,9 @@ protected override void ComputeDependencyNodeDependencies(List l.Contains("objc_msgSend") && l.Contains("MethodWithGCInfo")) + .ToArray(); + + string[] expectedStubs = new[] + { + "__objc_msgSend ", + "__objc_msgSend_2 ", + "__objc_msgSend_stret ", + }; + + bool allFound = true; + foreach (string expected in expectedStubs) + { + bool found = compiledStubs.Any(l => l.Contains(expected)); + Console.WriteLine($" {(found ? "OK" : "MISSING")}: {expected.Trim()}"); + if (!found) + allFound = false; + } + + if (!allFound) + Console.WriteLine("FAILED: Not all objc_msgSend P/Invoke stubs were precompiled into the R2R image."); + + return allFound; + } + + private static bool ValidatePendingExceptionPropagates() + { + IntPtr callback = (IntPtr)(delegate* unmanaged)&MsgSendCallback; + ObjectiveCMarshal.SetMessageSendCallback(MessageSendFunction.MsgSend, callback); + + try + { + objc_msgSend(IntPtr.Zero, IntPtr.Zero); + } + catch (PendingException ex) when (ex.Message == nameof(MsgSendCallback)) + { + return true; + } + catch (Exception ex) + { + Console.WriteLine($"FAILED: unexpected exception from objc_msgSend: {ex.GetType()} - {ex.Message}"); + return false; + } + + Console.WriteLine("FAILED: objc_msgSend returned without throwing the pending exception."); + return false; + } +} diff --git a/src/tests/readytorun/ObjCPInvokeR2R/ObjCPInvokeR2R.csproj b/src/tests/readytorun/ObjCPInvokeR2R/ObjCPInvokeR2R.csproj new file mode 100644 index 00000000000000..1c44495107978a --- /dev/null +++ b/src/tests/readytorun/ObjCPInvokeR2R/ObjCPInvokeR2R.csproj @@ -0,0 +1,62 @@ + + + true + false + false + + true + + true + + true + + + + + + + + + + + +