IL: share ILCallingConv instances - #20254
Conversation
❗ Release notes requiredYou can open this PR in browser to add release notes: open in github.dev
|
1c1b4ab to
cd07753
Compare
There are only 18 combinations of ILThisConvention and ILArgConvention. Pre-create all of them and hand out the shared instance from ILCallingConv.Create, so reading a method signature no longer allocates a Callconv. The two existing statics (Instance, Static) are placed in the table too, so every use shares one instance per combination. The index is computed with explicit matches rather than by casting the union tags, so adding a case to either union is a compile error here instead of a bad index. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
3bf3808 to
eeff5f0
Compare
|
🔍 Tooling Safety Check — Affects-Compiler-Output
|
T-Gro
left a comment
There was a problem hiding this comment.
Really nice, self-contained win — 60k live ILCallingConv objects collapsing to 18 for effectively free is exactly the allocation the metadata reader should never have been making. The semantics are preserved end to end: structural equality means the shared instances compare identically to freshly-allocated ones, the pickle byte format is untouched (p_ILCallConv still writes ThisConv/BasicConv), and every out-of-module Callconv(...) construction and match was migrated to Create / member access, so sealing the case as private is airtight. I double-checked there are no stragglers — the only Callconv(...) sites left are inside il.fs, and the ProvidedTypes.fs / absil.fsi hits are unrelated self-contained copies.
Two tiny things before merge:
-
The release-note link is missing its closing paren:
.../pull/20254)needs a second)to close the wrapping(, otherwise it renders as literal text unlike the sibling entries. -
The comment on
Getsays adding a union case is "a compile error here rather than a bad index." That holds for thematchcompleteness, butthisIdx * 6 + argIdxis a separate magic number: if a newILArgConventioncase is added, the incomplete-match error forces an update toargIdx, yet nothing forces the6to trackargConvs.Length— so the table build (i % argConvs.Length) and the lookup could silently disagree. Deriving the stride from one sharedletwould make the safety net actually match the comment.
Neither blocks — the change is correct as-is. A one-liner asserting obj.ReferenceEquals(ILCallingConv.Create(ILThisConvention.Instance, ILArgConvention.Default), ILCallingConv.Instance) would lock the sharing in against future regressions, but that's optional.
|
This is ready. |
This adds
ILCallingConv.Create, backed by a table of all 18 combinations, and uses it from the reader.In a heap snapshot of
ParseAndCheckProjectover a 57-file project with 489 references,ILCallingConvwent from 60,239 live objects (1.84 MB) to 18.Retained memory after ParseAndCheckProject: