<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if AMD64 || (BIT32 && !ARM)
#define HAS_CUSTOM_BLOCKS
#endif

using System;
using System.Runtime;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

#if BIT64
using nuint = System.UInt64;
#else
using nuint = System.UInt32;
#endif

namespace System
{
    public static class Buffer
    {
        public static unsafe void BlockCopy(Array src, int srcOffset,
                                            Array dst, int dstOffset,
                                            int count)
        {
            if (src == null)
                throw new ArgumentNullException(nameof(src));
            if (dst == null)
                throw new ArgumentNullException(nameof(dst));


            RuntimeImports.RhCorElementTypeInfo srcCorElementTypeInfo = src.ElementEEType.CorElementTypeInfo;

            nuint uSrcLen = ((nuint)src.Length) << srcCorElementTypeInfo.Log2OfSize;
            nuint uDstLen = uSrcLen;

            if (!srcCorElementTypeInfo.IsPrimitive)
                throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(src));

            if (src != dst)
            {
                RuntimeImports.RhCorElementTypeInfo dstCorElementTypeInfo = dst.ElementEEType.CorElementTypeInfo;
                if (!dstCorElementTypeInfo.IsPrimitive)
                    throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(dst));
                uDstLen = ((nuint)dst.Length) << dstCorElementTypeInfo.Log2OfSize;
            }

            if (srcOffset < 0)
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(srcOffset));
            if (dstOffset < 0)
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(dstOffset));
            if (count < 0)
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(count));

            nuint uCount = (nuint)count;
            if (uSrcLen < ((nuint)srcOffset) + uCount)
                throw new ArgumentException(SR.Argument_InvalidOffLen);
            if (uDstLen < ((nuint)dstOffset) + uCount)
                throw new ArgumentException(SR.Argument_InvalidOffLen);

            if (uCount == 0)
                return;<commit_msg>Optimize Buffer.BlockCopy for byte arrays (#3563)<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#if AMD64 || (BIT32 && !ARM)
#define HAS_CUSTOM_BLOCKS
#endif

using System;
using System.Runtime;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

#if BIT64
using nuint = System.UInt64;
#else
using nuint = System.UInt32;
#endif

namespace System
{
    [EagerStaticClassConstruction]
    public static class Buffer
    {
        /// <summary>
        /// This field is used to quickly check whether an array that is given to the BlockCopy
        /// method is a byte array and the code can take optimized path.
        /// </summary>
        private static readonly EETypePtr s_byteArrayEEType = EETypePtr.EETypePtrOf<byte[]>();

        public static unsafe void BlockCopy(Array src, int srcOffset,
                                            Array dst, int dstOffset,
                                            int count)
        {
            nuint uSrcLen;
            nuint uDstLen;

            if (src == null)
                throw new ArgumentNullException(nameof(src));
            if (dst == null)
                throw new ArgumentNullException(nameof(dst));

            // Use optimized path for byte arrays since this is the main scenario for Buffer::BlockCopy
            EETypePtr byteArrayEEType = s_byteArrayEEType;
            if (src.EETypePtr.FastEquals(byteArrayEEType))
            {
                uSrcLen = (nuint)src.Length;
            }
            else
            {
                RuntimeImports.RhCorElementTypeInfo srcCorElementTypeInfo = src.ElementEEType.CorElementTypeInfo;
                uSrcLen = ((nuint)src.Length) << srcCorElementTypeInfo.Log2OfSize;
                if (!srcCorElementTypeInfo.IsPrimitive)
                    throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(src));
            }

            if (src != dst)
            {
                if (dst.EETypePtr.FastEquals(byteArrayEEType))
                {
                    uDstLen = (nuint)dst.Length;
                }
                else
                {
                    RuntimeImports.RhCorElementTypeInfo dstCorElementTypeInfo = dst.ElementEEType.CorElementTypeInfo;
                    if (!dstCorElementTypeInfo.IsPrimitive)
                        throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(dst));
                    uDstLen = ((nuint)dst.Length) << dstCorElementTypeInfo.Log2OfSize;
                }
            }
            else
            {
                uDstLen = uSrcLen;
            }

            if (srcOffset < 0)
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(srcOffset));
            if (dstOffset < 0)
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(dstOffset));
            if (count < 0)
                throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_MustBeNonNegInt32, nameof(count));

            nuint uCount = (nuint)count;
            if (uSrcLen < ((nuint)srcOffset) + uCount)
                throw new ArgumentException(SR.Argument_InvalidOffLen);
            if (uDstLen < ((nuint)dstOffset) + uCount)
                throw new ArgumentException(SR.Argument_InvalidOffLen);

            if (uCount == 0)
                return;
{'fraction_non_alphanumeric': 0.07619513786914668, 'fraction_numerical': 0.00783162016642193, 'mean_word_length': 2.0452061599602582, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2972311', 'n_tokens_mistral': 1644, 'n_tokens_neox': 1591, 'n_words': 407}