Beispiel #1
0
        static public /*internal*/ unsafe object CheckCastArray(Object obj, void *pvTargetEEType)
        {
            // a null value can be cast to anything
            if (obj == null)
            {
                return(null);
            }

            object result = IsInstanceOfArray(obj, pvTargetEEType);

            if (result == null)
            {
                // Throw the invalid cast exception defined by the classlib, using the input EEType*
                // to find the correct classlib.

                ExceptionIDs exID = ExceptionIDs.InvalidCast;

                IntPtr    addr = ((EEType *)pvTargetEEType)->GetAssociatedModuleAddress();
                Exception e    = EH.GetClasslibException(exID, addr);

                BinderIntrinsics.TailCall_RhpThrowEx(e);
            }

            return(result);
        }
Beispiel #2
0
        static public unsafe void *LdelemaRef(Object array, int index, IntPtr elementType)
        {
            Debug.Assert(array.EEType->IsArray, "second argument must be an array");

            EEType *elemType      = (EEType *)elementType;
            EEType *arrayElemType = array.EEType->RelatedParameterType;

            if (!AreTypesEquivalentInternal(elemType, arrayElemType))
            {
                // Throw the array type mismatch exception defined by the classlib, using the input array's EEType*
                // to find the correct classlib.

                IntPtr    addr = array.EEType->GetAssociatedModuleAddress();
                Exception e    = EH.GetClasslibException(ExceptionIDs.ArrayTypeMismatch, addr);

                BinderIntrinsics.TailCall_RhpThrowEx(e);
            }

            fixed(void *pArray = &array.m_pEEType)
            {
                // CORERT-TODO: This code has GC hole - the method return type should really be byref.
                // Requires byref returns in C# to fix cleanly (https://github.com/dotnet/roslyn/issues/118)
                return((IntPtr *)pArray + ArrayBaseIndex + index);
            }
        }
Beispiel #3
0
        static public unsafe void CheckVectorElemAddr(void *pvElemType, object array)
        {
            if (array == null)
            {
                return;
            }

            Debug.Assert(array.EEType->IsArray, "second argument must be an array");

            EEType *elemType      = (EEType *)pvElemType;
            EEType *arrayElemType = array.EEType->RelatedParameterType;

            if (!AreTypesEquivalentInternal(elemType, arrayElemType)
                // In addition to the exactness check, add another check to allow non-exact matches through
                // if the element type is a ValueType. The issue here is Universal Generics. The Universal
                // Generic codegen will generate a call to this helper for all ldelema opcodes if the exact
                // type is not known, and this can include ValueTypes. For ValueTypes, the exact check is not
                // desireable as enum's are allowed to pass through this code if they are size matched.
                // While this check is overly broad and allows non-enum valuetypes to also skip the check
                // that is OK, because in the non-enum case the casting operations are sufficient to ensure
                // type safety.
                && !elemType->IsValueType)
            {
                // Throw the array type mismatch exception defined by the classlib, using the input array's EEType*
                // to find the correct classlib.
                ExceptionIDs exID = ExceptionIDs.ArrayTypeMismatch;

                IntPtr    addr = array.EEType->GetAssociatedModuleAddress();
                Exception e    = EH.GetClasslibException(exID, addr);

                BinderIntrinsics.TailCall_RhpThrowEx(e);
            }
        }
Beispiel #4
0
        public static void ThrowClasslibDivideByZeroException(IntPtr address)
        {
            // Throw the divide by zero exception defined by the classlib, using the return address of the asm helper
            // to find the correct classlib.

            Exception e = GetClasslibException(ExceptionIDs.DivideByZero, address);

            BinderIntrinsics.TailCall_RhpThrowEx(e);
            throw e;
        }
Beispiel #5
0
        static public unsafe void StelemRef(Object array, int index, object obj)
        {
            // This is supported only on arrays
            Debug.Assert(array.EEType->IsArray, "first argument must be an array");

            if (index >= array.GetArrayLength())
            {
                IntPtr    addr = array.EEType->GetAssociatedModuleAddress();
                Exception e    = EH.GetClasslibException(ExceptionIDs.IndexOutOfRange, addr);
                throw e;
            }

            if (obj != null)
            {
                EEType *arrayElemType = array.EEType->RelatedParameterType;
                bool    compatible;
                if (arrayElemType->IsInterface)
                {
                    compatible = IsInstanceOfInterface(obj, arrayElemType) != null;
                }
                else if (arrayElemType->IsArray)
                {
                    compatible = IsInstanceOfArray(obj, arrayElemType) != null;
                }
                else
                {
                    compatible = IsInstanceOfClass(obj, arrayElemType) != null;
                }

                if (!compatible)
                {
                    // Throw the array type mismatch exception defined by the classlib, using the input array's EEType*
                    // to find the correct classlib.

                    IntPtr    addr = array.EEType->GetAssociatedModuleAddress();
                    Exception e    = EH.GetClasslibException(ExceptionIDs.ArrayTypeMismatch, addr);

                    BinderIntrinsics.TailCall_RhpThrowEx(e);
                }

                // Both bounds and type check are ok.
                fixed(void *pArray = &array.m_pEEType)
                {
                    RhpAssignRef((IntPtr *)pArray + ArrayBaseIndex + index, obj);
                }
            }
            else
            {
                fixed(void *pArray = &array.m_pEEType)
                {
                    // Storing null does not require write barrier
                    *((IntPtr *)pArray + ArrayBaseIndex + index) = default(IntPtr);
                }
            }
        }
Beispiel #6
0
        public static void FailedAllocation(EETypePtr pEEType, bool fIsOverflow)
        {
            ExceptionIDs exID = fIsOverflow ? ExceptionIDs.Overflow : ExceptionIDs.OutOfMemory;

            // Throw the out of memory exception defined by the classlib, using the input EEType*
            // to find the correct classlib.

            Exception e = pEEType.ToPointer()->GetClasslibException(exID);

            BinderIntrinsics.TailCall_RhpThrowEx(e);
        }
        public static void FailedAllocation(bool fIsOverflow)
        {
            // Throw the out of memory or overflow exception defined by the classlib, using the return address from this helper
            // to find the correct classlib.

            ExceptionIDs exID = fIsOverflow ? ExceptionIDs.Overflow : ExceptionIDs.OutOfMemory;

            IntPtr    returnAddr = BinderIntrinsics.GetReturnAddress();
            Exception e          = GetClasslibException(exID, returnAddr);

            BinderIntrinsics.TailCall_RhpThrowEx(e);
        }
Beispiel #8
0
        public unsafe static void RhUnboxAny(object o, ref Hack_o_p data, EETypePtr pUnboxToEEType)
        {
            EEType *ptrUnboxToEEType = (EEType *)pUnboxToEEType.ToPointer();

            if (ptrUnboxToEEType->IsValueType)
            {
                // HACK: we would really want to take the address of o here,
                // but the rules of the C# language don't let us do that,
                // so we arrive at the same result by taking the address of p
                // and going back one pointer-sized unit
                fixed(IntPtr *pData = &data.p)
                {
                    bool isValid = false;

                    if (ptrUnboxToEEType->IsNullable)
                    {
                        isValid = (o == null) || TypeCast.AreTypesEquivalentInternal(o.EEType, ptrUnboxToEEType->GetNullableType());
                    }
                    else if (o != null)
                    {
                        isValid = UnboxAnyTypeCompare(o.EEType, ptrUnboxToEEType);
                    }

                    if (!isValid)
                    {
                        // Throw the invalid cast exception defined by the classlib, using the input unbox EEType*
                        // to find the correct classlib.

                        ExceptionIDs exID = o == null ? ExceptionIDs.NullReference : ExceptionIDs.InvalidCast;

                        IntPtr    addr = ptrUnboxToEEType->GetAssociatedModuleAddress();
                        Exception e    = EH.GetClasslibException(exID, addr);

                        BinderIntrinsics.TailCall_RhpThrowEx(e);
                    }
                    InternalCalls.RhUnbox(o, pData - 1, ptrUnboxToEEType);
                }
            }
            else
            {
                if (o == null || (TypeCast.IsInstanceOf(o, ptrUnboxToEEType) != null))
                {
                    data.o = o;
                }
                else
                {
                    IntPtr    addr = ptrUnboxToEEType->GetAssociatedModuleAddress();
                    Exception e    = EH.GetClasslibException(ExceptionIDs.InvalidCast, addr);

                    BinderIntrinsics.TailCall_RhpThrowEx(e);
                }
            }
        }
        public static void ThrowClasslibArithmeticException()
        {
            // Throw the arithmetic exception defined by the classlib, using the return address from this
            // helper to find the correct classlib.

            ExceptionIDs exID = ExceptionIDs.Arithmetic;

            IntPtr    returnAddr = BinderIntrinsics.GetReturnAddress();
            Exception e          = GetClasslibException(exID, returnAddr);

            BinderIntrinsics.TailCall_RhpThrowEx(e);
            throw e;
        }
Beispiel #10
0
        public static void ThrowClasslibIndexOutOfRangeException()
        {
            // Throw the index out of range exception defined by the classlib, using the return address from
            // this helper to find the correct classlib.

            ExceptionIDs exID = ExceptionIDs.IndexOutOfRange;

            IntPtr    returnAddr = BinderIntrinsics.GetReturnAddress();
            Exception e          = GetClasslibException(exID, returnAddr);

            BinderIntrinsics.TailCall_RhpThrowEx(e);
            throw e;
        }
Beispiel #11
0
        public static void FailedAllocation(EETypePtr pEEType, bool fIsOverflow)
        {
            // Throw the out of memory or overflow exception defined by the classlib, using the return address from this helper
            // to find the correct classlib.

            ExceptionIDs exID = fIsOverflow ? ExceptionIDs.Overflow : ExceptionIDs.OutOfMemory;

            // Throw the out of memory exception defined by the classlib, using the input EEType*
            // to find the correct classlib.
            IntPtr    addr = pEEType.ToPointer()->GetAssociatedModuleAddress();
            Exception e    = GetClasslibException(exID, addr);

            BinderIntrinsics.TailCall_RhpThrowEx(e);
        }
Beispiel #12
0
        static public /*internal*/ unsafe object CheckCastInterface(Object obj, void *pvTargetEEType)
        {
            // a null value can be cast to anything
            if (obj == null)
            {
                return(null);
            }

            EEType *pTargetType = (EEType *)pvTargetEEType;
            EEType *pObjType    = obj.EEType;

            if (ImplementsInterface(pObjType, pTargetType))
            {
                return(obj);
            }

            Exception castError = null;

            // If object type implements ICastable then there's one more way to check whether it implements
            // the interface.
            if (pObjType->IsICastable)
            {
                // Call the ICastable.IsInstanceOfInterface method directly rather than via an interface
                // dispatch since we know the method address statically.
                IntPtr pfnIsInstanceOfInterface = pObjType->ICastableIsInstanceOfInterfaceMethod;
                if (CalliIntrinsics.Call <bool>(pfnIsInstanceOfInterface, obj, pTargetType, out castError))
                {
                    return(obj);
                }
            }

            // Throw the invalid cast exception defined by the classlib, using the input EEType* to find the
            // correct classlib unless ICastable.IsInstanceOfInterface returned a more specific exception for
            // us to use.

            IntPtr addr = ((EEType *)pvTargetEEType)->GetAssociatedModuleAddress();

            if (castError == null)
            {
                castError = EH.GetClasslibException(ExceptionIDs.InvalidCast, addr);
            }

            BinderIntrinsics.TailCall_RhpThrowEx(castError);
            throw castError;
        }
Beispiel #13
0
        static public unsafe void RhUnboxNullable(ref Hack_o_p data, EETypePtr pUnboxToEEType, Object obj)
        {
            EEType *ptrUnboxToEEType = (EEType *)pUnboxToEEType.ToPointer();

            // HACK: we would really want to take the address of o here,
            // but the rules of the C# language don't let us do that,
            // so we arrive at the same result by taking the address of p
            // and going back one pointer-sized unit
            fixed(IntPtr *pData = &data.p)
            {
                if ((obj != null) && (obj.EEType != ptrUnboxToEEType->GetNullableType()))
                {
                    Exception e = ptrUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast);

                    BinderIntrinsics.TailCall_RhpThrowEx(e);
                }
                InternalCalls.RhUnbox(obj, pData - 1, ptrUnboxToEEType);
            }
        }
Beispiel #14
0
        static public unsafe void *RhUnbox2(EETypePtr pUnboxToEEType, Object obj)
        {
            EEType *ptrUnboxToEEType = (EEType *)pUnboxToEEType.ToPointer();

            if (obj.EEType != ptrUnboxToEEType)
            {
                // We allow enums and their primtive type to be interchangable
                if (obj.EEType->CorElementType != ptrUnboxToEEType->CorElementType)
                {
                    Exception e = ptrUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast);

                    BinderIntrinsics.TailCall_RhpThrowEx(e);
                }
            }

            fixed(void *pObject = &obj.m_pEEType)
            {
                // CORERT-TODO: This code has GC hole - the method return type should really be byref.
                // Requires byref returns in C# to fix cleanly (https://github.com/dotnet/roslyn/issues/118)
                return((IntPtr *)pObject + 1);
            }
        }
Beispiel #15
0
        static public /*internal*/ unsafe void CheckUnbox(Object obj, byte expectedCorElementType)
        {
            if (obj == null)
            {
                return;
            }

            if (obj.EEType->CorElementType == (CorElementType)expectedCorElementType)
            {
                return;
            }

            // Throw the invalid cast exception defined by the classlib, using the input object's EEType*
            // to find the correct classlib.

            ExceptionIDs exID = ExceptionIDs.InvalidCast;

            IntPtr    addr = obj.EEType->GetAssociatedModuleAddress();
            Exception e    = EH.GetClasslibException(exID, addr);

            BinderIntrinsics.TailCall_RhpThrowEx(e);
        }
Beispiel #16
0
        static public /*internal*/ unsafe void CheckArrayStore(object array, object obj)
        {
            if (array == null || obj == null)
            {
                return;
            }

            Debug.Assert(array.EEType->IsArray, "first argument must be an array");

            EEType *arrayElemType = array.EEType->RelatedParameterType;
            bool    compatible;

            if (arrayElemType->IsInterface)
            {
                compatible = IsInstanceOfInterface(obj, arrayElemType) != null;
            }
            else if (arrayElemType->IsArray)
            {
                compatible = IsInstanceOfArray(obj, arrayElemType) != null;
            }
            else
            {
                compatible = IsInstanceOfClass(obj, arrayElemType) != null;
            }

            if (!compatible)
            {
                // Throw the array type mismatch exception defined by the classlib, using the input array's EEType*
                // to find the correct classlib.

                ExceptionIDs exID = ExceptionIDs.ArrayTypeMismatch;

                IntPtr    addr = array.EEType->GetAssociatedModuleAddress();
                Exception e    = EH.GetClasslibException(exID, addr);

                BinderIntrinsics.TailCall_RhpThrowEx(e);
            }
        }
Beispiel #17
0
        static public /*internal*/ unsafe void CheckVectorElemAddr(void *pvElemType, object array)
        {
            if (array == null)
            {
                return;
            }

            Debug.Assert(array.EEType->IsArray, "second argument must be an array");

            EEType *elemType      = (EEType *)pvElemType;
            EEType *arrayElemType = array.EEType->RelatedParameterType;

            if (!AreTypesEquivalentInternal(elemType, arrayElemType))
            {
                // Throw the array type mismatch exception defined by the classlib, using the input array's EEType*
                // to find the correct classlib.
                ExceptionIDs exID = ExceptionIDs.ArrayTypeMismatch;

                IntPtr    addr = array.EEType->GetAssociatedModuleAddress();
                Exception e    = EH.GetClasslibException(exID, addr);

                BinderIntrinsics.TailCall_RhpThrowEx(e);
            }
        }