Repository navigation
[wasm][R2R] Fix calls through MethodImpl-redirected slots on portable entrypoints - #136050
Conversation
… targets Crossgen2 emitted R2R-to-interpreter thunks only for call-site signatures. When a JIT helper is backed by a managed CoreLib method that is not in the image, the method runs in the interpreter, and the helper's import cell can only reach it through a thunk of the helper's signature. Small composites that lacked a call site with a matching signature left the helper's portable entrypoint without native code, so R2R code trapped with "uninitialized element". Register the thunk at each helper use. On portable entrypoints, ExternalMethodFixupWorker prestubbed the declared method even when a MethodImpl in the same type redirected its slot to another method, tripping the !ShouldCallPrestub() assert. Prepare and call the MethodImpl target instead. TryGetMultiCallableAddrOfCode likewise handed out the declared method's entrypoint, so delegates and ldftn ran the substituted body; return the MethodImpl target's entrypoint, as FuncPtrStubs does on other platforms. Remove the WASI R2R quarantines for overflow0[1-4]_div and self_override5. Fixes #134949 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fc3c5462-a1aa-4727-b4d2-d43b9bbb16d9
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara |
|
Tagging subscribers to this area: @dotnet/crossgen-contrib |
Can we declare this configuration to be invalid? I do not think it is interesting to chase bugs in configurations where Corelib is interpreted, but the app is R2R.
|
Yeah that is probably the better choice, this is mostly a synthetic test problem due to the runtime tests being difficult to produce in r2r composite mode. Right now apple mobile runtime tests only r2r CoreLib, and wasi only r2rs the test assembly. I'm double checking and will update shortly. |
Managed JIT helpers only lack an R2R-to-interpreter thunk when CoreLib is interpreted while other code is R2R. Treat that configuration as unsupported (R2R code outside CoreLib requires an R2R CoreLib that contains all JIT helpers) instead of emitting helper thunks into every image. Restore the WASI R2R quarantines for overflow0[1-4]_div, which hit this in the current runtime-test lane where CoreLib is interpreted. The MethodImpl fixes are independent of that configuration and remain. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fc3c5462-a1aa-4727-b4d2-d43b9bbb16d9
|
Agreed, and I've updated the PR accordingly. The crossgen2 helper-thunk change is gone, and the Follow-ups:
Note This comment was drafted with the help of GitHub Copilot. |
Address review feedback on the portable-entrypoint MethodImpl handling: - ExternalMethodFixupWorker: like the non-portable branch, call through pMD's slot (GetMethodEntryPoint) and prepare the method that owns the slot's entry, instead of mapping pMD with MapMethodDeclToMethodImpl. - Drop the TryGetMultiCallableAddrOfCode change. Non-portable targets hand out the declared method's own entrypoint there too; the redirection happens when ThePreStub jumps to DoBackpatch's result, the slot target. The portable equivalent is the R2R-to-interpreter entry, which now maps decl to impl (as the interpreter's PrepareInterpreterCode does) before preparing and running the method, instead of ignoring the redirection. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fc3c5462-a1aa-4727-b4d2-d43b9bbb16d9
When the interpreter reaches a declaration whose slot a same-type MethodImpl redirects, PrepareInterpreterCode stores the implementation's interpreter code on the declaration. A later call from R2R code through the declaration's portable entrypoint took ExecuteInterpretedMethodWithArgs_ PortableEntryPoint_Complex's early path with that code, and in Checked builds asserted that the declaration's entrypoint had interpreter data. Run as the method that owns the interpreter code instead. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fc3c5462-a1aa-4727-b4d2-d43b9bbb16d9
Apply review suggestions: when the method already has interpreter code, run as the method that code was compiled for; otherwise prestub. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: fc3c5462-a1aa-4727-b4d2-d43b9bbb16d9
With a same-type
.override, a declaration's vtable slot holds the implementation's entrypoint, so on non-portable targets callers that start from the declaration still reach the implementation through the slot. With portable entrypoints (Wasm), three paths ran or prepared the declaration instead (self_override5):ExternalMethodFixupWorkerprestubbed the declaration before reading the slot, publishing the declaration's own R2R body and asserting in Checked. It now reads the slot, prepares the method that owns that entry, and patches the cell with it, like the non-portable branch.ExecuteInterpretedMethodWithArgs_PortableEntryPoint_Complex(R2R → interpreter) prepared and ran the declaration, for example for a delegate bound by name to it. It now maps decl→impl first, asPrepareInterpreterCodealready does.Removes the #134949 quarantine on
self_override5.Contributes to #134949
Scope and validation
The other #134949 failure (
overflow0[1-4]_div) occurs only when R2R code runs with an interpreted CoreLib, which review settled is unsupported, so those quarantines stay.CallDescrWorkerInternal's portable path also prestubs without mapping; not reproduced, possible follow-up.Validated on WASI (Checked runtime, wasmtime) with both an R2R CoreLib and the CI configuration: the MethodImpl tests, 20
CovariantReturnstests andjit64_5pass under R2R and the interpreter. Not validated: browser and Release runtime builds.Note
This pull request description was drafted with the help of GitHub Copilot.