Example #1
0
 public static IntPtr Set(byte *dest, int c, long count)
 {
     Debug.Assert(count >= 0);
     return(PlatformDetails.RunningOnPosix
         ? Syscall.Set(dest, c, count)
         : Win32UnmanagedMemory.Set(dest, c, count));
 }
Example #2
0
 public static int Move(byte *dest, byte *src, long count)
 {
     Debug.Assert(count >= 0);
     return(PlatformDetails.RunningOnPosix
         ? Syscall.Move(dest, src, count)
         : Win32UnmanagedMemory.Move(dest, src, count));
 }
Example #3
0
 public static int Compare(byte *b1, byte *b2, long count)
 {
     Debug.Assert(count >= 0);
     return(PlatformDetails.RunningOnPosix
         ? Syscall.Compare(b1, b2, count)
         : Win32UnmanagedMemory.Compare(b1, b2, count));
 }
Example #4
0
        public static void Move(byte *dest, byte *src, int n)
        {
            // if dest and src overlaps, we need to call specifically to memmove pinvoke supporting overlapping
            if (dest + n >= src &&
                src + n >= dest)
            {
                var _ = PlatformDetails.RunningOnPosix
                    ? Syscall.Move(dest, src, n)
                    : Win32UnmanagedMemory.Move(dest, src, n);
                return;
            }

            Copy(dest, src, n);
        }
Example #5
0
        public static int CompareInline(void *p1, void *p2, int size)
        {
            // If we use an unmanaged bulk version with an inline compare the caller site does not get optimized properly.
            // If you know you will be comparing big memory chunks do not use the inline version.
            if (size > CompareInlineVsCallThreshold)
            {
                goto UnmanagedCompare;
            }

            byte *bpx = (byte *)p1;
            byte *bpy = (byte *)p2;

            // PERF: This allows us to do pointer arithmetics and use relative addressing using the
            //       hardware instructions without needed an extra register.
            long offset = bpy - bpx;

            if ((size & 7) == 0)
            {
                goto ProcessAligned;
            }

            // We process first the "unaligned" size.
            ulong xor;

            if ((size & 4) != 0)
            {
                xor = *((uint *)bpx) ^ *((uint *)(bpx + offset));
                if (xor != 0)
                {
                    goto Tail;
                }

                bpx += 4;
            }

            if ((size & 2) != 0)
            {
                xor = (ulong)(*((ushort *)bpx) ^ *((ushort *)(bpx + offset)));
                if (xor != 0)
                {
                    goto Tail;
                }

                bpx += 2;
            }

            if ((size & 1) != 0)
            {
                int value = *bpx - *(bpx + offset);
                if (value != 0)
                {
                    return(value);
                }

                bpx += 1;
            }

ProcessAligned:

            byte *end = (byte *)p1 + size;
            byte *loopEnd = end - 16;

            while (bpx <= loopEnd)
            {
                // PERF: JIT will emit: ```{op} {reg}, qword ptr [rdx+rax]```
                if (*((ulong *)bpx) != *(ulong *)(bpx + offset))
                {
                    goto XorTail;
                }

                if (*((ulong *)(bpx + 8)) != *(ulong *)(bpx + 8 + offset))
                {
                    bpx += 8;
                    goto XorTail;
                }


                bpx += 16;
            }

            if (bpx < end)
            {
                goto XorTail;
            }

            return(0);

            XorTail : xor = *((ulong *)bpx) ^ *(ulong *)(bpx + offset);

Tail:

            // Fast-path for equals
            if (xor == 0)
            {
                return(0);
            }

            // PERF: This is a bit twiddling hack. Given that bitwise xoring 2 values flag the bits difference,
            //       we can use that we know we are running on little endian hardware and the very first bit set
            //       will correspond to the first byte which is different.

            bpx += Bits.TrailingZeroesInBytes(xor);
            return(*bpx - *(bpx + offset));

UnmanagedCompare:
            return(PlatformDetails.RunningOnPosix
                ? Syscall.Compare((byte *)p1, (byte *)p2, size)
                : Win32UnmanagedMemory.Compare((byte *)p1, (byte *)p2, size));
        }
Example #6
0
 public static IntPtr Copy(byte *dest, byte *src, int count)
 {
     return(Platform.RunningOnPosix
         ? PosixUnmanagedMemory.Copy(dest, src, count)
         : Win32UnmanagedMemory.Copy(dest, src, count));
 }
Example #7
0
 public static IntPtr Set(byte *dest, int c, int count)
 {
     return(Platform.RunningOnPosix
         ? PosixUnmanagedMemory.Set(dest, c, count)
         : Win32UnmanagedMemory.Set(dest, c, count));
 }
Example #8
0
 public static int Move(byte *b1, byte *b2, int count)
 {
     return(Platform.RunningOnPosix
         ? PosixUnmanagedMemory.Move(b1, b2, count)
         : Win32UnmanagedMemory.Move(b1, b2, count));
 }