Repository: dotnet/runtime
File: src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs (C#)

Code before:
        /// <exception cref="ArgumentException"><paramref name="type" /> must be a type provided by the runtime.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="size" /> is negative.</exception>
        /// <exception cref="ArgumentException"><paramref name="alignment" /> is not a power of <c>2</c>.</exception>
        public static IntPtr AllocateTypeAssociatedMemory(Type type, int size, int alignment)
        {
            if (type is not RuntimeType rt)
            {
                throw new ArgumentException(SR.Arg_MustBeType, nameof(type));
            }

            ArgumentOutOfRangeException.ThrowIfNegative(size);

            if (!BitOperations.IsPow2(alignment))
            {
                // The C standard doesn't define what a valid alignment is, however Windows and POSIX implementation requires a power of 2
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AlignmentMustBePow2);
            }

            return AlignedAllocateTypeAssociatedMemory(new QCallTypeHandle(ref rt), (uint)size, (uint)alignment);
        }

        [LibraryImport(QCall, EntryPoint = "RuntimeTypeHandle_AllocateTypeAssociatedMemory")]
        private static partial IntPtr AllocateTypeAssociatedMemory(QCallTypeHandle type, uint size);

        [LibraryImport(QCall, EntryPoint = "RuntimeTypeHandle_AlignedAllocateTypeAssociatedMemory")]
        private static partial IntPtr AlignedAllocateTypeAssociatedMemory(QCallTypeHandle type, uint size, uint alignment);

        [MethodImpl(MethodImplOptions.InternalCall)]
        private static extern unsafe TailCallArgBuffer* GetTailCallArgBuffer();

        [LibraryImport(QCall, EntryPoint = "TailCallHelp_AllocTailCallArgBufferInternal")]
        private static unsafe partial TailCallArgBuffer* AllocTailCallArgBufferInternal(int size);

        private const int TAILCALLARGBUFFER_ACTIVE = 0;
        // private const int TAILCALLARGBUFFER_INSTARG_ONLY = 1;
        private const int TAILCALLARGBUFFER_INACTIVE = 2;

        [MethodImpl(MethodImplOptions.AggressiveInlining)] // To allow unrolling of Span.Clear
        private static unsafe TailCallArgBuffer* AllocTailCallArgBuffer(int size, IntPtr gcDesc)
        {
            TailCallArgBuffer* buffer = GetTailCallArgBuffer();
            if (buffer != null && buffer->Size >= size)
            {
                buffer->State = TAILCALLARGBUFFER_INACTIVE;
            }
            else
            {
                buffer = AllocTailCallArgBufferWorker(size);

                [MethodImpl(MethodImplOptions.NoInlining)]
                static TailCallArgBuffer* AllocTailCallArgBufferWorker(int size) => AllocTailCallArgBufferInternal(size);

Review comment (performance):
I'd prefer the qualifier at the end, `AllocateTypeAssociatedMemoryAligned`. We do this for most APIs if I recall, "Unsafe", "Internal", "Slow", etc.

Code after:
        /// <exception cref="ArgumentException"><paramref name="type" /> must be a type provided by the runtime.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="size" /> is negative.</exception>
        /// <exception cref="ArgumentException"><paramref name="alignment" /> is not a power of <c>2</c>.</exception>
        public static IntPtr AllocateTypeAssociatedMemory(Type type, int size, int alignment)
        {
            if (type is not RuntimeType rt)
            {
                throw new ArgumentException(SR.Arg_MustBeType, nameof(type));
            }

            ArgumentOutOfRangeException.ThrowIfNegative(size);

            if (!BitOperations.IsPow2(alignment))
            {
                // The C standard doesn't define what a valid alignment is, however Windows and POSIX implementation requires a power of 2
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AlignmentMustBePow2);
            }

            return AllocateTypeAssociatedMemoryAligned(new QCallTypeHandle(ref rt), (uint)size, (uint)alignment);
        }

        [LibraryImport(QCall, EntryPoint = "RuntimeTypeHandle_AllocateTypeAssociatedMemory")]
        private static partial IntPtr AllocateTypeAssociatedMemory(QCallTypeHandle type, uint size);

        [LibraryImport(QCall, EntryPoint = "RuntimeTypeHandle_AllocateTypeAssociatedMemoryAligned")]
        private static partial IntPtr AllocateTypeAssociatedMemoryAligned(QCallTypeHandle type, uint size, uint alignment);

        [MethodImpl(MethodImplOptions.InternalCall)]
        private static extern unsafe TailCallArgBuffer* GetTailCallArgBuffer();

        [LibraryImport(QCall, EntryPoint = "TailCallHelp_AllocTailCallArgBufferInternal")]
        private static unsafe partial TailCallArgBuffer* AllocTailCallArgBufferInternal(int size);

        private const int TAILCALLARGBUFFER_ACTIVE = 0;
        // private const int TAILCALLARGBUFFER_INSTARG_ONLY = 1;
        private const int TAILCALLARGBUFFER_INACTIVE = 2;

        [MethodImpl(MethodImplOptions.AggressiveInlining)] // To allow unrolling of Span.Clear
        private static unsafe TailCallArgBuffer* AllocTailCallArgBuffer(int size, IntPtr gcDesc)
        {
            TailCallArgBuffer* buffer = GetTailCallArgBuffer();
            if (buffer != null && buffer->Size >= size)
            {
                buffer->State = TAILCALLARGBUFFER_INACTIVE;
            }
            else
            {
                buffer = AllocTailCallArgBufferWorker(size);

                [MethodImpl(MethodImplOptions.NoInlining)]
                static TailCallArgBuffer* AllocTailCallArgBufferWorker(int size) => AllocTailCallArgBufferInternal(size);