Skip to content

Remove Wrapper delegate kind, switch ARM32 VSD hidden arg to R12, finalize ARM32 VSD worker handoff cleanup, and fix ARM32 ResolveStub slow-entry length/alignment assertions#129403

Draft
Copilot wants to merge 14 commits into
mainfrom
copilot/remove-wrapper-delegate-kind
Draft

Remove Wrapper delegate kind, switch ARM32 VSD hidden arg to R12, finalize ARM32 VSD worker handoff cleanup, and fix ARM32 ResolveStub slow-entry length/alignment assertions#129403
Copilot wants to merge 14 commits into
mainfrom
copilot/remove-wrapper-delegate-kind

Conversation

Copilot AI commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

main PR

Description

CoreCLR’s Wrapper delegate kind was retained only to satisfy an ARM32 VSD ABI quirk (r4 hidden cell). This change removes that special delegate path by moving ARM32 VSD hidden-parameter passing to r12 and deleting wrapper-delegate infrastructure across VM/JIT/AOT/contracts and System.Private.CoreLib.

  • ARM32 VSD calling-convention alignment

    • Updates ARM32 stub-dispatch plumbing to carry IndirectionCellAndFlags in r12.
    • Aligns JIT virtual-stub parameter selection on ARM32 to REG_R12.
    • Applies follow-up ARM32 VSD worker handoff fixes:
      • LookupHolder::Initialize and ResolveStub slow-entry push incoming hidden r12 to the stack and load dispatch token into r12 before branching to the worker.
      • ResolveWorkerAsmStub now uses a fake-prolog/transition-block shape (matching the existing ARM delay-load pattern) so argument registers are preserved correctly while passing the dispatch token and hidden cell/flags to VSD_ResolveWorker.
      • Updates ARM stub length constants to match the instruction sequence changes.
    • Post-feedback correctness fixes:
      • Updates ResolveStub::slowEntryPointLen to match emitted ARM instructions.
      • Adds an additional alignment NOP in ResolveHolder::Initialize slow-entry emission and updates slowEntryPointLen to 8 so the subsequent even-word alignment invariant ((n & 1) == 0) holds.
  • Wrapper delegate infrastructure removal

    • Removes wrapper-delegate creation/detection/runtime paths from COMDelegate.
    • Removes remaining wrapper handling from MulticastDelegate.CoreCLR.cs.
    • Removes wrapper-specific IL stub kind/plumbing and associated metadata fields.
    • Removes wrapper-specific JIT call flags and late-arg handling.
  • Cross-layer contract cleanup

    • Deletes obsolete wrapperDelegateInvoke and offsetOfWrapperDelegateIndirectCell from EE/JIT interfaces and SuperPMI agnostic records.
    • Keeps VM/JIT/AOT call-info structures consistent after field removal.
    • Revs the JIT/EE interface GUID in jiteeversionguid.h to match the interface change.
  • IL stub enum cleanup

    • Deletes the unused wrapper IL stub value and renumbers subsequent IL stub values in VM (method.hpp, dllimport.h) and corresponding cDAC contract mapping.
  • ARM32 ResolveStub correctness fix

    • Fixes ResolveStub::_failEntryPoint to avoid clobbering r12 (which now carries IndirectionCellAndFlags).
    • Uses r4 as decrement scratch for _pCounter update and preserves callee-saved r4 via stack save/restore in the fail path.
  • JIT cleanup after feedback

    • Removes an unused VirtualStubParamInfo constructor argument in src/coreclr/jit/compiler.h.
    • Updates the call site in src/coreclr/jit/compiler.cpp accordingly.
    • Moves GTF_CALL_M_STACK_ARRAY to the removed wrapper-flag slot (0x00004000) so call flag values remain contiguous.
  • Delegate VM cleanup after feedback

    • Removes the temporary refRealDelegate local and associated GCPROTECT_BEGIN/END in COMDelegate::BindToMethod.
    • Replaces uses with (*pRefThis) directly.
    • Deletes the unused _ReturnAddress intrinsic declaration from comdelegate.cpp.
  • R2R compatibility boundary

    • Bumps ReadyToRun major/minimum version to 24 for the ARM32 VSD register contract change.
    • Syncs version constants across native and managed header definitions.
  • Documentation update

    • Updates docs/design/coreclr/botr/clr-abi.md hidden-parameter section: ARM32 VSD hidden parameter is now R12.
// src/coreclr/jit/compiler.h (ARM32)
#elif defined(TARGET_ARM)
    reg     = REG_R12;
    regMask = RBM_R12;

Customer Impact

Without this change, ARM32 virtual stub dispatch can mis-handle hidden argument/token flow in edge paths and wrapper-delegate-specific infrastructure remains in place even though it is no longer needed. This can lead to correctness risk and unnecessary maintenance burden. The slow-entry length/alignment fixes also prevent ARM checked-build assertion failures in ResolveHolder::Initialize.

Regression

No known product regression is being fixed; this is ABI/calling-convention cleanup plus correctness hardening in ARM32 VSD paths. The latest updates fix regressions introduced during this PR’s ARM32 stub reshaping (slow-entry length mismatch and subsequent even-word alignment assertion failure).

Testing

  • Baseline build completed: ./build.sh clr+libs+host
  • Targeted ARM validation completed: ./build.sh clr.runtime -arch arm -c Release
  • Additional ARM build attempt: ./build.sh clr -arch arm -c Release (failed in ILCompiler_publish.csproj due missing libjitinterface_arm.so, unrelated to the ARM32 asm helper change)
  • Follow-up validation for assertion fixes: ./build.sh clr.runtime -arch arm -c Checked (passed)

Risk

Medium. The change touches low-level CoreCLR ARM32 stub assembly and calling-convention plumbing, but is narrowly scoped to VSD worker handoff and aligned with existing fake-prolog transition-block patterns used elsewhere in ARM stubs. The follow-up slow-entry alignment fix is low risk and aligns metadata and padding with already-emitted code.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 15, 2026 04:32
Copilot AI changed the title [WIP] Remove need for the special Wrapper delegate kind Remove Wrapper delegate kind; switch ARM32 VSD hidden arg to R12 Jun 15, 2026
Copilot AI requested a review from jkotas June 15, 2026 04:33
@MichalPetryka

Copy link
Copy Markdown
Contributor

@copilot Remove all wrapper handling code from MulticastDelegate.CoreCLR.cs too.

Comment thread src/coreclr/inc/corinfo.h
Comment thread src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs Outdated
Comment thread src/coreclr/vm/method.hpp Outdated
@MichalPetryka

Copy link
Copy Markdown
Contributor

@copilot Remove all wrapper handling code from MulticastDelegate.CoreCLR.cs too.

@jkotas Can you repost this since only maintainers can interact with copilot?

Comment thread src/coreclr/vm/dllimport.h Outdated
@jkotas

jkotas commented Jun 15, 2026

Copy link
Copy Markdown
Member

@copilot Remove all wrapper handling code from MulticastDelegate.CoreCLR.cs too.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment thread src/coreclr/vm/arm/asmhelpers.S Outdated
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 15, 2026 05:03
Copilot AI removed the request for review from Copilot June 16, 2026 01:25
Copilot AI requested a review from jkotas June 16, 2026 01:26
Comment thread src/coreclr/vm/arm/asmhelpers.S Outdated
Comment thread src/coreclr/vm/arm/asmhelpers.S Outdated

@jkotas jkotas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot apply feedback

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 16, 2026 01:58
Copilot AI requested a review from jkotas June 16, 2026 02:00
Comment thread src/coreclr/vm/comdelegate.cpp
Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 16, 2026 02:27

Copilot AI commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot apply feedback

Applied in 3c6ffef: updated the ARM32 asm helper fake-prolog symbol name per feedback (NESTED_ENTRY/NESTED_END ResolveWorkerAsmStub_FakeProlog).

@jkotas

jkotas commented Jun 16, 2026

Copy link
Copy Markdown
Member

@copilot Tests are failing with

ASSERT FAILED
Expression: n == ResolveStub::slowEntryPointLen
Location: /__w/1/s/src/coreclr/vm/arm/stubs.cpp:852
Function: Initialize
Process: 16

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Copilot AI requested review from Copilot and removed request for Copilot June 16, 2026 05:23

Copilot AI commented Jun 16, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Tests are failing with

ASSERT FAILED
...

Fixed in e628fbd: updated ResolveStub::slowEntryPointLen from 6 to 7 in src/coreclr/vm/arm/virtualcallstubcpu.hpp to match the 7 WORDs emitted in ResolveHolder::Initialize, which resolves the assertion failure at stubs.cpp:852.

Note

AI-generated by Copilot.

Copilot AI changed the title Remove Wrapper delegate kind, switch ARM32 VSD hidden arg to R12, and finalize ARM32 VSD worker handoff cleanup Remove Wrapper delegate kind, switch ARM32 VSD hidden arg to R12, finalize ARM32 VSD worker handoff cleanup, and fix ARM32 ResolveStub slow-entry length assertion Jun 16, 2026
// nop for alignment
_stub._slowEntryPoint[n++] = 0xbf00;

_ASSERTE(n == ResolveStub::slowEntryPointLen);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot slowEntryPointLen is 7, but the assert a few lines below checks that n is even - it is going to fail.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 59fba73a: made ResolveStub slow-entry length even by adding a second alignment nop in ResolveHolder::Initialize and updated ResolveStub::slowEntryPointLen to 8, so the subsequent even-length alignment assert no longer fails.

Comment thread src/coreclr/vm/arm/stubs.cpp Outdated
_stub._slowEntryPoint[n++] = 0xf8df;
_stub._slowEntryPoint[n++] = 0xf000 | offset;

// nop for alignment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot Is this nop really needed?

Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants