-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Generate calls to interface methods through resolve helper #112406
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas |
/azp run runtime-nativeaot-outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
This reverts commit 7f879d6.
For this not to be a throughput regression, we need to figure out a clean way to implement the hack in last two commits. I ran JSON serialization with/without this PR. Having to preserve argument registers before calling the resolve helper costs us about 1% in throughput. PR-hack is the hack where we allow RyuJIT to assume argument registers are not clobbered. We better not take a GC in the slow path.
Do we have a way to do this hack cleanly that doesn't involve building a new universal transition? |
/azp run runtime-nativeaot-outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run runtime-nativeaot-outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
342fb19
to
b370b17
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot reviewed 3 out of 22 changed files in this pull request and generated no comments.
Files not reviewed (19)
- src/coreclr/inc/corinfo.h: Language not supported
- src/coreclr/inc/jiteeversionguid.h: Language not supported
- src/coreclr/inc/jithelpers.h: Language not supported
- src/coreclr/jit/codegencommon.cpp: Language not supported
- src/coreclr/jit/gentree.cpp: Language not supported
- src/coreclr/jit/gentree.h: Language not supported
- src/coreclr/jit/lower.cpp: Language not supported
- src/coreclr/jit/morph.cpp: Language not supported
- src/coreclr/jit/targetamd64.h: Language not supported
- src/coreclr/jit/targetarm64.h: Language not supported
- src/coreclr/nativeaot/Runtime/AsmOffsets.h: Language not supported
- src/coreclr/nativeaot/Runtime/CMakeLists.txt: Language not supported
- src/coreclr/nativeaot/Runtime/EHHelpers.cpp: Language not supported
- src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp: Language not supported
- src/coreclr/nativeaot/Runtime/amd64/DispatchResolve.asm: Language not supported
- src/coreclr/nativeaot/Runtime/amd64/UniversalTransition.asm: Language not supported
- src/coreclr/nativeaot/Runtime/arm64/DispatchResolve.asm: Language not supported
- src/coreclr/nativeaot/Runtime/arm64/UniversalTransition.asm: Language not supported
- src/coreclr/nativeaot/Runtime/inc/rhbinder.h: Language not supported
Comments suppressed due to low confidence (1)
src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs:267
- Ensure that the new helper CORINFO_HELP_INTERFACELOOKUP_FOR_SLOT is covered by tests to verify its behavior.
CORINFO_HELP_INTERFACELOOKUP_FOR_SLOT, // Resolve a non-generic interface method from this pointer and dispatch cell
@dotnet/ilc-contrib this is ready for review @jakobbotsch who would be the best to review the JIT side? |
/azp run jit-cfg |
Azure Pipelines successfully started running 1 pipeline(s). |
There's some more JIT work needed to properly report non callee saves after a call. I opened #113071 for it. |
The runtime knows how to do it for the existing VSD helper that tailcalls, so it should be able to do it for helper that returns as well. The new helper uses the same GC reporting setup as the existing VSD helper that tailcalls. In order for this to work, the JIT has to setup all arguments before calling the new helper. It does not seem to be happening in all cases. For example, I see the following codegen for a call from
|
That's expected with how this is implemented in the JIT. The JIT just considers this helper to not trash the argument registers. It is free to leave any GC ref in those registers across the call. It is not considering the "resolve + dispatch" sequence as one unit that takes the arguments of the final call. (I am not sure if this would be feasible on arm64 that uses "resolve + validate + call" sequence). |
Yes, I have pushed a commit to do that (some of the changes in that commit are quick hack that needs cleaning up if it works). |
Track all integer registers for calls in `regPtrDsc`. This does not cost any extra memory and it saves us from going back and forth between an intermediate format. It also unblocks proper GC reporting for helper calls that are GC reported with non-standard calling convention.
/azp run jit-cfg |
Azure Pipelines successfully started running 1 pipeline(s). |
@dotnet/samsung Could you please take a look? These changes may be related to riscv64. |
1 similar comment
@dotnet/samsung Could you please take a look? These changes may be related to riscv64. |
Should we just take a simpler but more obviously correct fix here instead of trying to make the calling convention change work? It does not appear to be that simple. I still wonder if it wouldn't be simpler/less risk to change the cached interface dispatch stubs to emit the call through the CFG dispatcher directly and avoid the more substantial changes in how the scheme works. |
Would that help? Right now the interface call sequence is:
The call is indirected within the codegen so doing this in the stub that DispatchCellInMutableMemory points to would be too late because we already made a unverified call. |
Really? That would surprise me. JIT should make sure this goes through CFG. That should definitely be fixed. |
Ah, yeah, this goes through a CFG check. But your suggestion is to go through two CFG checks for a single interface call? |
Yes, it would end up going through two CFG checks. I don't know how bad the impact on performance would be. |
I can have a look at that next week. However, it looks like the resolve helper method would actually be a perf improvement from where we're now, so it's a bit more attractive (#112406 (comment)). |
I agree that resolve helper with different calling convention is likely the best way to do the dispatch when CFG is enabled, but at this point in the release cycle and based on the kind of issues we saw trying to make that work it seems like a lot of risk to me. Maybe the resolve helper with standard calling convention will turn out to be better than double CFG approach. That should be less risky (but not quite as low risk as changing the CID stubs). |
This change looks risky to me for .NET 10 at this point regardless of the implementation strategy. |
Could you please resolve the conflicts and get this build again so that we can start iterating on it? (It can wait after .NET 10 snap.) |
@dotnet/samsung Could you please take a look? These changes may be related to riscv64. |
This changes interface calls when CFG is enabled to use a resolve helper instead of the stub dispatcher. I've also extended the CFG testing a bit to cover more of interface calls in the smoke test.
Before this change:
After this change: