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

Code before:
                    methodHandle = MetadataTokens.MemberReferenceHandle(rid);
                }
                else
                {
                    methodHandle = MetadataTokens.MethodDefinitionHandle(rid);
                }
                string[] methodTypeArgs = null;
                if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_MethodInstantiation) != 0)
                {
                    uint typeArgCount = decoder.ReadUInt();
                    methodTypeArgs = new string[typeArgCount];
                    for (int typeArgIndex = 0; typeArgIndex < typeArgCount; typeArgIndex++)
                    {
                        methodTypeArgs[typeArgIndex] = decoder.ReadTypeSignatureNoEmit();
                    }
                }

                string constrainedType = null;
                if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_Constrained) != 0)
                {
                    constrainedType = decoder.ReadTypeSignatureNoEmit();
                }

                int runtimeFunctionId;
                int? fixupOffset;
                GetRuntimeFunctionIndexFromOffset((int)decoder.Offset, out runtimeFunctionId, out fixupOffset);
                ReadyToRunMethod method = new ReadyToRunMethod(
                    this,
                    mdReader,
                    methodHandle,
                    runtimeFunctionId,
                    owningType,
                    constrainedType,
                    methodTypeArgs,
                    fixupOffset);
                if (method.EntryPointRuntimeFunctionId >= 0 && method.EntryPointRuntimeFunctionId < isEntryPoint.Length)
                {
                    isEntryPoint[method.EntryPointRuntimeFunctionId] = true;
                }
                _instanceMethods.Add(new InstanceMethod(curParser.LowHashcode, method));
                curParser = allEntriesEnum.GetNext();
            }
        }

        public IEnumerable<ReadyToRunMethod> Methods
        {
            get
            {
                EnsureMethods();
                return _readyToRunAssemblies.SelectMany(assembly => assembly.Methods).Concat(_instanceMethods.Select(im => im.Method));
            }

Review comment (suggestion):
DecodeMethodSignature allocates a List<string> and then an array for every parsed signature (even when no flags are set). Since there are only three known prefixes, consider avoiding per-method allocations by directly building a small array (or using Array.Empty<string>() when no flags are present).
```suggestion
            int prefixCount = 0;
            bool hasUnboxingStub = (methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_UnboxingStub) != 0;
            if (hasUnboxingStub)
            {
                prefixCount++;
            }

            bool hasInstantiatingStub = (methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_InstantiatingStub) != 0;
            if (hasInstantiatingStub)
            {
                prefixCount++;
            }

            bool hasAsyncVariant = (methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_AsyncVariant) != 0;
            if (hasAsyncVariant)
            {
                prefixCount++;
            }

            string[] signaturePrefixes;
            if (prefixCount == 0)
            {
                signaturePrefixes = Array.Empty<string>();
            }
            else
            {
                signaturePrefixes = new string[prefixCount];
                int prefixIndex = 0;
                if (hasUnboxingStub)
                {
                    signaturePrefixes[prefixIndex++] = "[UNBOX]";
                }
                if (hasInstantiatingStub)
                {
                    signaturePrefixes[prefixIndex++] = "
";
                }
                if (hasAsyncVariant)
                {
                    signaturePrefixes[prefixIndex++] = "[ASYNC]";
                }
            }

            return new DecodedMethodSignature(owningType, methodHandle, methodTypeArgs, constrainedType, signaturePrefixes);
```

Code after:
                {
                    methodTypeArgs[typeArgIndex] = decoder.ReadTypeSignatureNoEmit();
                }
            }

            string constrainedType = null;
            if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_Constrained) != 0)
            {
                constrainedType = decoder.ReadTypeSignatureNoEmit();
            }

            List<string> signaturePrefixes = [];
            if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_UnboxingStub) != 0)
            {
                signaturePrefixes.Add("[UNBOX]");
            }
            if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_InstantiatingStub) != 0)
            {
                signaturePrefixes.Add("
");
            }
            if ((methodFlags & (uint)ReadyToRunMethodSigFlags.READYTORUN_METHOD_SIG_AsyncVariant) != 0)
            {
                signaturePrefixes.Add("[ASYNC]");
            }

            return new DecodedMethodSignature(owningType, methodHandle, methodTypeArgs, constrainedType, signaturePrefixes.ToArray());
        }

        /// <summary>
        /// Initialize generic method instances with argument types and runtime function indices from InstanceMethodEntrypoints
        /// </summary>
        private void ParseInstanceMethodEntrypoints(bool[] isEntryPoint)
        {
            if (!ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.InstanceMethodEntryPoints, out ReadyToRunSection instMethodEntryPointSection))
            {
                return;
            }
            int instMethodEntryPointsOffset = GetOffset(instMethodEntryPointSection.RelativeVirtualAddress);
            NativeParser parser = new NativeParser(ImageReader, (uint)instMethodEntryPointsOffset);
            NativeHashtable instMethodEntryPoints = new NativeHashtable(ImageReader, parser, (uint)(instMethodEntryPointsOffset + instMethodEntryPointSection.Size));
            NativeHashtable.AllEntriesEnumerator allEntriesEnum = instMethodEntryPoints.EnumerateAllEntries();
            NativeParser curParser = allEntriesEnum.GetNext();
            while (!curParser.IsNull())
            {
                IAssemblyMetadata mdReader = GetGlobalMetadata();
                SignatureFormattingOptions dummyOptions = new SignatureFormattingOptions();
                SignatureDecoder decoder = new SignatureDecoder(_assemblyResolver, dummyOptions, mdReader?.MetadataReader, this, (int)curParser.Offset);

                var sig = DecodeMethodSignature(ref mdReader, ref decoder);

                int runtimeFunctionId;