Skip to content

[bgen] Share native-object block invocation code. Fixes #6792 - #27178

Open
rolfbjarne wants to merge 1 commit into
mainfrom
dev/rolf/trampoline-code-reuse
Open

rolfbjarne wants to merge 1 commit into
mainfrom
dev/rolf/trampoline-code-reuse

Conversation

@rolfbjarne

Copy link
Copy Markdown
Member

Generate a common INativeObject-based invoker for void block delegates with a single native-object reference parameter. Keep delegate-specific factories, native-to-managed bridges, and UserDelegateType metadata, while sharing the invocation method, native invoker delegate, and invoker field. Preserve null-to-zero conversion, GC.KeepAlive, and block ownership through TrampolineBlockBase.

Apply the same optimization to compatible rgen callbacks. Keep non-nullable rgen parameters specialized so their argument validation and parameter names remain unchanged, and give the rgen helper distinct names for assemblies using both generators.

Add generator regressions covering NSObject, native-object and protocol callbacks, nested delegate discovery, unchanged specialized signatures, and compilation of the emitted shared invokers. This reduces the duplication described in #6792 without introducing public API.

For the iOS and macOS builds measured before rebasing, 312 iOS and 167 macOS invokers share one invocation implementation per generator. The managed assembly sizes decreased by 48,640 bytes and 25,600 bytes, respectively; these are not measurements of linked or AOT-compiled application sizes.

🤖 Pull request created by Copilot

Fixes #6792

Generate a common INativeObject-based invoker for void block delegates with a single native-object reference parameter. Keep delegate-specific factories, native-to-managed bridges, and UserDelegateType metadata, while sharing the invocation method, native invoker delegate, and invoker field. Preserve null-to-zero conversion, GC.KeepAlive, and block ownership through TrampolineBlockBase.

Apply the same optimization to compatible rgen callbacks. Keep non-nullable rgen parameters specialized so their argument validation and parameter names remain unchanged, and give the rgen helper distinct names for assemblies using both generators.

Add generator regressions covering NSObject, native-object and protocol callbacks, nested delegate discovery, unchanged specialized signatures, and compilation of the emitted shared invokers. This reduces the duplication described in #6792 without introducing public API.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 207a8109-973e-4c0e-9413-e5849518dba7
Copilot AI balanced review requested due to automatic review settings October 29, 2026 20:23
@rolfbjarne
rolfbjarne requested a review from dalexsoto as a code owner October 29, 2026 20:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Sharing void callbacks with a single model-typed parameter bypasses GenerateArgumentChecks, suppressing the existing BI1106 warning for invalid parameter types.

1 open issue
What changed in this PR

Reduces generated block-invocation duplication in bgen and rgen, addressing #6792 by sharing compatible native-object invokers while retaining delegate-specific bridges and factories.

Changes:

  • Shares invocation code, native delegates, and invoker fields for compatible callbacks.
  • Keeps non-nullable rgen callbacks specialized and uses distinct helper names for each generator.
  • Adds regression tests for shared and specialized signatures, nested callbacks, metadata, and emitted-code compilation.
File Description
tests/​rgen/​Microsoft.Macios.Generator.Tests/​Emitters/​TrampolineEmitterTests.cs Tests rgen sharing eligibility and generated helper compilation.
tests/​bgen/​tests/​shared-native-object-trampolines.cs Adds callback fixtures covering shared, specialized, and nested cases.
tests/​bgen/​BGenTests.cs Verifies shared invocation, lifetime handling, factories, and metadata.
src/​rgen/​Microsoft.Macios.Generator/​Emitters/​TrampolineEmitter.cs Emits a shared invoker for compatible nullable native-object callbacks.
src/​bgen/​Generator.cs Emits a shared native-object invoker and reuses it across compatible callbacks.

Review effort: Balanced

Comment thread src/bgen/Generator.cs
Comment on lines +1615 to +1616
return !type.IsByRef && !type.IsValueType && !HasBindAsAttribute (parameter) &&
(TypeManager.IsWrappedType (type) || TypeCache.INativeObject.IsAssignableFrom (type));
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 82e8cd8b8c3e49064b7738dbe70d568c39225136 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🔥 [CI Build #82e8cd8] Test results 🔥

Test results

❌ Tests failed on VSTS: test results

2 tests crashed, 3 tests failed, 207 tests passed.

Failures

❌ dotnettests tests (macOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.AppSizeTest.CoreCLR_Interpreter(MacOSX,"osx-arm64;...: App size changed significantly (-27,501 bytes (-26.9 KB = -0.0 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). ...
    • Xamarin.Tests.AppSizeTest.CoreCLR_R2R(MacOSX,"osx-arm64;osx-x64"...: App size changed significantly (-63,341 bytes (-61.9 KB = -0.1 MB) different > tolerance of +-10,240 bytes (10.0 KB = 0.0 MB)). ...

Html Report (VSDrops) Download

❌ fsharp tests

🔥 Failed catastrophically on VSTS: test results - fsharp (no summary found).

Html Report (VSDrops) Download

❌ windows tests

🔥 Failed catastrophically on VSTS: test results - windows (no summary found).

Html Report (VSDrops) Download

❌ Tests on macOS Sonoma (14) tests

1 tests failed, 4 tests passed.

Failed tests

  • macOS/osx-x64 monotouch-test: Failed (exit code 137)
    • No test failure details available. Output tail:
      • MonoTouchFixtures.Compression.ThoroughCompressionStreamTest : 10.0896 ms
      • MonoTouchFixtures.Compression : 72.7243 ms
      • MonoTouchFixtures.ConfigTest
      • [PASS] Existence
      • MonoTouchFixtures.ConfigTest : 1.4846 ms
      • MonoTouchFixtures.Contacts
      • MonoTouchFixtures.Contacts.ContactFetchRequestTest
      • Contacts permission denied (error: Access Denied)
      • Execution timed out after 600 seconds.
      • Execution completed with exit code 137
  • MacCatalyst/maccatalyst-x64 monotouch-test: Failed (exit code 137)
    • No test failure details available. Output tail:
      • at MonoTouch.NUnit.UI.BaseTouchRunner.Run(NUnit.Framework.Internal.Test)
      • at MonoTouch.NUnit.UI.BaseTouchRunner.Run()
      • at MonoTouch.NUnit.UI.BaseTouchRunner.<AutoRun>b__49_0()
      • at MonoTouch.NUnit.UI.TouchRunner+<>c__DisplayClass19_0.<ExecuteOnMainThread>b__0()
      • at Foundation.NSAsyncActionDispatcher.Apply()
      • at __Registrar_Callbacks__.callback_3037_Foundation_NSAsyncActionDispatcher_Apply(IntPtr, IntPtr, IntPtr*)
      • at UIKit.UIApplication.UIApplicationMain(Int32, System.String[], IntPtr, IntPtr)
      • at UIKit.UIApplication.Main(System.String[], System.Type, System.Type)
      • at MainClass.Main(System.String[])
      • Execution completed with exit code 137

Html Report (VSDrops) Download

❌ Tests on macOS Sequoia (15) tests

1 tests failed, 4 tests passed.

Failed tests

  • MacCatalyst/maccatalyst-x64 monotouch-test: Failed (exit code 137)
    • No test failure details available. Output tail:
      • at MonoTouch.NUnit.UI.BaseTouchRunner.Run(NUnit.Framework.Internal.Test)
      • at MonoTouch.NUnit.UI.BaseTouchRunner.Run()
      • at MonoTouch.NUnit.UI.BaseTouchRunner.<AutoRun>b__49_0()
      • at MonoTouch.NUnit.UI.TouchRunner+<>c__DisplayClass19_0.<ExecuteOnMainThread>b__0()
      • at Foundation.NSAsyncActionDispatcher.Apply()
      • at __Registrar_Callbacks__.callback_3037_Foundation_NSAsyncActionDispatcher_Apply(IntPtr, IntPtr, IntPtr*)
      • at UIKit.UIApplication.UIApplicationMain(Int32, System.String[], IntPtr, IntPtr)
      • at UIKit.UIApplication.Main(System.String[], System.Type, System.Type)
      • at MainClass.Main(System.String[])
      • Execution completed with exit code 137
  • MacCatalyst/maccatalyst-arm64 monotouch-test: Failed (exit code 137)
    • No test failure details available. Output tail:
      • at MonoTouch.NUnit.UI.BaseTouchRunner.Run(NUnit.Framework.Internal.Test)
      • at MonoTouch.NUnit.UI.BaseTouchRunner.Run()
      • at MonoTouch.NUnit.UI.BaseTouchRunner.<AutoRun>b__49_0()
      • at MonoTouch.NUnit.UI.TouchRunner+<>c__DisplayClass19_0.<ExecuteOnMainThread>b__0()
      • at Foundation.NSAsyncActionDispatcher.Apply()
      • at __Registrar_Callbacks__.callback_3037_Foundation_NSAsyncActionDispatcher_Apply(IntPtr, IntPtr, IntPtr*)
      • at UIKit.UIApplication.UIApplicationMain(Int32, System.String[], IntPtr, IntPtr)
      • at UIKit.UIApplication.Main(System.String[], System.Type, System.Type)
      • at MainClass.Main(System.String[])
      • Execution completed with exit code 137

Html Report (VSDrops) Download

Successes

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ generator: All 1 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 4 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 21 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 20 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 20 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 20 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 20 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Golden Gate (27): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

✅ Linux build succeeded

Pipeline on Agent
Hash: 82e8cd8b8c3e49064b7738dbe70d568c39225136 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

⚠️ AppSizeTest expected files changed ⚠️

The AppSizeTest detected changes in the expected app size files.

To update the expected files, add a comment with the following command:

/apply-gist https://gist.github.com/vs-mobiletools-engineering-service2/6d0249fce2224722a8102168365b66b7
Updated files
  • MacOSX-CoreCLR-Interpreter-size.txt
  • MacOSX-CoreCLR-R2R-size.txt

Pipeline on Agent
Hash: 82e8cd8b8c3e49064b7738dbe70d568c39225136 [PR build]

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generalize trampoline code to allow reuse and reduce code size

3 participants