Enable R2R precompilation of objc_msgSend P/Invoke stubs#124770
Draft
davidnguyen-tech wants to merge 6 commits intodotnet:mainfrom
Draft
Enable R2R precompilation of objc_msgSend P/Invoke stubs#124770davidnguyen-tech wants to merge 6 commits intodotnet:mainfrom
davidnguyen-tech wants to merge 6 commits intodotnet:mainfrom
Conversation
The R2R PInvokeILEmitter previously threw NotSupportedException for any P/Invoke requiring an ObjC pending exception check (objc_msgSend family), forcing runtime IL stub generation. On JIT-less platforms like iOS with CoreCLR, these stubs fall back to the interpreter. This change teaches the R2R emitter to emit a call to ObjectiveCMarshal.ThrowPendingExceptionObject() after the native call, mirroring the common/NativeAOT PInvokeILEmitter. For blittable ObjC P/Invokes, the entire stub is now precompiled into the R2R image. The ThrowPendingExceptionObject method was previously only available in NativeAOT's System.Private.CoreLib. This change adds it to CoreCLR's ObjectiveCMarshal.CoreCLR.cs as well, delegating to the existing StubHelpers.GetPendingExceptionObject() infrastructure. Changes: - ObjectiveCMarshal.CoreCLR.cs: Add ThrowPendingExceptionObject() - PInvokeILEmitter.cs: Remove NotSupportedException for ObjC; emit ThrowPendingExceptionObject call after the native call - Marshaller.ReadyToRun.cs: Add IsObjCMessageSendPInvoke helper - GeneratesPInvoke: Return true for ObjC P/Invokes - CreateValueFromKey: Catch RequiresRuntimeJitException for ObjC P/Invokes with non-blittable params - CorInfoImpl: Remove assert that assumed GeneratesPInvoke is false when stubIL is null Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove Marshaller.IsObjCMessageSendPInvoke wrapper, call MarshalHelpers.ShouldCheckForPendingException directly in GeneratesPInvoke - Clarify GeneratesPInvoke comment: IsMarshallingRequired returns true for ObjC P/Invokes because they need an IL stub, not actual type marshalling - Add comment to empty catch block explaining JIT fallback behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… ILCompiler directly now.
Contributor
There was a problem hiding this comment.
Pull request overview
Enables ReadyToRun (R2R) precompilation of Objective-C objc_msgSend-family P/Invoke stubs by emitting a managed pending-exception check after the native call, avoiding a runtime-stub/interpreter fallback on JIT-less Apple platforms.
Changes:
- Add
ObjectiveCMarshal.ThrowPendingExceptionObject()in CoreCLR and expose it to the runtime binder. - Update the R2R
PInvokeILEmitterto emit a post-call pending-exception check instead of rejecting ObjC P/Invokes. - Adjust R2R compilation policy and IL caching behavior to allow ObjC P/Invokes to be attempted and to gracefully fall back when unsupported.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/vm/corelib.h | Adds CoreLib binder entry for ObjectiveCMarshal.ThrowPendingExceptionObject. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs | Simplifies P/Invoke stub IL retrieval logic now that unsupported cases are handled/cached in ILCache. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/Stubs/PInvokeILEmitter.cs | Emits ThrowPendingExceptionObject after ObjC native calls; removes ObjC-specific NotSupportedException. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs | Allows GeneratesPInvoke for ObjC msgSend P/Invokes even when marshalling is otherwise considered required. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs | Caches “requires runtime JIT” decisions for unsupported P/Invoke stub emission via RequiresRuntimeJitException catch. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs | Implements ThrowPendingExceptionObject() using pending-exception storage and ExceptionDispatchInfo.Throw. |
Contributor
|
Tagging subscribers to 'os-ios': @vitek-karas, @kotlarmilos, @steveisok, @akoeplinger |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
TODO: Add measurements on a sample app
The R2R PInvokeILEmitter previously threw
NotSupportedExceptionfor any P/Invoke requiring an ObjC pending exception check (objc_msgSendcalls), forcing runtime IL stub generation every time.On JIT-less platforms like iOS with CoreCLR, these stubs fall back to the interpreter, with unnecessary performance costs.
Solution
Change R2R P/Invoke IL Emitter to emit a call to
ObjectiveCMarshal.ThrowPendingExceptionObject()after the native call, mirroring the NativeAOT PInvokeILEmitter:runtime/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
Lines 349 to 353 in 66f3596
For blittable ObjC P/Invokes, the entire stub is now precompiled into the R2R image.