Ejemplo n.º 1
0
        static unsafe bool BlockCopyInternal(byte *src, int srcOffset, byte *dest, int destOffset,
                                             int count)
        {
            /* Return false on overflow within src or dest */
            int srcElemSize = *(int *)(src + ArrayOperations.GetElemSizeOffset());
            //int srcIALength = *(int*)(src + ArrayOperations.GetInnerArrayLengthOffset());
            int srcIALength = 0;

            throw new NotImplementedException();
            int srcByteSize = srcElemSize * srcIALength;

            if ((srcOffset + count) > srcByteSize)
            {
                return(false);
            }

            int destElemSize = *(int *)(dest + ArrayOperations.GetElemSizeOffset());
            //int destIALength = *(int*)(dest + ArrayOperations.GetInnerArrayLengthOffset());
            int destIALength = 0;
            int destByteSize = destElemSize * destIALength;

            if ((destOffset + count) > destByteSize)
            {
                return(false);
            }

            /* Get source and dest addresses */
            byte *srcAddr  = *(byte **)(src + ArrayOperations.GetInnerArrayOffset()) + srcOffset;
            byte *destAddr = *(byte **)(dest + ArrayOperations.GetInnerArrayOffset()) + destOffset;

            /* Execute a memmove */
            MemoryOperations.MemMove((void *)destAddr, (void *)srcAddr, count);

            return(true);
        }
Ejemplo n.º 2
0
        static void push_ehdr(void *eh, void *fp)
        {
            if (start == null)
            {
                void **new_start = (void **)MemoryOperations.GcMalloc(stack_length * sizeof(void *));

                fixed(void ***start_addr = &start)
                {
                    if (OtherOperations.CompareExchange((void **)start_addr, (void *)new_start) == null)
                    {
                        end = start + stack_length;
                        cur = start;
                        System.Diagnostics.Debugger.Log(0, "libsupcs", "new ehdr stack at " + ((ulong)start).ToString("X") + "-" + ((ulong)end).ToString("X"));
                    }
                }
            }

            if ((cur + 1) >= end)
            {
                System.Diagnostics.Debugger.Break();
                throw new OutOfMemoryException("exception header stack overflowed");
            }

            //if(System.Threading.Thread.CurrentThread.ManagedThreadId != 1)
            //    System.Diagnostics.Debugger.Log(0, "libsupcs", "exceptions: push_ehdr: " + ((ulong)eh).ToString("X"));

            // the following should be atomic for the current stack only, so disabling interrupts is
            //  sufficient
            var state = OtherOperations.EnterUninterruptibleSection();

            *cur++ = eh;
            *cur++ = fp;
            OtherOperations.ExitUninterruptibleSection(state);
        }
Ejemplo n.º 3
0
        static unsafe bool InternalStrcpy(byte *dest, int destPos, byte *src, int srcPos, int count)
        {
            /* Get size of src and dest */
            int srcLength  = *(int *)(src + StringOperations.GetLengthOffset());
            int destLength = *(int *)(dest + StringOperations.GetLengthOffset());

            /* Ensure the source and destination are big enough */
            if (destPos < 0)
            {
                return(false);
            }
            if (srcPos < 0)
            {
                return(false);
            }
            if (count < 0)
            {
                return(false);
            }
            if (destPos + count > destLength)
            {
                return(false);
            }
            if (srcPos + count > srcLength)
            {
                return(false);
            }

            /* Do the copy */
            MemoryOperations.MemCpy((void *)(dest + StringOperations.GetDataOffset() + destPos * 2),
                                    (void *)(src + StringOperations.GetDataOffset() + srcPos * 2), count * 2);

            return(true);
        }
Ejemplo n.º 4
0
        static unsafe object to_object(TysosType enum_type, object value)
        {
            /* Convert value (of an integral type) to an enum of type 'enum_type'
             * and return its boxed value
             */

            if (enum_type == null)
            {
                throw new ArgumentNullException("enumType");
            }
            if (value == null)
            {
                throw new ArgumentException("value");
            }

            /* The incoming value type 'value' is already boxed.
             *
             * We can therefore just copy its data to a new enum object
             */

            void *value_obj   = CastOperations.ReinterpretAsPointer(value);
            void *value_vtbl  = *(void **)value_obj;
            int   value_csize = *(int *)((byte *)value_vtbl + ClassOperations.GetVtblTypeSizeOffset());

            void *ret_obj = MemoryOperations.GcMalloc(value_csize);

            MemoryOperations.MemCpy(ret_obj, value_obj, value_csize);

            void *ret_vtbl = *(void **)((byte *)CastOperations.ReinterpretAsPointer(enum_type) + ClassOperations.GetSystemTypeImplOffset());

            *(void **)ret_obj = ret_vtbl;
            *(void **)((byte *)ret_obj + ClassOperations.GetMutexLockOffset()) = null;

            return(CastOperations.ReinterpretAsObject(ret_obj));
        }
Ejemplo n.º 5
0
        static unsafe void *InternalToObject(void *typedref)
        {
            // get the type from the typed reference to see if we need to box the object
            //  or simply return the address as a reference type

            void *et  = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceTypeOffset());
            void *src = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceValueOffset());

            void *etextends = *(void **)((byte *)et + ClassOperations.GetVtblExtendsVtblPtrOffset());

            if (etextends == OtherOperations.GetStaticObjectAddress("_Zu1L") ||
                etextends == OtherOperations.GetStaticObjectAddress("_ZW6System4Enum"))
            {
                // this is a boxed value type.  Get its size
                var vt_size = TysosType.GetValueTypeSize(et);

                // build a new boxed type
                var ret = MemoryOperations.GcMalloc(*(int *)((byte *)et + ClassOperations.GetVtblTypeSizeOffset()));

                // dst ptr
                var dst = (byte *)ret + ClassOperations.GetBoxedTypeDataOffset();

                CopyMem(dst, (byte *)src, vt_size);

                return(ret);
            }
            else
            {
                // simply copy the reference
                return(*(void **)src);
            }
        }
Ejemplo n.º 6
0
        static unsafe void InitializeArray(void *arr, void *fld_handle)
        {
            System.Diagnostics.Debugger.Log(0, "libsupcs", "InitializeArray: arr: " + ((ulong)arr).ToString("X16") + ", fld_handle: " + ((ulong)fld_handle).ToString("X16"));
            void *dst = *(void **)((byte *)arr + ArrayOperations.GetInnerArrayOffset());

            /* Get total number of elements, and hence data size */
            int *sizes = *(int **)((byte *)arr + ArrayOperations.GetSizesOffset());
            int  rank  = *(int *)((byte *)arr + ArrayOperations.GetRankOffset());

            if (rank == 0)
            {
                return;
            }

            int size = sizes[0];

            for (int i = 1; i < rank; i++)
            {
                size *= sizes[i];
            }

            int len = size * *(int *)((byte *)arr + ArrayOperations.GetElemSizeOffset());

            /* Field Typeinfos hava a pointer to the stored data as their third element */
            void *src = ((void **)fld_handle)[2];

            System.Diagnostics.Debugger.Log(0, "libsupcs", "InitializeArray: src: " + ((ulong)src).ToString("X16") +
                                            ", dest: " + ((ulong)dst).ToString("X16") + ", len: " + len.ToString());

            MemoryOperations.MemCpy(dst, src, len);
        }
Ejemplo n.º 7
0
        public static void *InternalInvoke(void *mptr, object[] args, void *rtype, uint flags)
        {
            int p_length = (args == null) ? 0 : args.Length;

            // See InternalStrCpy for the rationale here
            int     max_stack_alloc = p_length > 512 ? 512 : p_length;
            IntPtr *pstack          = stackalloc IntPtr[max_stack_alloc];
            IntPtr *tstack          = stackalloc IntPtr[max_stack_alloc];

            void **ps, ts;

            if (max_stack_alloc <= 512)
            {
                ps = (void **)pstack;
                ts = (void **)tstack;
            }
            else
            {
                ps = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *));
                ts = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *));
            }

            // Build a new params array and a tysos type array
            if (args != null)
            {
                for (int i = 0; i < args.Length; i++)
                {
                    var cp = CastOperations.ReinterpretAsPointer(args[i]);
                    ps[i] = cp;
                    ts[i] = *(void **)cp;
                }
            }

            return(InternalInvoke(mptr, args.Length, ps, ts, rtype, flags));
        }
Ejemplo n.º 8
0
        static unsafe void StringCtor(byte *str, char[] srcArr)
        {
            void *src = MemoryOperations.GetInternalArray(srcArr);
            int   len = srcArr.Length * sizeof(char);
            void *dst = str + StringOperations.GetDataOffset();

            MemoryOperations.MemCpy(dst, src, len);
        }
Ejemplo n.º 9
0
        static unsafe void StringCtor(byte *str, char[] srcArr, int startIndex, int length)
        {
            void *src = (byte *)MemoryOperations.GetInternalArray(srcArr) + sizeof(char) * startIndex;
            int   len = length * sizeof(char);
            void *dst = str + StringOperations.GetDataOffset();

            MemoryOperations.MemCpy(dst, src, len);
        }
Ejemplo n.º 10
0
        static unsafe void StringCtor(byte *str, char *value, int startIndex, int length)
        {
            void *src = value + startIndex;
            int   len = length * sizeof(char);
            void *dst = str + StringOperations.GetDataOffset();

            MemoryOperations.MemCpy(dst, src, len);
        }
Ejemplo n.º 11
0
        static unsafe void CopyToNative(void *srcArr, int startIndex, void *dst, int length)
        {
            var  esize  = *(int *)((byte *)srcArr + ArrayOperations.GetElemSizeOffset());
            int *lovals = *(int **)((byte *)srcArr + ArrayOperations.GetLoboundsOffset());

            var src = *(byte **)((byte *)srcArr + ArrayOperations.GetInnerArrayOffset()) + (startIndex - lovals[0]) * esize;

            MemoryOperations.MemCpy(dst, src, length * esize);
        }
Ejemplo n.º 12
0
        static unsafe void Clear(void *arr, int index, int length)
        {
            /* Get a pointer to the source data */
            var   elem_size = *(int *)((byte *)arr + ArrayOperations.GetElemSizeOffset());
            void *ia        = *(void **)((byte *)arr + ArrayOperations.GetInnerArrayOffset());
            void *sptr      = (void *)((byte *)ia + index * elem_size);

            var mem_size = length * elem_size;

            MemoryOperations.MemSet(sptr, 0, mem_size);
        }
Ejemplo n.º 13
0
        static unsafe void CopyToManaged(void *src, void *dstArr, int startIndex, int length)
        {
            var  esize  = *(int *)((byte *)dstArr + ArrayOperations.GetElemSizeOffset());
            int *lovals = *(int **)((byte *)dstArr + ArrayOperations.GetLoboundsOffset());

            var dst = *(byte **)((byte *)dstArr + ArrayOperations.GetInnerArrayOffset()) + (startIndex - lovals[0]) * esize;

            System.Diagnostics.Debugger.Log(0, null, "libsupcs: Array.CopyToManaged: src: " + ((ulong)src).ToString("X16") +
                                            ", dstArr: " + ((ulong)dstArr).ToString("X16") +
                                            ", startIndex: " + startIndex.ToString() +
                                            ", length: " + length.ToString() +
                                            ", esize: " + esize.ToString() +
                                            ", lovals[0]: " + lovals[0].ToString() +
                                            ", dst: " + ((ulong)dst).ToString("X16"));

            MemoryOperations.MemCpy(dst, src, length * esize);
        }
Ejemplo n.º 14
0
        /* Build an array of a particular type */
        public static unsafe T[] CreateSZArray <T>(int nitems, void *data_addr)
        {
            TysosType arrtt  = (TysosType)typeof(T[]);
            TysosType elemtt = (TysosType)typeof(T);

            int elemsize;

            if (elemtt.IsValueType)
            {
                elemsize = elemtt.GetClassSize() - ClassOperations.GetBoxedTypeDataOffset();
            }
            else
            {
                elemsize = OtherOperations.GetPointerSize();
            }

            if (data_addr == null)
            {
                data_addr = MemoryOperations.GcMalloc(elemsize * nitems);
            }

            byte *ret = (byte *)MemoryOperations.GcMalloc(ArrayOperations.GetArrayClassSize() + 8);     // extra space for lobounds and length array

            void *vtbl = *(void **)((byte *)CastOperations.ReinterpretAsPointer(arrtt) + ClassOperations.GetSystemTypeImplOffset());

            *(void **)(ret + ClassOperations.GetVtblFieldOffset()) = vtbl;
            *(ulong *)(ret + ClassOperations.GetMutexLockOffset()) = 0;

            *(void **)(ret + ArrayOperations.GetElemTypeOffset())   = *(void **)((byte *)CastOperations.ReinterpretAsPointer(elemtt) + ClassOperations.GetSystemTypeImplOffset());
            *(int *)(ret + ArrayOperations.GetElemSizeOffset())     = elemsize;
            *(void **)(ret + ArrayOperations.GetInnerArrayOffset()) = data_addr;
            *(void **)(ret + ArrayOperations.GetLoboundsOffset())   = ret + ArrayOperations.GetArrayClassSize();
            *(void **)(ret + ArrayOperations.GetSizesOffset())      = ret + ArrayOperations.GetArrayClassSize() + 4;
            *(int *)(ret + ArrayOperations.GetRankOffset())         = 1;
            *(int *)(ret + ArrayOperations.GetArrayClassSize())     = 0;      // lobounds[0]
            *(int *)(ret + ArrayOperations.GetArrayClassSize() + 4) = nitems; // sizes[0]

            return((T[])CastOperations.ReinterpretAsObject(ret));
        }
Ejemplo n.º 15
0
        static unsafe void *get_value(void *obj)
        {
            /* we can copy the entire enum object to an instance
             * of the underlying type and just change the
             * vtbl
             */

            byte *enum_vtbl = *(byte **)obj;
            int   enum_size = *(int *)(enum_vtbl + ClassOperations.GetVtblTypeSizeOffset());

            void **enum_ti = *(void ***)enum_vtbl;
            void * ut_vtbl = *(enum_ti + 1);

            void *new_obj = MemoryOperations.GcMalloc(enum_size);

            MemoryOperations.MemCpy(new_obj, obj, enum_size);

            *(void **)new_obj = ut_vtbl;
            *(void **)((byte *)new_obj + ClassOperations.GetMutexLockOffset()) = null;

            return(new_obj);
        }
Ejemplo n.º 16
0
        public override object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture)
        {
            uint flags = 0;

            if (MethodAddress == null)
            {
                var mangled_name = mspec.MangleMethod();
                System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: requesting run-time address for " + mangled_name);
                MethodAddress = JitOperations.GetAddressOfObject(mspec.MangleMethod());
                if (MethodAddress == null)
                {
                    System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: jit compiling method");
                    MethodAddress = JitOperations.JitCompile(this.mspec);
                }
            }
            if (MethodAddress == null)
            {
                throw new System.Reflection.TargetException("Method does not have a defined implementation (" + OwningType.FullName + "." + Name + "())");
            }
            if (!IsStatic && (obj == null))
            {
                throw new System.Reflection.TargetException("Instance method and obj is null (" + OwningType.FullName + "." + Name + "())");
            }

            // TODO: check number and type of parameters is what the method expects

            // Get total number of parameters
            int p_length = 0;

            if (parameters != null)
            {
                p_length = parameters.Length;
            }
            if (!IsStatic)
            {
                p_length++;
            }

            // See InternalStrCpy for the rationale here
            int     max_stack_alloc = p_length > 512 ? 512 : p_length;
            IntPtr *pstack          = stackalloc IntPtr[max_stack_alloc];
            IntPtr *tstack          = stackalloc IntPtr[max_stack_alloc];

            void **ps, ts;

            if (max_stack_alloc <= 512)
            {
                ps = (void **)pstack;
                ts = (void **)tstack;
            }
            else
            {
                ps = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *));
                ts = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *));
            }

            // Build a new params array to include obj if necessary, and a tysos type array
            int curptr = 0;

            if (!IsStatic)
            {
                ps[0] = CastOperations.ReinterpretAsPointer(obj);
                ts[0] = OtherOperations.GetStaticObjectAddress("_Zu1O");
                curptr++;
            }
            if (parameters != null)
            {
                for (int i = 0; i < parameters.Length; i++, curptr++)
                {
                    var cp = CastOperations.ReinterpretAsPointer(parameters[i]);
                    ps[curptr] = cp;
                    ts[curptr] = *(void **)cp;
                }
            }

            if (!IsStatic)
            {
                flags |= invoke_flag_instance;
            }
            if (OwningType.IsValueType)
            {
                flags |= invoke_flag_vt;
            }
            if (ReturnType != null && ReturnType.IsValueType)
            {
                flags |= invoke_flag_vt_ret;
            }

            return(CastOperations.ReinterpretAsObject(InternalInvoke(MethodAddress, p_length, ps, ts,
                                                                     (ReturnType != null) ? TysosType.ReinterpretAsType(ReturnType)._impl : null, flags)));
        }
Ejemplo n.º 17
0
        static unsafe string InternalReplace(string str, string old_value, string new_value)
        {
            /* maximum size of new string is str if new_value <= old_value or
             * if new_value is larger then assume str is made up of all old_value
             * in which case it is this count * new_value + remainder (or count + 1 * new_value)
             */

            int max_new_str;

            if (new_value.Length > old_value.Length)
            {
                max_new_str = ((str.Length / old_value.Length) + 1) * new_value.Length;
            }
            else
            {
                max_new_str = str.Length;
            }

            //System.Diagnostics.Debugger.Log(0, "libsupcs", "InternalReplace: str: " + str + ", old_value: " + old_value +
            //    ", new_value: " + new_value + ", max_new_str: " + max_new_str.ToString());

            /* limit stack alloc to 1024 chars to reduce risk of stack overflows.  Implementations
             *  should have a stack guard page anyway to catch overflows of this size whilst larger
             *  stack allocs could be used to introduce code beyond the guard page.
             *
             *  We do it this way because C# does not support conditional stack alloc assigns
             */
            int   max_stack_new_str = max_new_str > 1024 ? 1024 : max_new_str;
            char *nstack            = stackalloc char[max_stack_new_str];

            char *ns;

            if (max_new_str <= 1024)
            {
                ns = nstack;
            }
            else
            {
                ns = (char *)MemoryOperations.GcMalloc(max_new_str * sizeof(char));
            }
            char *ptr = ns;

            for (int i = 0; i < str.Length; i++)
            {
                bool found = true;
                for (int j = 0; j < old_value.Length; j++)
                {
                    if (((i + j) >= str.Length) || (str[i + j] != old_value[j]))
                    {
                        found = false;
                        break;
                    }
                }

                if (found)
                {
                    for (int j = 0; j < new_value.Length; j++)
                    {
                        *ptr++ = new_value[j];
                    }
                    i += old_value.Length;
                    i--;        // the for loop adds a 1 for us
                }
                else
                {
                    *ptr++ = str[i];
                }
            }

            var str_len = ptr - ns;

            //var ret = new string(ns, 0, (int)str_len);
            //System.Diagnostics.Debugger.Log(0, "libsupcs", "InternalReplace: ret: " + ret);
            //return ret;
            return(new string(ns, 0, (int)str_len));
        }
Ejemplo n.º 18
0
        static unsafe void Copy(void *srcArr, int srcIndex, void *dstArr, int dstIndex, int length,
                                bool reliable)
        {
            /* Ensure arrays are valid */
            if (srcArr == null || dstArr == null)
            {
                throw new ArgumentNullException();
            }

            /* Ensure length is valid */
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            /* Ensure both arrays are of the same rank */
            var srcRank = *(int *)((byte *)srcArr + ArrayOperations.GetRankOffset());
            var dstRank = *(int *)((byte *)dstArr + ArrayOperations.GetRankOffset());

            if (srcRank != dstRank)
            {
                throw new RankException();
            }

            /* Get source and dest element types */
            var srcET = *(void **)((byte *)srcArr + ArrayOperations.GetElemTypeOffset());
            var dstET = *(void **)((byte *)dstArr + ArrayOperations.GetElemTypeOffset());

            /* See if we can do a quick copy */
            bool can_quick_copy = false;

            if (srcET == dstET)
            {
                can_quick_copy = true;
            }
            else if (TysosType.CanCast(srcET, dstET))
            {
                can_quick_copy = true;
            }
            else if (reliable)
            {
                throw new ArrayTypeMismatchException();   /* ConstrainedCopy requires types to be the same or derived */
            }
            else
            {
                can_quick_copy = false;
            }

            /* For now we don't handle arrays with lobounds != 0 */
            var srcLobounds = *(int **)((byte *)srcArr + ArrayOperations.GetLoboundsOffset());
            var dstLobounds = *(int **)((byte *)dstArr + ArrayOperations.GetLoboundsOffset());

            for (int i = 0; i < srcRank; i++)
            {
                if (srcLobounds[i] != 0)
                {
                    throw new NotImplementedException("srcLobounds != 0");
                }
                if (dstLobounds[i] != 0)
                {
                    throw new NotImplementedException("dstLobounds != 0");
                }
            }
            if (srcIndex < 0 || dstIndex < 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            /* Ensure we don't overflow */
            var src_len = GetLength(srcArr);
            var dst_len = GetLength(dstArr);

            if (srcIndex + length > src_len)
            {
                System.Diagnostics.Debugger.Log(0, "libsupcs", "Array.Copy srcIndex/length out of range");
                System.Diagnostics.Debugger.Log(length, "libsupcs", "length");
                System.Diagnostics.Debugger.Log(srcIndex, "libsupcs", "srcIndex");
                System.Diagnostics.Debugger.Log(src_len, "libsupcs", "src_len");
                throw new ArgumentOutOfRangeException();
            }
            if (dstIndex + length > dst_len)
            {
                System.Diagnostics.Debugger.Log(0, "libsupcs", "Array.Copy dstIndex/length out of range");
                System.Diagnostics.Debugger.Log(length, "libsupcs", "length");
                System.Diagnostics.Debugger.Log(dstIndex, "libsupcs", "dstIndex");
                System.Diagnostics.Debugger.Log(dst_len, "libsupcs", "dst_len");
                throw new ArgumentOutOfRangeException();
            }

            if (can_quick_copy)
            {
                /* Elem size of both arrays is guaranteed to be the same and we can do a shallow copy */
                var e_size = *(int *)((byte *)srcArr + ArrayOperations.GetElemSizeOffset());

                var src_ia = *(byte **)((byte *)srcArr + ArrayOperations.GetInnerArrayOffset());
                var dst_ia = *(byte **)((byte *)dstArr + ArrayOperations.GetInnerArrayOffset());

                MemoryOperations.MemMove(dst_ia + dstIndex * e_size, src_ia + srcIndex * e_size, length * e_size);
            }
            else
            {
                /* TODO: implement as per System.Array.Copy() semantics */
                throw new NotImplementedException("Cannot quick copy " + ((ulong)srcET).ToString("X") +
                                                  " to " + ((ulong)dstET).ToString("X"));
            }
        }
Ejemplo n.º 19
0
        static unsafe void *GetValueImpl(void *arr, int pos)
        {
            /* Get the element type of the array */
            void *et = *(void **)((byte *)arr + ArrayOperations.GetElemTypeOffset());

            /* Get a pointer to the source data */
            var   elem_size = *(int *)((byte *)arr + ArrayOperations.GetElemSizeOffset());
            void *ia        = *(void **)((byte *)arr + ArrayOperations.GetInnerArrayOffset());
            void *sptr      = (void *)((byte *)ia + pos * elem_size);

            /* Is this a value type? In which case we need to return a boxed value */
            void *extends = *(void **)((byte *)et + ClassOperations.GetVtblExtendsVtblPtrOffset());

            if (extends == OtherOperations.GetStaticObjectAddress("_Zu1L") ||
                extends == OtherOperations.GetStaticObjectAddress("_ZW6System4Enum"))
            {
                /* This is a value type.  We need to read the size of the element,
                 * create a new object of the appropriate size and copy the data
                 * into it */
                byte *ret = (byte *)MemoryOperations.GcMalloc(elem_size + ClassOperations.GetBoxedTypeDataOffset());
                *(void **)(ret + ClassOperations.GetVtblFieldOffset()) = et;
                *(ulong *)(ret + ClassOperations.GetMutexLockOffset()) = 0;

                /* Avoid calls to memcpy if possible */
                switch (elem_size)
                {
                case 1:
                    *(byte *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(byte *)sptr;
                    return(ret);

                case 2:
                    *(ushort *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(ushort *)sptr;
                    return(ret);

                case 4:
                    *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(uint *)sptr;
                    return(ret);

                case 8:
                    if (OtherOperations.GetPointerSize() >= 8)
                    {
                        *(ulong *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(ulong *)sptr;
                        return(ret);
                    }
                    else
                    {
                        *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset())     = *(uint *)sptr;
                        *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 4) = *(uint *)((byte *)sptr + 4);
                        return(ret);
                    }

                case 16:
                    if (OtherOperations.GetPointerSize() >= 8)
                    {
                        *(ulong *)(ret + ClassOperations.GetBoxedTypeDataOffset())     = *(ulong *)sptr;
                        *(ulong *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 8) = *(ulong *)((byte *)sptr + 8);
                        return(ret);
                    }
                    else
                    {
                        *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset())      = *(uint *)sptr;
                        *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 4)  = *(uint *)((byte *)sptr + 4);
                        *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 8)  = *(uint *)((byte *)sptr + 8);
                        *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 12) = *(uint *)((byte *)sptr + 12);
                        return(ret);
                    }
                }

                /* Do data copy via memcpy */
                MemoryOperations.MemCpy(ret + ClassOperations.GetBoxedTypeDataOffset(),
                                        sptr, elem_size);
                return(ret);
            }
            else
            {
                /* Its a reference type, so just return the pointer */
                return(*(void **)sptr);
            }
        }
Ejemplo n.º 20
0
        static unsafe bool FastCopy(void *srcArr, int srcIndex, void *dstArr, int dstIndex, int length)
        {
            /* This is often called with length == 0 when the
             * first item is added to a List<T> as the default
             * array within the list has length 0.
             */

            if (length == 0)
            {
                return(true);
            }

            // Ensure both arrays are of rank 1
            int srcRank = *(int *)((byte *)srcArr + ArrayOperations.GetRankOffset());
            int dstRank = *(int *)((byte *)dstArr + ArrayOperations.GetRankOffset());

            if (srcRank != 1)
            {
                return(false);
            }
            if (dstRank != 1)
            {
                return(false);
            }

            // Ensure srcIndex is valid
            int srcLobound = **(int **)((byte *)srcArr + ArrayOperations.GetLoboundsOffset());
            int srcSize    = **(int **)((byte *)srcArr + ArrayOperations.GetSizesOffset());

            srcIndex -= srcLobound;
            if (srcIndex + length > srcSize)
            {
                return(false);
            }

            // Ensure destIndex is valid
            int dstLobound = **(int **)((byte *)dstArr + ArrayOperations.GetLoboundsOffset());
            int dstSize    = **(int **)((byte *)dstArr + ArrayOperations.GetSizesOffset());

            dstIndex -= dstLobound;
            if (dstIndex + length > dstSize)
            {
                return(false);
            }

            // Ensure both have same element type
            void *srcET = *(void **)((byte *)srcArr + ArrayOperations.GetElemTypeOffset());
            void *dstET = *(void **)((byte *)dstArr + ArrayOperations.GetElemTypeOffset());

            if (srcET != dstET)
            {
                return(false);
            }

            // Get element size
            int elemSize = *(int *)((byte *)srcArr + ArrayOperations.GetElemSizeOffset());

            srcIndex *= elemSize;
            dstIndex *= elemSize;

            byte *srcAddr = *(byte **)((byte *)srcArr + ArrayOperations.GetInnerArrayOffset()) + srcIndex;
            byte *dstAddr = *(byte **)((byte *)dstArr + ArrayOperations.GetInnerArrayOffset()) + dstIndex;

            length *= elemSize;

            MemoryOperations.MemMove(dstAddr, srcAddr, length);

            return(true);
        }