Simplify "secret stub arg" handling between JIT and EE#100823
Simplify "secret stub arg" handling between JIT and EE#100823jakobbotsch merged 19 commits intodotnet:mainfrom
Conversation
|
/azp run runtime-coreclr outerloop, runtime-nativeaot-outerloop, runtime-coreclr r2r |
|
Azure Pipelines successfully started running 3 pipeline(s). |
|
cc @dotnet/jit-contrib PTAL @kunalspathak @jkotas (no rush given you're on vacation) In the end I decided not to try to unify x86/arm32 |
jkotas
left a comment
There was a problem hiding this comment.
The EE side of the implementation LGTM
|
Kunal is OOF, but this PR will also break LA64/RISCV64 until they implement #100744 and switch to the new register homing implementation, so I think I will just wait with merging this for now. |
|
/azp run runtime |
|
Azure Pipelines successfully started running 1 pipeline(s). |
When a pinvoke/reverse pinvoke needs marshalling the VM creates an IL stub to perform this marshalling. These IL stubs have a non-standard parameter called the "secret stub parameter". The VM uses this parameter to map the IL stub back to the user defined function that caused the IL stub to be required (multiple user functions can share the same IL stubs, so the mapping cannot be done by other means). To facilitate the access of this value the JIT must make the parameter's value available to the VM somehow. Previously this was done in two separate ways for 32-bit and 64-bit target: - For 32-bit targets the parameter was marked as do-not-enregister and always spilled to the stack frame at a location that was known by the VM. - For 64-bit targets the parameter was saved in the `InlinedCallFrame` as part of a VM helper call. We still marked it as do-not-enregister, probably because parameter homing did not handle it. For 64-bit targets this introduces a bit of inefficiency: the secret stub parameter is only needed for the IL stubs case, but `InlinedCallFrame` is used for all inlined pinvokes. So we ended up with a larger frame than necessary and with an additional store to the frame, even outside IL stubs. This change removes that inefficiency by unifying how 32-bit and 64-bit targets work: - Switch all platforms to only allocate space in `InlinedCallFrame` for the secret stub parameter when necessary - Move responsibility of storing the secret stub parameter out of `CORINFO_HELP_INIT_PINVOKE_FRAME` and to the JIT generated code - Remove special casing of frame layout around the secret stub parameter and frame structures within the JIT - Enable enregistration for the secret stub parameter Fix dotnet#100662
When a pinvoke/reverse pinvoke needs marshalling the VM creates an IL stub to perform this marshalling. These IL stubs have a non-standard parameter called the "secret stub parameter". The VM uses this parameter to map the IL stub back to the user defined function that caused the IL stub to be required (multiple user functions can share the same IL stubs, so the mapping cannot be done by other means).
To facilitate the access of this value the JIT must make the parameter's value available to the VM somehow. Previously this was done in two separate ways for 32-bit and 64-bit target:
InlinedCallFrameas part of a VM helper call. We still marked it as do-not-enregister, probably because parameter homing did not handle it.For 64-bit targets this introduces a bit of inefficiency: the secret stub parameter is only needed for the IL stubs case, but
InlinedCallFrameis used for all inlined pinvokes. So we ended up with a larger frame than necessary and with an additional store to the frame, even outside IL stubs.This change removes that inefficiency by unifying how 32-bit and 64-bit targets work:
InlinedCallFramefor the secret stub parameter when necessaryCORINFO_HELP_INIT_PINVOKE_FRAMEand to the JIT generated codeFix #100662
Example diff
Benchmark:
Codegen + execution time diffs: x64 (improvement), x86 (no change)