1

I'm looking at System.buffer.cs on the Microsoft reference source, and I see this code starting at line 508:

#if WIN64
        private unsafe static void _Memmove(byte* dest, byte* src, ulong len)
#else
        private unsafe static void _Memmove(byte* dest, byte* src, uint len)
#endif
        {
            __Memmove(dest, src, len);
        }

        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
        [SuppressUnmanagedCodeSecurity]
        [SecurityCritical]
        [ResourceExposure(ResourceScope.None)]        
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#if WIN64
        extern private unsafe static void __Memmove(byte* dest, byte* src, ulong len);
#else
        extern private unsafe static void __Memmove(byte* dest, byte* src, uint len);
#endif

The code refers to an external __Memmove() function. Where is that function implemented?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
ssa2
  • 75
  • 6
  • 2
    https://stackoverflow.com/a/6558515/103167 – Ben Voigt Mar 24 '18 at 04:19
  • 1
    https://github.com/dotnet/coreclr/blob/master/src/vm/comutilnative.cpp#L823 The function that does the real job there, memmove(), is a standard C library function: http://www.cplusplus.com/reference/cstring/memmove The only real reason it is wrapped like this is to change the behavior when the code causes an AccessViolationException. – Hans Passant Mar 24 '18 at 07:18

1 Answers1

2

After I read the question and answers that Ben Voigt posted in the comments:

How is Array.Copy implemented in C#? [Hans Passant's answer]
https://stackoverflow.com/a/6558515/103167

I've searched for JitHelpers.QCall and found this post:

What is [DllImport("QCall")]?

That led me to this page:

coreclr/Documentation/mscorlib.md - Calling from managed to native code
https://github.com/dotnet/coreclr/blob/0c88c2e67260ddcb1d400eb6adda19de627998f5/Documentation/mscorlib.md#calling-from-managed-to-native-code

We have two techniques for calling into the CLR from managed code. FCall allows you to call directly into the CLR code, and provides a lot of flexibility in terms of manipulating objects, though it is easy to cause GC holes by not tracking object references correctly. QCall allows you to call into the CLR via the P/Invoke, and is much harder to accidentally mis-use than FCall. FCalls are identified in managed code as extern methods with the MethodImplOptions.InternalCall bit set. QCalls are static extern methods that look like regular P/Invokes, but to a library called "QCall".

[...]

QCall Functional Behavior
QCalls are very much like a normal P/Invoke from mscorlib.dll to CLR. Unlike FCalls, QCalls will marshal all arguments as unmanaged types like a normal P/Invoke. QCall also switch to preemptive GC mode like a normal P/Invoke. These two features should make QCalls easier to write reliably compared to FCalls. QCalls are not prone to GC holes and GC starvation bugs that are common with FCalls.

If you run ILDasm (one possible path: C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.7 Tools\x64\ildasm.exe) and opens mscorlib.dll (one possible path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll), and look under System > System.Buffer, you will see Memmove, _Memmove and __Memmove.

Pedro Gaspar
  • 777
  • 8
  • 35