Example #1
0
        private static unsafe void InitializeStatics(IntPtr gcStaticRegionStart, int length)
        {
            IntPtr gcStaticRegionEnd = (IntPtr)((byte *)gcStaticRegionStart + length);

            for (IntPtr *block = (IntPtr *)gcStaticRegionStart; block < (IntPtr *)gcStaticRegionEnd; block++)
            {
                // Gc Static regions can be shared by modules linked together during compilation. To ensure each
                // is initialized once, the static region pointer is stored with lowest bit set in the image.
                // The first time we initialize the static region its pointer is replaced with an object reference
                // whose lowest bit is no longer set.
                IntPtr *pBlock    = (IntPtr *)*block;
                long    blockAddr = (*pBlock).ToInt64();
                if ((blockAddr & GCStaticRegionConstants.Uninitialized) == GCStaticRegionConstants.Uninitialized)
                {
                    object obj = RuntimeImports.RhNewObject(new EETypePtr(new IntPtr(blockAddr & ~GCStaticRegionConstants.Mask)));

                    if ((blockAddr & GCStaticRegionConstants.HasPreInitializedData) == GCStaticRegionConstants.HasPreInitializedData)
                    {
                        // The next pointer is preinitialized data blob that contains preinitialized static GC fields,
                        // which are pointer relocs to GC objects in frozen segment.
                        // It actually has all GC fields including non-preinitialized fields and we simply copy over the
                        // entire blob to this object, overwriting everything.
                        IntPtr pPreInitDataAddr = *(pBlock + 1);
                        RuntimeImports.RhBulkMoveWithWriteBarrier(ref obj.GetRawData(), ref *(byte *)pPreInitDataAddr, obj.GetRawDataSize());
                    }

                    *pBlock = RuntimeImports.RhHandleAlloc(obj, GCHandleType.Normal);
                }
            }
        }
Example #2
0
        internal static void Memmove <T>(ref T destination, ref T source, nuint elementCount)
        {
            if (!RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                // Blittable memmove

                Memmove(
                    ref Unsafe.As <T, byte>(ref destination),
                    ref Unsafe.As <T, byte>(ref source),
                    elementCount * (nuint)Unsafe.SizeOf <T>());
            }
            else
            {
                // Non-blittable memmove

                // Try to avoid calling RhBulkMoveWithWriteBarrier if we can get away
                // with a no-op.
                if (!Unsafe.AreSame(ref destination, ref source) && elementCount != 0)
                {
                    RuntimeImports.RhBulkMoveWithWriteBarrier(
                        ref Unsafe.As <T, byte>(ref destination),
                        ref Unsafe.As <T, byte>(ref source),
                        elementCount * (nuint)Unsafe.SizeOf <T>());
                }
            }
        }
Example #3
0
        internal static void Memmove <T>(ref T destination, ref T source, nuint elementCount)
        {
            if (!RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                // Blittable memmove
#if PROJECTN
                unsafe
                {
                    fixed(byte *pDestination = &Unsafe.As <T, byte>(ref destination), pSource = &Unsafe.As <T, byte>(ref source))
                    Memmove(pDestination, pSource, elementCount * (nuint)Unsafe.SizeOf <T>());
                }
#else
                Memmove(
                    new ByReference <byte>(ref Unsafe.As <T, byte>(ref destination)),
                    new ByReference <byte>(ref Unsafe.As <T, byte>(ref source)),
                    elementCount * (nuint)Unsafe.SizeOf <T>());
#endif
            }
            else
            {
                // Non-blittable memmove

                // Try to avoid calling RhBulkMoveWithWriteBarrier if we can get away
                // with a no-op.
                if (!Unsafe.AreSame(ref destination, ref source) && elementCount != 0)
                {
                    RuntimeImports.RhBulkMoveWithWriteBarrier(
                        ref Unsafe.As <T, byte>(ref destination),
                        ref Unsafe.As <T, byte>(ref source),
                        elementCount * (nuint)Unsafe.SizeOf <T>());
                }
            }
        }
Example #4
0
        internal static unsafe void Memmove <T>(ref T destination, ref T source, nuint elementCount)
        {
            if (!RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                // Blittable memmove

                Memmove(
                    ref Unsafe.As <T, byte>(ref destination),
                    ref Unsafe.As <T, byte>(ref source),
                    elementCount * (nuint)Unsafe.SizeOf <T>());
            }
            else
            {
                // Non-blittable memmove
                RuntimeImports.RhBulkMoveWithWriteBarrier(
                    ref Unsafe.As <T, byte>(ref destination),
                    ref Unsafe.As <T, byte>(ref source),
                    elementCount * (nuint)Unsafe.SizeOf <T>());
            }
        }
Example #5
0
        internal static unsafe void CopyTo <T>(ref T destination, ref T source, int elementsCount)
        {
            if (Unsafe.AreSame(ref destination, ref source))
            {
                return;
            }

            if (elementsCount <= 1)
            {
                if (elementsCount == 1)
                {
                    destination = source;
                }
                return;
            }

            nuint byteCount = (nuint)elementsCount * (nuint)Unsafe.SizeOf <T>();

            if (!RuntimeHelpers.IsReferenceOrContainsReferences <T>())
            {
                fixed(byte *pDestination = &Unsafe.As <T, byte>(ref destination))
                {
                    fixed(byte *pSource = &Unsafe.As <T, byte>(ref source))
                    {
                        Buffer.Memmove(pDestination, pSource, byteCount);
                    }
                }
            }
            else
            {
                RuntimeImports.RhBulkMoveWithWriteBarrier(
                    ref Unsafe.As <T, byte>(ref destination),
                    ref Unsafe.As <T, byte>(ref source),
                    byteCount);
            }
        }
Example #6
0
 // Move memory which may be on the heap which may have object references in it.
 // In general, a memcpy on the heap is unsafe, but this is able to perform the
 // correct write barrier such that the GC is not incorrectly impacted.
 public static unsafe void BulkMoveWithWriteBarrier(IntPtr dmem, IntPtr smem, int size)
 {
     RuntimeImports.RhBulkMoveWithWriteBarrier(ref *(byte *)dmem.ToPointer(), ref *(byte *)smem.ToPointer(), (uint)size);
 }
Example #7
0
 internal static void BulkMoveWithWriteBarrier(ref byte dmem, ref byte smem, nuint size)
 => RuntimeImports.RhBulkMoveWithWriteBarrier(ref dmem, ref smem, size);