diff --git a/src/coreclr/nativeaot/Bootstrap/main.cpp b/src/coreclr/nativeaot/Bootstrap/main.cpp index 16ffe8f9dbcb0..94afc2dfff8e3 100644 --- a/src/coreclr/nativeaot/Bootstrap/main.cpp +++ b/src/coreclr/nativeaot/Bootstrap/main.cpp @@ -138,10 +138,7 @@ typedef void (CDECL *pfn)(); static const pfn c_classlibFunctions[] = { &MANAGED_RUNTIME_EXPORT_NAME(GetRuntimeException), &MANAGED_RUNTIME_EXPORT_NAME(RuntimeFailFast), - nullptr, // &UnhandledExceptionHandler, &MANAGED_RUNTIME_EXPORT_NAME(AppendExceptionStackFrame), - nullptr, // &CheckStaticClassConstruction, - &MANAGED_RUNTIME_EXPORT_NAME(GetSystemArrayEEType), &MANAGED_RUNTIME_EXPORT_NAME(OnFirstChanceException), &MANAGED_RUNTIME_EXPORT_NAME(OnUnhandledException), &MANAGED_RUNTIME_EXPORT_NAME(IDynamicCastableIsInterfaceImplemented), diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Exception.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Exception.cs index f3851d38d7833..5a94b19b0049b 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Exception.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Exception.cs @@ -86,4 +86,14 @@ internal class OutOfMemoryException : Exception { public OutOfMemoryException() { } } + + internal class EntryPointNotFoundException : Exception + { + public EntryPointNotFoundException() { } + } + + internal class AmbiguousImplementationException : Exception + { + public AmbiguousImplementationException() { } + } } diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/DispatchResolve.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/DispatchResolve.cs index 349415c743aa9..8cfcc9e11aa00 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/DispatchResolve.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/DispatchResolve.cs @@ -29,7 +29,7 @@ public static IntPtr FindInterfaceMethodImplementationTarget(MethodTable* pTgtTy if (FindImplSlotForCurrentType( pCur, pItfType, itfSlotNumber, fDoDefaultImplementationLookup, &implSlotNumber, ppGenericContext)) { - IntPtr targetMethod; + IntPtr targetMethod = IntPtr.Zero; if (implSlotNumber < pCur->NumVtableSlots) { // true virtual - need to get the slot from the target type in case it got overridden @@ -37,11 +37,11 @@ public static IntPtr FindInterfaceMethodImplementationTarget(MethodTable* pTgtTy } else if (implSlotNumber == SpecialDispatchMapSlot.Reabstraction) { - throw pTgtType->GetClasslibException(ExceptionIDs.EntrypointNotFound); + ThrowHelper.ThrowEntryPointNotFoundException(); } else if (implSlotNumber == SpecialDispatchMapSlot.Diamond) { - throw pTgtType->GetClasslibException(ExceptionIDs.AmbiguousImplementation); + ThrowHelper.ThrowAmbiguousImplementationException(); } else { diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs index 8bdfb650362fd..25a67bf7906d3 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs @@ -316,14 +316,8 @@ internal static Exception GetClasslibException(ExceptionIDs id, IntPtr address) Exception? e = id switch { ExceptionIDs.AccessViolation => new AccessViolationException(), - ExceptionIDs.Arithmetic => new ArithmeticException(), - ExceptionIDs.AmbiguousImplementation => new AmbiguousImplementationException(), - ExceptionIDs.ArrayTypeMismatch => new ArrayTypeMismatchException(), ExceptionIDs.DataMisaligned => new DataMisalignedException(), ExceptionIDs.DivideByZero => new DivideByZeroException(), - ExceptionIDs.EntrypointNotFound => new EntryPointNotFoundException(), - ExceptionIDs.IndexOutOfRange => new IndexOutOfRangeException(), - ExceptionIDs.InvalidCast => new InvalidCastException(), ExceptionIDs.NullReference => new NullReferenceException(), ExceptionIDs.OutOfMemory => new OutOfMemoryException(), ExceptionIDs.Overflow => new OverflowException(), @@ -338,63 +332,8 @@ internal static Exception GetClasslibException(ExceptionIDs id, IntPtr address) return e; } -#if NATIVEAOT - // Given an ExceptionID and an MethodTable address, get an exception object of a type that the module containing - // the given address will understand. This finds the classlib-defined GetRuntimeException function and asks - // it for the exception object. - internal static Exception GetClasslibExceptionFromEEType(ExceptionIDs id, MethodTable* pEEType) - { - // Find the classlib function that will give us the exception object we want to throw. This - // is a RuntimeExport function from the classlib module, and is therefore managed-callable. - IntPtr pGetRuntimeExceptionFunction = IntPtr.Zero; - if (pEEType != null) - { - pGetRuntimeExceptionFunction = (IntPtr)InternalCalls.RhpGetClasslibFunctionFromEEType(pEEType, ClassLibFunctionId.GetRuntimeException); - } - - // Return the exception object we get from the classlib. - Exception? e = null; - try - { - e = ((delegate*)pGetRuntimeExceptionFunction)(id); - } - catch when (true) - { - // disallow all exceptions leaking out of callbacks - } - - // If the helper fails to yield an object, then we fail-fast. - if (e == null) - { - FailFastViaClasslib(RhFailFastReason.InternalError, null, (IntPtr)pEEType); - } - - return e; - } - - // RhExceptionHandling_ functions are used to throw exceptions out of our asm helpers. We tail-call from - // the asm helpers to these functions, which performs the throw. The tail-call is important: it ensures that - // the stack is crawlable from within these functions. - [StackTraceHidden] - [RuntimeExport("RhExceptionHandling_ThrowClasslibOverflowException")] - public static void ThrowClasslibOverflowException(IntPtr address) - { - // Throw the overflow exception defined by the classlib, using the return address of the asm helper - // to find the correct classlib. - - throw GetClasslibException(ExceptionIDs.Overflow, address); - } - - [StackTraceHidden] - [RuntimeExport("RhExceptionHandling_ThrowClasslibDivideByZeroException")] - 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. - - throw GetClasslibException(ExceptionIDs.DivideByZero, address); - } +#if NATIVEAOT [StackTraceHidden] [RuntimeExport("RhExceptionHandling_FailedAllocation")] public static void FailedAllocation(MethodTable* pEEType, bool fIsOverflow) @@ -403,39 +342,8 @@ public static void FailedAllocation(MethodTable* pEEType, bool fIsOverflow) // Throw the out of memory exception defined by the classlib, using the input MethodTable* // to find the correct classlib. - throw pEEType->GetClasslibException(exID); } - -#if !INPLACE_RUNTIME - private static readonly OutOfMemoryException s_theOOMException = new OutOfMemoryException(); - - // MRT exports GetRuntimeException for the few cases where we have a helper that throws an exception - // and may be called by either MRT or other classlibs and that helper needs to throw an exception. - // There are only a few cases where this happens now (the fast allocation helpers), so we limit the - // exception types that MRT will return. - [RuntimeExport("GetRuntimeException")] - public static Exception GetRuntimeException(ExceptionIDs id) - { - switch (id) - { - case ExceptionIDs.OutOfMemory: - // Throw a preallocated exception to avoid infinite recursion. - return s_theOOMException; - - case ExceptionIDs.Overflow: - return new OverflowException(); - - case ExceptionIDs.InvalidCast: - return new InvalidCastException(); - - default: - Debug.Assert(false, "unexpected ExceptionID"); - FallbackFailFast(RhFailFastReason.InternalError, null); - return null; - } - } -#endif #endif // NATIVEAOT private enum HwExceptionCode : uint @@ -561,16 +469,16 @@ public static void RhThrowHwEx(uint exceptionCode, ref ExInfo exInfo) #endif IntPtr faultingCodeAddress = exInfo._pExContext->IP; bool instructionFault = true; - ExceptionIDs exceptionId = default(ExceptionIDs); + ExceptionIDs exceptionId = 0; Exception? exceptionToThrow = null; - switch (exceptionCode) + switch ((HwExceptionCode)exceptionCode) { - case (uint)HwExceptionCode.STATUS_REDHAWK_NULL_REFERENCE: + case HwExceptionCode.STATUS_REDHAWK_NULL_REFERENCE: exceptionId = ExceptionIDs.NullReference; break; - case (uint)HwExceptionCode.STATUS_REDHAWK_UNMANAGED_HELPER_NULL_REFERENCE: + case HwExceptionCode.STATUS_REDHAWK_UNMANAGED_HELPER_NULL_REFERENCE: // The write barrier where the actual fault happened has been unwound already. // The IP of this fault needs to be treated as return address, not as IP of // faulting instruction. @@ -579,26 +487,26 @@ public static void RhThrowHwEx(uint exceptionCode, ref ExInfo exInfo) break; #if NATIVEAOT - case (uint)HwExceptionCode.STATUS_REDHAWK_THREAD_ABORT: + case HwExceptionCode.STATUS_REDHAWK_THREAD_ABORT: exceptionToThrow = InternalCalls.RhpGetThreadAbortException(); break; #endif - case (uint)HwExceptionCode.STATUS_DATATYPE_MISALIGNMENT: + case HwExceptionCode.STATUS_DATATYPE_MISALIGNMENT: exceptionId = ExceptionIDs.DataMisaligned; break; // N.B. -- AVs that have a read/write address lower than 64k are already transformed to // HwExceptionCode.REDHAWK_NULL_REFERENCE prior to calling this routine. - case (uint)HwExceptionCode.STATUS_ACCESS_VIOLATION: + case HwExceptionCode.STATUS_ACCESS_VIOLATION: exceptionId = ExceptionIDs.AccessViolation; break; - case (uint)HwExceptionCode.STATUS_INTEGER_DIVIDE_BY_ZERO: + case HwExceptionCode.STATUS_INTEGER_DIVIDE_BY_ZERO: exceptionId = ExceptionIDs.DivideByZero; break; - case (uint)HwExceptionCode.STATUS_INTEGER_OVERFLOW: + case HwExceptionCode.STATUS_INTEGER_OVERFLOW: exceptionId = ExceptionIDs.Overflow; break; @@ -610,7 +518,7 @@ public static void RhThrowHwEx(uint exceptionCode, ref ExInfo exInfo) break; } - if (exceptionId != default(ExceptionIDs)) + if (exceptionId != 0) { exceptionToThrow = GetClasslibException(exceptionId, faultingCodeAddress); } @@ -1081,38 +989,9 @@ private static bool FindFirstPassHandler(object exception, uint idxStart, return false; } -#if DEBUG && !INPLACE_RUNTIME && NATIVEAOT - private static MethodTable* s_pLowLevelObjectType; - private static void AssertNotRuntimeObject(MethodTable* pClauseType) - { - // - // The C# try { } catch { } clause expands into a typed catch of System.Object. - // Since runtime has its own definition of System.Object, try { } catch { } might not do what - // was intended (catch all exceptions). - // - // This assertion is making sure we don't use try { } catch { } within the runtime. - // The runtime codebase should either use try { } catch (Exception) { } for exception types - // from the runtime or a try { } catch when (true) { } to catch all exceptions. - // - - if (s_pLowLevelObjectType == null) - { - // Allocating might fail, but since this is just a debug assert, it's probably fine. - s_pLowLevelObjectType = new System.Object().MethodTable; - } - - Debug.Assert(!pClauseType->IsEquivalentTo(s_pLowLevelObjectType)); - } -#endif // DEBUG && !INPLACE_RUNTIME && NATIVEAOT - - private static bool ShouldTypedClauseCatchThisException(object exception, MethodTable* pClauseType, bool tryUnwrapException) { #if NATIVEAOT -#if DEBUG && !INPLACE_RUNTIME - AssertNotRuntimeObject(pClauseType); -#endif - return TypeCast.IsInstanceOfException(pClauseType, exception); #else if (tryUnwrapException && exception is RuntimeWrappedException ex) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionIDs.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionIDs.cs index 764bd124d6774..d7e8df376476e 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionIDs.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionIDs.cs @@ -11,16 +11,10 @@ namespace System.Runtime enum ExceptionIDs { OutOfMemory = 1, - Arithmetic = 2, - ArrayTypeMismatch = 3, - DivideByZero = 4, - IndexOutOfRange = 5, - InvalidCast = 6, - Overflow = 7, - NullReference = 8, - AccessViolation = 9, - DataMisaligned = 10, - EntrypointNotFound = 11, - AmbiguousImplementation = 12, + DivideByZero = 2, + Overflow = 3, + NullReference = 4, + AccessViolation = 5, + DataMisaligned = 6 } } diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs index 7ea73ba7c2c38..0efef08af6a31 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs @@ -38,18 +38,15 @@ internal enum ClassLibFunctionId { GetRuntimeException = 0, FailFast = 1, - // UnhandledExceptionHandler = 2, // unused - AppendExceptionStackFrame = 3, - // unused = 4, - GetSystemArrayEEType = 5, - OnFirstChance = 6, - OnUnhandledException = 7, - IDynamicCastableIsInterfaceImplemented = 8, - IDynamicCastableGetInterfaceImplementation = 9, - ObjectiveCMarshalTryGetTaggedMemory = 10, - ObjectiveCMarshalGetIsTrackedReferenceCallback = 11, - ObjectiveCMarshalGetOnEnteredFinalizerQueueCallback = 12, - ObjectiveCMarshalGetUnhandledExceptionPropagationHandler = 13, + AppendExceptionStackFrame = 2, + OnFirstChance = 3, + OnUnhandledException = 4, + IDynamicCastableIsInterfaceImplemented = 5, + IDynamicCastableGetInterfaceImplementation = 6, + ObjectiveCMarshalTryGetTaggedMemory = 7, + ObjectiveCMarshalGetIsTrackedReferenceCallback = 8, + ObjectiveCMarshalGetOnEnteredFinalizerQueueCallback = 9, + ObjectiveCMarshalGetUnhandledExceptionPropagationHandler = 10, } internal static class InternalCalls diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/MethodTable.Runtime.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/MethodTable.Runtime.cs index 1c786946c82bf..1c2c322531605 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/MethodTable.Runtime.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/MethodTable.Runtime.cs @@ -11,24 +11,12 @@ namespace Internal.Runtime // Extensions to MethodTable that are specific to the use in Runtime.Base. internal unsafe partial struct MethodTable { -#if !INPLACE_RUNTIME - internal MethodTable* GetArrayEEType() - { - MethodTable* pThis = (MethodTable*)Unsafe.Pointer(ref this); - void* pGetArrayEEType = InternalCalls.RhpGetClasslibFunctionFromEEType(pThis, ClassLibFunctionId.GetSystemArrayEEType); - return ((delegate* )pGetArrayEEType)(); - } - +#pragma warning disable CA1822 internal Exception GetClasslibException(ExceptionIDs id) { - if (IsParameterizedType) - { - return RelatedParameterType->GetClasslibException(id); - } - - return EH.GetClasslibExceptionFromEEType(id, (MethodTable*)Unsafe.AsPointer(ref this)); + return RuntimeExceptionHelpers.GetRuntimeException(id); } -#endif +#pragma warning restore CA1822 internal IntPtr GetClasslibFunction(ClassLibFunctionId id) { diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs index 6fa6c5460dbb8..280b845b00be4 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs @@ -169,7 +169,7 @@ public static unsafe void RhUnboxAny(object? o, ref byte data, MethodTable* pUnb { if (pUnboxToEEType->IsValueType) { - bool isValid = false; + bool isValid; if (pUnboxToEEType->IsNullable) { @@ -177,17 +177,13 @@ public static unsafe void RhUnboxAny(object? o, ref byte data, MethodTable* pUnb } else { - isValid = (o != null) && UnboxAnyTypeCompare(o.GetMethodTable(), pUnboxToEEType); + // This will throw NullReferenceException if obj is null. + isValid = UnboxAnyTypeCompare(o.GetMethodTable(), pUnboxToEEType); } if (!isValid) { - // Throw the invalid cast exception defined by the classlib, using the input unbox MethodTable* - // to find the correct classlib. - - ExceptionIDs exID = o == null ? ExceptionIDs.NullReference : ExceptionIDs.InvalidCast; - - throw pUnboxToEEType->GetClasslibException(exID); + ThrowHelper.ThrowInvalidCastException(); } RhUnbox(o, ref data, pUnboxToEEType); @@ -196,7 +192,7 @@ public static unsafe void RhUnboxAny(object? o, ref byte data, MethodTable* pUnb { if (o != null && (TypeCast.IsInstanceOfAny(pUnboxToEEType, o) == null)) { - throw pUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast); + ThrowHelper.ThrowInvalidCastException(); } Unsafe.As(ref data) = o; @@ -209,11 +205,12 @@ public static unsafe void RhUnboxAny(object? o, ref byte data, MethodTable* pUnb [RuntimeExport("RhUnbox2")] public static unsafe ref byte RhUnbox2(MethodTable* pUnboxToEEType, object obj) { - if ((obj == null) || !UnboxAnyTypeCompare(obj.GetMethodTable(), pUnboxToEEType)) + // This will throw NullReferenceException if obj is null. + if (!UnboxAnyTypeCompare(obj.GetMethodTable(), pUnboxToEEType)) { - ExceptionIDs exID = obj == null ? ExceptionIDs.NullReference : ExceptionIDs.InvalidCast; - throw pUnboxToEEType->GetClasslibException(exID); + ThrowHelper.ThrowInvalidCastException(); } + return ref obj.GetRawData(); } @@ -222,7 +219,7 @@ public static unsafe void RhUnboxNullable(ref byte data, MethodTable* pUnboxToEE { if (obj != null && obj.GetMethodTable() != pUnboxToEEType->NullableType) { - throw pUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast); + ThrowHelper.ThrowInvalidCastException(); } RhUnbox(obj, ref data, pUnboxToEEType); } diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs index 0161e8c47c150..33d3032b6e50e 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/TypeCast.cs @@ -382,15 +382,14 @@ private static unsafe object CheckCastInterface_Helper(MethodTable* pTargetType, { // If object type implements IDynamicInterfaceCastable then there's one more way to check whether it implements // the interface. - if (obj.GetMethodTable()->IsIDynamicInterfaceCastable - && IsInstanceOfInterfaceViaIDynamicInterfaceCastable(pTargetType, obj, throwing: true)) + Debug.Assert(obj is not null); + if (!obj.GetMethodTable()->IsIDynamicInterfaceCastable + || !IsInstanceOfInterfaceViaIDynamicInterfaceCastable(pTargetType, obj, throwing: true)) { - return obj; + ThrowHelper.ThrowInvalidCastException(); } - // Throw the invalid cast exception defined by the classlib, using the input MethodTable* to find the - // correct classlib. - return ThrowInvalidCastException(pTargetType); + return obj; } [RuntimeExport("RhTypeCast_CheckCastClass")] @@ -432,7 +431,7 @@ private static unsafe object CheckCastClassSpecial(MethodTable* pTargetType, obj goto done; // They don't cast to any other class - goto fail; + ThrowHelper.ThrowInvalidCastException(); } for (; ; ) @@ -466,13 +465,10 @@ private static unsafe object CheckCastClassSpecial(MethodTable* pTargetType, obj break; } - goto fail; + ThrowHelper.ThrowInvalidCastException(); done: return obj; - - fail: - return ThrowInvalidCastException(pTargetType); } private static unsafe bool IsInstanceOfInterfaceViaIDynamicInterfaceCastable(MethodTable* pTargetType, object obj, bool throwing) @@ -738,24 +734,7 @@ public static unsafe void CheckArrayStore(object array, object obj) if (obj.GetMethodTable()->IsIDynamicInterfaceCastable && IsInstanceOfInterfaceViaIDynamicInterfaceCastable(arrayElemType, obj, throwing: false)) return; - // Throw the array type mismatch exception defined by the classlib, using the input array's MethodTable* - // to find the correct classlib. - - throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); - } - - private static unsafe void ThrowIndexOutOfRangeException(object?[] array) - { - // Throw the index out of range exception defined by the classlib, using the input array's MethodTable* - // to find the correct classlib. - throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.IndexOutOfRange); - } - - private static unsafe void ThrowArrayMismatchException(object?[] array) - { - // Throw the array type mismatch exception defined by the classlib, using the input array's MethodTable* - // to find the correct classlib. - throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); + ThrowHelper.ThrowArrayTypeMismatchException(); } // @@ -767,29 +746,16 @@ private static unsafe void ThrowArrayMismatchException(object?[] array) { Debug.Assert(array is null || array.GetMethodTable()->IsArray, "first argument must be an array"); -#if INPLACE_RUNTIME // This will throw NullReferenceException if obj is null. if ((nuint)index >= (uint)array.Length) - ThrowIndexOutOfRangeException(array); + ThrowHelper.ThrowIndexOutOfRangeException(); Debug.Assert(index >= 0); ref object? element = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), index); -#else - if (array is null) - { - throw elementType->GetClasslibException(ExceptionIDs.NullReference); - } - if ((nuint)index >= (uint)array.Length) - { - throw elementType->GetClasslibException(ExceptionIDs.IndexOutOfRange); - } - ref object rawData = ref Unsafe.As(ref Unsafe.As(array).Data); - ref object element = ref Unsafe.Add(ref rawData, index); -#endif MethodTable* arrayElemType = array.GetMethodTable()->RelatedParameterType; if (elementType != arrayElemType) - ThrowArrayMismatchException(array); + ThrowHelper.ThrowArrayTypeMismatchException(); return ref element; } @@ -800,27 +766,12 @@ public static unsafe void StelemRef(object?[] array, nint index, object? obj) // This is supported only on arrays Debug.Assert(array is null || array.GetMethodTable()->IsArray, "first argument must be an array"); -#if INPLACE_RUNTIME // This will throw NullReferenceException if obj is null. if ((nuint)index >= (uint)array.Length) - ThrowIndexOutOfRangeException(array); + ThrowHelper.ThrowIndexOutOfRangeException(); Debug.Assert(index >= 0); ref object? element = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), index); -#else - if (array is null) - { - // TODO: If both array and obj are null, we're likely going to throw Redhawk's NullReferenceException. - // This should blame the caller. - throw obj.GetMethodTable()->GetClasslibException(ExceptionIDs.NullReference); - } - if ((uint)index >= (uint)array.Length) - { - throw array.GetMethodTable()->GetClasslibException(ExceptionIDs.IndexOutOfRange); - } - ref object rawData = ref Unsafe.As(ref Unsafe.As(array).Data); - ref object element = ref Unsafe.Add(ref rawData, index); -#endif MethodTable* elementType = array.GetMethodTable()->RelatedParameterType; @@ -839,11 +790,8 @@ public static unsafe void StelemRef(object?[] array, nint index, object? obj) return; notExactMatch: -#if INPLACE_RUNTIME - // This optimization only makes sense for inplace runtime where there's only one System.Object. if (array.GetMethodTable() == MethodTable.Of()) goto doWrite; -#endif StelemRef_Helper(ref element, elementType, obj); } @@ -866,9 +814,7 @@ private static unsafe void StelemRef_Helper_NoCacheLookup(ref object? element, M object? castedObj = IsInstanceOfAny_NoCacheLookup(elementType, obj); if (castedObj == null) { - // Throw the array type mismatch exception defined by the classlib, using the input array's - // MethodTable* to find the correct classlib. - throw elementType->GetClasslibException(ExceptionIDs.ArrayTypeMismatch); + ThrowHelper.ThrowArrayTypeMismatchException(); } InternalCalls.RhpAssignRef(ref element, obj); @@ -918,10 +864,7 @@ private static unsafe object CheckCastArray(MethodTable* pTargetEEType, object o if (result == null) { - // Throw the invalid cast exception defined by the classlib, using the input MethodTable* - // to find the correct classlib. - - return ThrowInvalidCastException(pTargetEEType); + ThrowHelper.ThrowInvalidCastException(); } return result; @@ -929,6 +872,7 @@ private static unsafe object CheckCastArray(MethodTable* pTargetEEType, object o private static unsafe object IsInstanceOfVariantType(MethodTable* pTargetType, object obj) { + Debug.Assert(obj is not null); if (!AreTypesAssignableInternal(obj.GetMethodTable(), pTargetType, AssignmentVariation.BoxedSource, null) && (!obj.GetMethodTable()->IsIDynamicInterfaceCastable || !IsInstanceOfInterfaceViaIDynamicInterfaceCastable(pTargetType, obj, throwing: false))) @@ -941,11 +885,12 @@ private static unsafe object IsInstanceOfVariantType(MethodTable* pTargetType, o private static unsafe object CheckCastVariantType(MethodTable* pTargetType, object obj) { + Debug.Assert(obj is not null); if (!AreTypesAssignableInternal(obj.GetMethodTable(), pTargetType, AssignmentVariation.BoxedSource, null) && (!obj.GetMethodTable()->IsIDynamicInterfaceCastable || !IsInstanceOfInterfaceViaIDynamicInterfaceCastable(pTargetType, obj, throwing: true))) { - return ThrowInvalidCastException(pTargetType); + ThrowHelper.ThrowInvalidCastException(); } return obj; @@ -967,13 +912,6 @@ private static unsafe EETypeElementType GetNormalizedIntegralArrayElementType(Me return elementType; } - // Would not be inlined, but still need to mark NoInlining so that it doesn't throw off tail calls - [MethodImpl(MethodImplOptions.NoInlining)] - private static unsafe object ThrowInvalidCastException(MethodTable* pMT) - { - throw pMT->GetClasslibException(ExceptionIDs.InvalidCast); - } - internal unsafe struct EETypePairList { private MethodTable* _eetype1; @@ -1284,9 +1222,7 @@ private static unsafe object CheckCastAny_NoCacheLookup(MethodTable* pTargetType } else if (pTargetType->IsParameterizedType || pTargetType->IsFunctionPointer) { - // We handled arrays above so this is for pointers and byrefs only. - // Nothing can be a boxed instance of these. - return ThrowInvalidCastException(pTargetType); + ThrowHelper.ThrowInvalidCastException(); } else { diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/__Finalizer.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/__Finalizer.cs index a55b7fc040d25..6f30686fb5fb4 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/__Finalizer.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/__Finalizer.cs @@ -19,9 +19,7 @@ internal static class __Finalizer [UnmanagedCallersOnly(EntryPoint = "ProcessFinalizers")] public static void ProcessFinalizers() { -#if INPLACE_RUNTIME - System.Runtime.FinalizerInitRunner.DoInitialize(); -#endif + FinalizerInitRunner.DoInitialize(); while (true) { diff --git a/src/coreclr/nativeaot/Runtime/ICodeManager.h b/src/coreclr/nativeaot/Runtime/ICodeManager.h index dfc6e9efa915a..76de0a8e88eda 100644 --- a/src/coreclr/nativeaot/Runtime/ICodeManager.h +++ b/src/coreclr/nativeaot/Runtime/ICodeManager.h @@ -186,18 +186,15 @@ enum class ClasslibFunctionId { GetRuntimeException = 0, FailFast = 1, - UnhandledExceptionHandler = 2, - AppendExceptionStackFrame = 3, - // unused = 4, - GetSystemArrayEEType = 5, - OnFirstChanceException = 6, - OnUnhandledException = 7, - IDynamicCastableIsInterfaceImplemented = 8, - IDynamicCastableGetInterfaceImplementation = 9, - ObjectiveCMarshalTryGetTaggedMemory = 10, - ObjectiveCMarshalGetIsTrackedReferenceCallback = 11, - ObjectiveCMarshalGetOnEnteredFinalizerQueueCallback = 12, - ObjectiveCMarshalGetUnhandledExceptionPropagationHandler = 13, + AppendExceptionStackFrame = 2, + OnFirstChanceException = 3, + OnUnhandledException = 4, + IDynamicCastableIsInterfaceImplemented = 5, + IDynamicCastableGetInterfaceImplementation = 6, + ObjectiveCMarshalTryGetTaggedMemory = 7, + ObjectiveCMarshalGetIsTrackedReferenceCallback = 8, + ObjectiveCMarshalGetOnEnteredFinalizerQueueCallback = 9, + ObjectiveCMarshalGetUnhandledExceptionPropagationHandler = 10, }; enum class AssociatedDataFlags : unsigned char diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/MethodTable.Runtime.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/MethodTable.Runtime.cs index 899ac448d5f9d..2b37d6f9206b8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/MethodTable.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/MethodTable.Runtime.cs @@ -16,11 +16,6 @@ internal unsafe partial struct MethodTable { return MethodTable.Of(); } - - internal Exception GetClasslibException(ExceptionIDs id) - { - return RuntimeExceptionHelpers.GetRuntimeException(id); - } #pragma warning restore CA1822 internal static bool AreSameType(MethodTable* mt1, MethodTable* mt2) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj index bea161cffbaa0..91fc07d56456e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -207,7 +207,7 @@ - + @@ -283,7 +283,7 @@ Interop\Windows\Ole32\Interop.CoGetContextToken.cs - + Interop\Windows\OleAut32\Interop.VariantClear.cs @@ -509,10 +509,6 @@ - true - - - INPLACE_RUNTIME;$(DefineConstants) FEATURE_64BIT_ALIGNMENT;$(DefineConstants) FEATURE_64BIT_ALIGNMENT;$(DefineConstants) FEATURE_64BIT_ALIGNMENT;$(DefineConstants) @@ -520,7 +516,7 @@ $(ArtifactsObjDir)\coreclr\$(TargetOS).$(TargetArchitecture).$(CoreCLRConfiguration) $(IntermediatesDir)\ide - + Runtime.Base\src\System\Runtime\CachedInterfaceDispatch.cs @@ -558,7 +554,7 @@ Common\TransitionBlock.cs - + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs index 0c9c571ed0f7e..b77a3bcf347a2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs @@ -49,14 +49,6 @@ internal unsafe bool IsSzArray } } - // This is the classlib-provided "get array MethodTable" function that will be invoked whenever the runtime - // needs to know the base type of an array. - [RuntimeExport("GetSystemArrayEEType")] - private static unsafe MethodTable* GetSystemArrayEEType() - { - return MethodTable.Of(); - } - [RequiresDynamicCode("The code for an array of the specified type might not be available.")] private static unsafe Array InternalCreate(RuntimeType elementType, int rank, int* pLengths, int* pLowerBounds) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/ExceptionIDs.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/ExceptionIDs.cs index 7fc0ad6a9dfeb..b22720ed325e8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/ExceptionIDs.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/ExceptionIDs.cs @@ -6,16 +6,10 @@ namespace System.Runtime internal enum ExceptionIDs { OutOfMemory = 1, - Arithmetic = 2, - ArrayTypeMismatch = 3, - DivideByZero = 4, - IndexOutOfRange = 5, - InvalidCast = 6, - Overflow = 7, - NullReference = 8, - AccessViolation = 9, - DataMisaligned = 10, - EntrypointNotFound = 11, - AmbiguousImplementation = 12, + DivideByZero = 2, + Overflow = 3, + NullReference = 4, + AccessViolation = 5, + DataMisaligned = 6 } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs index d0021229b7522..ca0beaf62dcaf 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs @@ -9,7 +9,6 @@ internal static class FinalizerInitRunner { // Here, we are subscribing to a callback from the runtime. This callback is made from the finalizer // thread before any objects are finalized. - [RuntimeExport("InitializeFinalizerThread")] public static void DoInitialize() { // Make sure that the finalizer thread is CoInitialized before any objects are finalized. If this diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs index 0ed5f375cc27c..4ed4798dc49d1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs @@ -71,21 +71,9 @@ internal static class RuntimeExceptionHelpers return outOfMemoryException; - case ExceptionIDs.Arithmetic: - return new ArithmeticException(); - - case ExceptionIDs.ArrayTypeMismatch: - return new ArrayTypeMismatchException(); - case ExceptionIDs.DivideByZero: return new DivideByZeroException(); - case ExceptionIDs.IndexOutOfRange: - return new IndexOutOfRangeException(); - - case ExceptionIDs.InvalidCast: - return new InvalidCastException(); - case ExceptionIDs.Overflow: return new OverflowException(); @@ -99,12 +87,6 @@ internal static class RuntimeExceptionHelpers case ExceptionIDs.DataMisaligned: return new DataMisalignedException(); - case ExceptionIDs.EntrypointNotFound: - return new EntryPointNotFoundException(); - - case ExceptionIDs.AmbiguousImplementation: - return new AmbiguousImplementationException(); - default: FailFast("The runtime requires an exception for a case that this class library does not understand."); return null; diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/Internal/Runtime/MethodTable.Runtime.cs b/src/coreclr/nativeaot/Test.CoreLib/src/Internal/Runtime/MethodTable.Runtime.cs index 1bb7dcd62abd1..20654398f09ea 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/Internal/Runtime/MethodTable.Runtime.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/Internal/Runtime/MethodTable.Runtime.cs @@ -13,10 +13,5 @@ internal unsafe partial struct MethodTable { return MethodTable.Of(); } - - internal Exception GetClasslibException(ExceptionIDs id) - { - return RuntimeExceptionHelpers.GetRuntimeException(id); - } } } diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Array.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Array.cs deleted file mode 100644 index 33e35805e4df4..0000000000000 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Array.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Runtime; - -using MethodTable = Internal.Runtime.MethodTable; - -namespace System -{ - public partial class Array - { - // This is the classlib-provided "get array MethodTable" function that will be invoked whenever the runtime - // needs to know the base type of an array. - [RuntimeExport("GetSystemArrayEEType")] - private static unsafe MethodTable* GetSystemArrayEEType() - { - return MethodTable.Of(); - } - } -} diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/RuntimeExceptionHelpers.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/RuntimeExceptionHelpers.cs index 8100d936e66b0..b218e70bb7342 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/RuntimeExceptionHelpers.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/RuntimeExceptionHelpers.cs @@ -43,21 +43,9 @@ public static Exception GetRuntimeException(ExceptionIDs id) case ExceptionIDs.OutOfMemory: return PreallocatedOutOfMemoryException.Instance; - case ExceptionIDs.Arithmetic: - return new ArithmeticException(); - - case ExceptionIDs.ArrayTypeMismatch: - return new ArrayTypeMismatchException(); - case ExceptionIDs.DivideByZero: return new DivideByZeroException(); - case ExceptionIDs.IndexOutOfRange: - return new IndexOutOfRangeException(); - - case ExceptionIDs.InvalidCast: - return new InvalidCastException(); - case ExceptionIDs.Overflow: return new OverflowException(); diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/ThrowHelper.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/ThrowHelper.cs new file mode 100644 index 0000000000000..4dcf0c29a8ee5 --- /dev/null +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/ThrowHelper.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; + +namespace System +{ + [StackTraceHidden] + internal static class ThrowHelper + { + internal static void ThrowEntryPointNotFoundException() + { + throw new EntryPointNotFoundException(); + } + + internal static void ThrowAmbiguousImplementationException() + { + throw new AmbiguousImplementationException(); + } + + internal static void ThrowOverflowException() + { + throw new OverflowException(); + } + + internal static void ThrowDivideByZeroException() + { + throw new DivideByZeroException(); + } + + internal static void ThrowOutOfMemoryException() + { + throw new OutOfMemoryException(); + } + + internal static void ThrowNullReferenceException() + { + throw new NullReferenceException(); + } + + internal static void ThrowInvalidCastException() + { + throw new InvalidCastException(); + } + + internal static void ThrowArrayTypeMismatchException() + { + throw new ArrayTypeMismatchException(); + } + + internal static void ThrowIndexOutOfRangeException() + { + throw new IndexOutOfRangeException(); + } + } +} diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj b/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj index c6c4b5e7d7689..ac361020c50ed 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj +++ b/src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj @@ -18,10 +18,6 @@ - true - - - INPLACE_RUNTIME;$(DefineConstants) FEATURE_64BIT_ALIGNMENT;$(DefineConstants) FEATURE_64BIT_ALIGNMENT;$(DefineConstants) @@ -31,7 +27,7 @@ $([MSBuild]::NormalizeDirectory('$(LibrariesProjectRoot)', 'Common', 'src')) - + Runtime.Base\src\System\Runtime\CachedInterfaceDispatch.cs @@ -72,7 +68,7 @@ Common\Interop\Windows\Interop.BOOL.cs - + @@ -230,9 +226,9 @@ - + diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 1f1669a04359c..a7f799498884a 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -3743,9 +3743,6 @@ Number of elements in source vector is greater than the destination array - - The method was called with a null array argument. - AggressiveGC requires setting the generation parameter to MaxGeneration diff --git a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs index d042b39bca143..c5e4170b1962c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs @@ -65,6 +65,18 @@ internal static void ThrowAccessViolationException() throw new AccessViolationException(); } + [DoesNotReturn] + internal static void ThrowAmbiguousImplementationException() + { + throw new AmbiguousImplementationException(); + } + + [DoesNotReturn] + internal static void ThrowEntryPointNotFoundException() + { + throw new EntryPointNotFoundException(); + } + [DoesNotReturn] internal static void ThrowArrayTypeMismatchException() { @@ -77,6 +89,12 @@ internal static void ThrowArrayTypeMismatchException_CantAssignType() throw new ArrayTypeMismatchException(SR.ArrayTypeMismatch_CantAssignType); } + [DoesNotReturn] + internal static void ThrowInvalidCastException() + { + throw new InvalidCastException(); + } + [DoesNotReturn] internal static void ThrowInvalidCastException_DownCastArrayElement() { @@ -419,7 +437,7 @@ internal static void ThrowInvalidOperationException(ExceptionResource resource, [DoesNotReturn] internal static void ThrowNullReferenceException() { - throw new NullReferenceException(SR.Arg_NullArgumentNullRef); + throw new NullReferenceException(); } [DoesNotReturn]