Repository navigation
Apply existing constrained call target refinements to static abstract interface methods - #135169
NinoFloris wants to merge 2 commits into
Conversation
|
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 this area: @JulieLeeMSFT, @jakobbotsch |
8d3a4c9 to
9729caa
Compare
|
Failure is #134825 |
… interface methods Extend the existing instance target-resolution strategy to constrained static interface calls on value types. Preserve instance handling, static defaults, and reference-type hierarchy resolution without changing dictionary lookup or call generation. Add functional coverage for shared receivers, generic methods, defaults, variance, and delegates, plus codegen checks for five cases that now inline, including the FuncImpl scenario.
9729caa to
a75b0b1
Compare
|
Added another commit allowing target refinement for static abstract calls on reference types. Instance calls retain the existing restriction to value types. Static abstract calls now use the same target refinements for class targets. The reason this is safe is that static abstract dispatch depends on the constrained type argument, not an object’s runtime type. This is one part of improving static abstract performance in shared generics when the implementing type family is known (e.g. Node<T>, instantiated with string). We can identify the interface implementation even though the generic argument causes the code to be shared. |
Existing constrained call resolution refinements weren’t applied to static abstract interface methods: static calls were handled by an early-return path before reaching them. This moves that path after the refinements and extends the existing logic to handle static members where necessary.
This fixes #135168, and a few other deficiencies (see regression cases).
Tested on macOS arm64 Release, tiered compilation disabled. Before the change, all five static calls use a generic-dictionary lookup and an indirect call. Afterward, each implementation is inlined, with no lookup or call remaining.
CallUniqueFuncImplcasemov w0, w2— return the tuple's integer fieldCallExactGenericExactGenericFunc<int>add w0, w2, #5CallDefaultmov w0, #7CallCovariantUniquetypeof(string)referenceCallGenericExactintargumenttypeof(int)referenceAddress values shown as
0xD1FFAB1Eare placeholders emitted byJitDisasmDiffable.CallUnique: 100 → 20 bytes
Before:
After:
CallExactGeneric: 84 → 20 bytes
Before:
After:
CallDefault: 84 → 20 bytes
Before:
After:
CallCovariantUnique: 60 → 28 bytes
Before:
After:
CallGenericExact: 84 → 28 bytes
Before:
After: