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); }
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); } }
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); } }
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); } } }
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); } } }
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; }
public unsafe static object RhBox(EETypePtr pEEType, void *pData) { EEType *ptrEEType = (EEType *)pEEType.ToPointer(); object result; // If we're boxing a Nullable<T> then either box the underlying T or return null (if the // nullable's value is empty). if (ptrEEType->IsNullable) { // The boolean which indicates whether the value is null comes first in the Nullable struct. if (!*(bool *)pData) { return(null); } // Switch type we're going to box to the Nullable<T> target type and advance the data pointer // to the value embedded within the nullable. pData = (byte *)pData + ptrEEType->GetNullableValueOffset(); ptrEEType = ptrEEType->GetNullableType(); } #if FEATURE_64BIT_ALIGNMENT if (ptrEEType->RequiresAlign8) { result = InternalCalls.RhpNewFastMisalign(ptrEEType); } else #endif // FEATURE_64BIT_ALIGNMENT { result = InternalCalls.RhpNewFast(ptrEEType); } if (result == null) { // Throw the out of memory exception defined by the classlib, using the input EEType* // to find the correct classlib. ExceptionIDs exID = ExceptionIDs.OutOfMemory; IntPtr addr = pEEType.ToPointer()->GetAssociatedModuleAddress(); Exception e = EH.GetClasslibException(exID, addr); throw e; } InternalCalls.RhpBox(result, pData); return(result); }
public static IntPtr RhHandleAllocVariable(object value, uint type) { IntPtr h = InternalCalls.RhpHandleAllocVariable(value, type); if (h == IntPtr.Zero) { // Throw the out of memory exception defined by the classlib, using the return address of this method // to find the correct classlib. ExceptionIDs exID = ExceptionIDs.OutOfMemory; IntPtr returnAddr = BinderIntrinsics.GetReturnAddress(); Exception e = EH.GetClasslibException(exID, returnAddr); throw e; } return(h); }
public static IntPtr RhHandleAllocDependent(object primary, object secondary) { IntPtr h = InternalCalls.RhpHandleAllocDependent(primary, secondary); if (h == IntPtr.Zero) { // Throw the out of memory exception defined by the classlib, using the return address of this method // to find the correct classlib. ExceptionIDs exID = ExceptionIDs.OutOfMemory; IntPtr returnAddr = BinderIntrinsics.GetReturnAddress(); Exception e = EH.GetClasslibException(exID, returnAddr); throw e; } return(h); }
public static void RhpReversePInvokeBadTransition() { IntPtr returnAddress = BinderIntrinsics.GetReturnAddress(); if (returnAddress != IntPtr.Zero) { EH.FailFastViaClasslib( RhFailFastReason.IllegalNativeCallableEntry, null, returnAddress); } else { // @HACKHACK: we need to force the method to have an EBP frame so that we can use the // GetReturnAddress() intrinsic above. This seems to be the smallest way to do this. EH.FailFast(RhFailFastReason.InternalError, null); throw EH.GetClasslibException(ExceptionIDs.Arithmetic, returnAddress); } }
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())) { IntPtr addr = ptrUnboxToEEType->GetAssociatedModuleAddress(); Exception e = EH.GetClasslibException(ExceptionIDs.InvalidCast, addr); BinderIntrinsics.TailCall_RhpThrowEx(e); } InternalCalls.RhUnbox(obj, pData - 1, ptrUnboxToEEType); } }
public unsafe static object RhNewObject(EETypePtr pEEType) { try { EEType *ptrEEType = (EEType *)pEEType.ToPointer(); #if FEATURE_64BIT_ALIGNMENT if (ptrEEType->RequiresAlign8) { if (ptrEEType->IsValueType) { return(InternalCalls.RhpNewFastMisalign(ptrEEType)); } if (ptrEEType->IsFinalizable) { return(InternalCalls.RhpNewFinalizableAlign8(ptrEEType)); } return(InternalCalls.RhpNewFastAlign8(ptrEEType)); } else #endif // FEATURE_64BIT_ALIGNMENT { if (ptrEEType->IsFinalizable) { return(InternalCalls.RhpNewFinalizable(ptrEEType)); } return(InternalCalls.RhpNewFast(ptrEEType)); } } catch (OutOfMemoryException) { // Throw the out of memory exception defined by the classlib, using the input EEType* // to find the correct classlib. ExceptionIDs exID = ExceptionIDs.OutOfMemory; IntPtr addr = pEEType.ToPointer()->GetAssociatedModuleAddress(); Exception e = EH.GetClasslibException(exID, addr); throw e; } }
public unsafe static object RhNewArray(EETypePtr pEEType, int length) { EEType *ptrEEType = (EEType *)pEEType.ToPointer(); try { #if FEATURE_64BIT_ALIGNMENT if (ptrEEType->RequiresAlign8) { return(InternalCalls.RhpNewArrayAlign8(ptrEEType, length)); } else #endif // FEATURE_64BIT_ALIGNMENT { return(InternalCalls.RhpNewArray(ptrEEType, length)); } } catch (OutOfMemoryException) { // Throw the out of memory exception defined by the classlib, using the input EEType* // to find the correct classlib. ExceptionIDs exID = ExceptionIDs.OutOfMemory; IntPtr addr = pEEType.ToPointer()->GetAssociatedModuleAddress(); Exception e = EH.GetClasslibException(exID, addr); throw e; } catch (OverflowException) { // Throw the overflow exception defined by the classlib, using the input EEType* // to find the correct classlib. ExceptionIDs exID = ExceptionIDs.Overflow; IntPtr addr = pEEType.ToPointer()->GetAssociatedModuleAddress(); Exception e = EH.GetClasslibException(exID, addr); throw e; } }
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); }
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); } }
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) { IntPtr addr = ptrUnboxToEEType->GetAssociatedModuleAddress(); Exception e = EH.GetClasslibException(ExceptionIDs.InvalidCast, addr); 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); } }
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); } }