예제 #1
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));
 }
예제 #2
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));
        }
예제 #3
0
 public static int Compare(byte *b1, byte *b2, int count)
 {
     return(Platform.RunningOnPosix
         ? PosixUnmanagedMemory.Compare(b1, b2, count)
         : Win32UnmanagedMemory.Compare(b1, b2, count));
 }