Skip to content

Remove obsolete native managed-invocation machinery - #133660

Merged
jkoritzinsky merged 3 commits into
dev/jkoritzinsky/func-eval-ucofrom
dev/jkoritzinsky/invocation-cleanup
Nov 3, 2026
Merged

jkoritzinsky merged 3 commits into
dev/jkoritzinsky/func-eval-ucofrom
dev/jkoritzinsky/invocation-cleanup

Conversation

@jkoritzinsky

@jkoritzinsky jkoritzinsky commented Sep 11, 2026 •

Copy link
Copy Markdown
Member

Summary

Layer 4 of the stack for #123864, following #133659. Remove the native machinery whose final callers disappeared in the preceding reflection, custom-attribute, and func-eval layers.

  • Delete MethodDescCallSite, CallDescrData, CallDescrWorker, DispatchCallSimple, and their argument/return-value copying closure.
  • Remove the dedicated per-architecture workers, integrated x86/ARM assembly blocks, build entries, offsets, and return-address identification.
  • Remove unreachable EH branches and simplify the affected prestub/VSD/interpreter dispatcher paths without changing the surviving native-rethrow behavior.
  • Remove orphaned multicore-JIT diagnostic state and its now-unused holder; avoid computing a dead return address/PAC strip in Release builds.
  • Update VM-to-managed calling documentation to describe typed UCO entrypoints.

Retained: live InvokeUtil field/pointer/conversion/exception helpers, UnmanagedCallersOnlyCaller, default-constructor dispatch, ArgDestination GC reporting, profiler/calling-convention logic, and debugger raw-result storage. Historical stack traces are left intact.

The layer removes about 2,900 net lines across 49 files.

Validation

  • Windows x64 and x86 Checked native builds succeeded. The x86 binary was verified as I386 and executed with an architecture-matched CoreLib.
  • The initial cleanup passed 5,956 x64 reflection/emit/extensions/invocation cases. After the final dead-state/guard refinements, both x64 and x86 forced invocation suites passed 631 + 631 cases, and both multicore-JIT profile tests passed.
  • Independent native review covered EH/SEH, GC/DAC reporting, live helpers, and assembly/build wiring; identified cleanup advisories were addressed.
  • The unchanged MDbg frozen20 ran once against the final snapshot: 18 passed, 0 failed, 2 existing skips, with all exact outcomes and abort/nullable recovery markers preserved. Six binary hashes and actual loaded modules matched the supplied runtime.

The tested binaries were built from the identical final working tree before the cleanup commit, so their embedded native version identifies the parent commit. Actual Linux, ARM/ARM64, and WebAssembly runtime execution was not performed.


Stack created with GitHub Stacks CLI • Give Feedback 💬

Note

This PR description and cleanup were prepared with GitHub Copilot.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@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.

@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from 6ecc72a to ae37eaf Compare September 13, 2026 04:17
@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from ae37eaf to f34fdbb Compare September 13, 2026 15:15
@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from f34fdbb to cdf3559 Compare September 15, 2026 00:28
@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from cdf3559 to 3e2eea9 Compare September 15, 2026 21:55
@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from 3e2eea9 to 1f30315 Compare September 15, 2026 22:57
@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from 1f30315 to 52121f1 Compare September 16, 2026 22:59
@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from 52121f1 to 5dcd19e Compare September 18, 2026 20:06
@jkoritzinsky

Copy link
Copy Markdown
Member Author

/ba-g build analysis doesn't go green on PRs to non-main even though that's how stacked PRs work.

@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from 6d38cde to f0faf14 Compare November 2, 2026 23:40
@jkoritzinsky
jkoritzinsky enabled stacked auto-merge (squash) November 2, 2026 23:40
@jkoritzinsky
jkoritzinsky requested a review from janvorli November 2, 2026 23:41
@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from f0faf14 to c608dd1 Compare November 3, 2026 03:28
jkoritzinsky and others added 3 commits November 2, 2026 21:30
Delete MethodDescCallSite, CallDescrWorker and their argument-copying, return-value, architecture assembly, build, and EH identification closure after the reflection, custom-attribute, and func-eval migrations. Remove orphaned multicore-JIT diagnostic state and update VM-to-managed calling documentation. Preserve live field-access helpers, typed UCO calls, GC argument reporting, and calling-convention traits.

Co-authored-by: Copilot App <[email protected]>
@jkoritzinsky
jkoritzinsky force-pushed the dev/jkoritzinsky/invocation-cleanup branch from c608dd1 to b11c205 Compare November 3, 2026 05:31
@jkoritzinsky
jkoritzinsky requested a review from jkotas November 3, 2026 05:34
@jkoritzinsky

Copy link
Copy Markdown
Member Author

/ba-g wbt xml failure unrelated

@jkoritzinsky
jkoritzinsky disabled stacked auto-merge November 3, 2026 16:35
@jkoritzinsky
jkoritzinsky merged commit 73337a4 into main Nov 3, 2026
121 of 123 checks passed
@jkoritzinsky
jkoritzinsky deleted the dev/jkoritzinsky/invocation-cleanup branch November 3, 2026 16:35
@github-project-automation github-project-automation Bot moved this to Done in AppModel Nov 3, 2026
jkoritzinsky added a commit that referenced this pull request Nov 3, 2026
## Summary

Layer 3 of the stack for #123864, following #133658. The prior
func-eval-specific proposal is #126809.

This layer started as replacing the final native managed-call dispatch
with a managed UnmanagedCallersOnly entrypoint. It now moves most
debugger function-evaluation preparation, invocation, storage, and
copy-back into managed CoreLib while retaining the debugger-specific
control flow and GC-safe bootstrap in native code.

### Managed invocation and storage

- Add `Debugger.FunctionEvaluation`, a runtime-owned UCO entrypoint that
resolves the exact target method from its declaring `RuntimeType` and
rooted `IRuntimeMethodInfo`.
- Extend the shared reflection invocation emitter with debugger-specific
thunks that prepare arguments, invoke methods and constructors, copy
back writable arguments, and publish results.
- Emit `newobj` for debugger object construction instead of
preallocating an object and calling its constructor as an ordinary
method. Existing-object constructor calls remain supported, and
abstract/interface allocation is rejected.
- Keep the entire managed call-address vector registered through
`GCFrameRegistration`, using exact typed locals for memory-backed
by-value ref structs so their managed byrefs are reported by normal JIT
GC info.
- Handle object, primitive, enum, pointer, value-type, nullable,
literal, memory, register, and byref argument representations in managed
code while preserving native-endian storage and debugger copy-back
semantics.
- Align nullable behavior with the existing debugger contract: direct
value-type memory homes are mutated in place, while debugger handles are
not treated as writable nullable homes. Exact register-backed nullable
temporaries are boxed only after their MethodTable is instance-active.
- Move ordinary value-type result storage into temporary GC-described
external memory and defer boxing until after invocation and argument
copy-back. Keep byref-like results in persistent external storage and
raw byref results rooted directly in the debugger result slot.
- Create result handles in managed code only after the result is fully
prepared, and preserve object identity and updated field contents across
collections and later debugger inspection.

### Native debugger and GC integration

- Retain native method/signature validation, generic resolution, class
initialization, receiver validation inputs, register/home capture, abort
state, exception publication, completion, and result ownership.
- Capture contiguous register value-type snapshots before the first
GC-triggering managed transition and describe them with their exact type
layout.
- Root non-leaf register references and register value-type snapshots
with `ExternalMemoryHandle` registrations so collections during managed
preparation relocate their contents correctly.
- Represent external memory with a full tagged `TypeHandle`, allowing
the runtime and cDAC to distinguish inline value types, object-reference
slots, managed-byref slots, and unmanaged pointer/function-pointer
locals.
- Report each external-memory type's loader allocator during GC
scanning, keeping collectible layouts alive while external storage is
registered.
- Add dedicated GC-safe object-register copy-back and native-endian
scalar register copy-back paths.
- Remove stale native argument copies and architecture-specific packing
layers that are no longer needed, while preserving the
architecture-specific register-home logic required by debugger IPC.
- Treat the debugger UCO entrypoint as a runtime-internal reverse
transition for exception handling, and exclude its debugger-only
MethodDesc state on WebAssembly targets that do not build `debug/ee`.
- Update the cDAC ExternalMemoryHandles reader, descriptors, tests, and
authoritative contract documentation for the exact managed-local
representation.

### Correctness fixes included

- Avoid double relocation of overlapping byrefs in by-value ref structs
(#135245).
- Keep raw byref results rooted until deferred debugger completion
(#135247).
- Prevent stale non-leaf register values after a compacting GC
(#135249).
- Preserve current external-result fields across collections and later
inspection (#135251).
- Keep collectible loader allocators alive while external-memory layouts
are scanned (#135252).

## Validation

Validation used the existing internal MDbg/xUnit debugger-test harness
with a private CoreRun and ProjectK/CoreCLR-only configuration:

- Targeted nested-byref invariant under target-only `GCStress=0x3`:
**1/1 passed**.
- Revised normal matrix: **35/35 passed**.
- Targeted stress matrix: **4/4 passed**.
- Windows x64 and x86 Checked native, CoreLib, and ReadyToRun builds
completed with zero warnings and errors.
- cDAC unit tests and generated usage/documentation checks passed for
the ExternalMemoryHandle descriptor changes.

Coverage includes moving GC, overlapping and nested byrefs, memory and
register homes, non-leaf registers, receiver mutation, constructors,
primitive/native-endian copy-back, nullable memory homes,
byref/byref-like/value-type results, collectible generics and layouts,
nested and exception-time eval, safe/rude/exception-unwind aborts, and
post-eval inspection. Runtime hashes and loaded modules were audited;
each abort scenario completed the callback, successfully evaluated
`Echo(42)`, detached, and exited MDbg with code 100. Test configurations
were restored and no debugger/test processes survived the runs.

These results were recorded on the validated pre-refresh candidate. The
final stack rebase preserved the layer's net diff; builds and tests were
not repeated after the history rewrite at the user's request.

The final native invocation cleanup layer is #133660.

---

<sub>Stack created with <a
href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a
href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

Resolves #135245
Resolves #135247
Resolves #135249
Resolves #135251
Resolves #135252

> [!NOTE]
> This PR description and implementation were prepared with GitHub
Copilot. Commits that reuse am11's code retain the requested co-author
attribution.

---------

Co-authored-by: Adeel Mujahid <[email protected]>
Co-authored-by: Copilot App <[email protected]>
@filipnavara

Copy link
Copy Markdown
Member

Amazing work, thanks a lot!

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

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants