Repository: dotnet/runtime
File: src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs (C#)

Code before:
                if (Logger.IsVerbose)
                    Logger.Writer.WriteLine($"Processing {obj.Count} dependencies");

                // Ensure all methods being compiled have assigned tokens. This matters for code from modules from outside of the version bubble
                // as those tokens are dynamically assigned, and for instantiation which depend on tokens outside of the module
                var ilProvider = (ReadyToRunILProvider)_methodILCache.ILProvider;
                obj.MergeSortAllowDuplicates(new SortableDependencyNode.ObjectNodeComparer(CompilerComparer.Instance));
                foreach (var dependency in obj)
                {
                    if (dependency is MethodWithGCInfo methodCodeNodeNeedingCode)
                    {
                        var method = methodCodeNodeNeedingCode.Method;
                        if (method.GetTypicalMethodDefinition() is EcmaMethod ecmaMethod)
                        {
                            if (ilProvider.NeedsCrossModuleInlineableTokens(ecmaMethod) &&
                                !_methodsWhichNeedMutableILBodies.Contains(ecmaMethod) &&
                                CorInfoImpl.IsMethodCompilable(this, methodCodeNodeNeedingCode.Method))
                                _methodsWhichNeedMutableILBodies.Add(ecmaMethod);
                        }
                        if (method.IsAsyncThunk())
                        {
                            // The synthetic async thunks require references to methods/types that may not have existing methodRef entries in the version bubble.
                            // These references need to be added to the mutable module if they don't exist.
                            var requiredMutableModuleReferences = method.IsAsyncVariant() ?
                                AsyncThunkILEmitter.GetRequiredReferencesForAsyncThunk(((AsyncMethodVariant)method).Target)
                                : AsyncThunkILEmitter.GetRequiredReferencesForTaskReturningThunk(method);
                            _nodeFactory.ManifestMetadataTable._mutableModule.ModuleThatIsCurrentlyTheSourceOfNewReferences = ((EcmaMethod)method.GetTypicalMethodDefinition()).Module;
                            try
                            {
                                foreach (var entity in requiredMutableModuleReferences)
                                {
                                    switch (entity)
                                    {
                                        case MethodDesc md:
                                            if (_nodeFactory.Resolver.GetModuleTokenForMethod(md, allowDynamicallyCreatedReference: true, throwIfNotFound: false).IsNull)
                                            {
                                                _nodeFactory.ManifestMetadataTable._mutableModule.TryGetEntityHandle(md);
                                                Debug.Assert(!_nodeFactory.Resolver.GetModuleTokenForMethod(md, allowDynamicallyCreatedReference: true, throwIfNotFound: true).IsNull);
                                            }
                                            break;
                                        case EcmaType td:
                                            if (_nodeFactory.Resolver.GetModuleTokenForType(td, allowDynamicallyCreatedReference: true, throwIfNotFound: false).IsNull)
                                            {
                                                _nodeFactory.ManifestMetadataTable._mutableModule.TryGetEntityHandle(td);
                                                Debug.Assert(!_nodeFactory.Resolver.GetModuleTokenForType(td, allowDynamicallyCreatedReference: true, throwIfNotFound: true).IsNull);
                                            }
                                            break;
                                        default:
                                            Logger.LogMessage($"Unable to add a reference to '{entity.GetDisplayName()}' to the mutable module");
                                            break;
                                    }

Review comment (refactor):
What is the set of methods/types this returns? Would we be able to obtain the same set of types/method by inspecting the IL of `method`?

What I'm getting at is whether we'd be able to leave AsyncThunks.cs as-is and instead here do `ilProvider.GetMethodIL(method)`, construct an `ILReader` over the body, do a for loop over all instructions and extract the dependencies from there. I'm concerned about the readability of AsyncThunks.cs basically.

Code after:
                if (Logger.IsVerbose)
                    Logger.Writer.WriteLine($"Processing {obj.Count} dependencies");

                // Ensure all methods being compiled have assigned tokens. This matters for code from modules from outside of the version bubble
                // as those tokens are dynamically assigned, and for instantiation which depend on tokens outside of the module
                var ilProvider = (ReadyToRunILProvider)_methodILCache.ILProvider;
                obj.MergeSortAllowDuplicates(new SortableDependencyNode.ObjectNodeComparer(CompilerComparer.Instance));
                foreach (var dependency in obj)
                {
                    if (dependency is MethodWithGCInfo methodCodeNodeNeedingCode)
                    {
                        var method = methodCodeNodeNeedingCode.Method;
                        if (method.GetTypicalMethodDefinition() is EcmaMethod ecmaMethod)
                        {
                            if (ilProvider.NeedsCrossModuleInlineableTokens(ecmaMethod) &&
                                !_methodsWhichNeedMutableILBodies.Contains(ecmaMethod) &&
                                CorInfoImpl.IsMethodCompilable(this, methodCodeNodeNeedingCode.Method))
                                _methodsWhichNeedMutableILBodies.Add(ecmaMethod);
                        }
                        if (method.IsAsyncThunk())
                        {
                            // The synthetic async thunks require references to methods/types that may not have existing methodRef entries in the version bubble.
                            // These references need to be added to the mutable module if they don't exist.
                            // Extract the required references by reading the IL of the thunk method.
                            MethodIL methodIL = GetMethodIL(method);
                            if (methodIL is null)
                                continue;

                            _nodeFactory.ManifestMetadataTable._mutableModule.ModuleThatIsCurrentlyTheSourceOfNewReferences = ((EcmaMethod)method.GetTypicalMethodDefinition()).Module;
                            try
                            {
                                foreach (var entity in ILStubReferences.GetNecessaryReferencesFromIL(methodIL))
                                {
                                    switch (entity)
                                    {
                                        case MethodDesc md:
                                            if (md.IsAsyncVariant())
                                            {
                                                Debug.Assert(((CompilerTypeSystemContext)md.Context).GetTargetOfAsyncVariantMethod(md.GetTypicalMethodDefinition()) == method);
                                                Debug.Assert(!_nodeFactory.Resolver.GetModuleTokenForMethod(method, allowDynamicallyCreatedReference: false, throwIfNotFound: true).IsNull);
                                            }
                                            else if (_nodeFactory.Resolver.GetModuleTokenForMethod(md, allowDynamicallyCreatedReference: true, throwIfNotFound: false).IsNull)
                                            {
                                                _nodeFactory.ManifestMetadataTable._mutableModule.TryGetEntityHandle(md);
                                                Debug.Assert(!_nodeFactory.Resolver.GetModuleTokenForMethod(md, allowDynamicallyCreatedReference: true, throwIfNotFound: true).IsNull);
                                            }
                                            break;
                                        case TypeDesc td:
                                            if (_nodeFactory.Resolver.GetModuleTokenForType(td, allowDynamicallyCreatedReference: true, throwIfNotFound: false).IsNull)
                                            {
                                                _nodeFactory.ManifestMetadataTable._mutableModule.TryGetEntityHandle(td);