diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs index 41534ab0651837..33df3dfc35af89 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/CustomAttribute.cs @@ -1228,7 +1228,7 @@ private static void AddCustomAttributes( } else { - attribute = attributeType.CreateInstanceDefaultCtor(publicOnly: false, skipCheckThis: true, fillCache: true, wrapExceptions: false)!; + attribute = attributeType.CreateInstanceDefaultCtor(publicOnly: false, wrapExceptions: false)!; // It is allowed by the ECMA spec to have an empty signature blob int blobLen = (int)((byte*)blobEnd - (byte*)blobStart); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs index cd6be54ace1f41..1c0224bd8560b7 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs @@ -346,7 +346,7 @@ public sealed override Delegate CreateDelegate(Type delegateType) // Compile the method since accessibility checks are done as part of compilation. GetMethodDescriptor(); IRuntimeMethodInfo? methodHandle = m_methodHandle; - System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(methodHandle != null ? methodHandle.Value : RuntimeMethodHandleInternal.EmptyHandle); + System.Runtime.CompilerServices.RuntimeHelpers.CompileMethod(methodHandle != null ? methodHandle.Value : RuntimeMethodHandleInternal.EmptyHandle); GC.KeepAlive(methodHandle); } @@ -363,7 +363,7 @@ public sealed override Delegate CreateDelegate(Type delegateType, object? target // Compile the method since accessibility checks are done as part of compilation GetMethodDescriptor(); IRuntimeMethodInfo? methodHandle = m_methodHandle; - System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(methodHandle != null ? methodHandle.Value : RuntimeMethodHandleInternal.EmptyHandle); + System.Runtime.CompilerServices.RuntimeHelpers.CompileMethod(methodHandle != null ? methodHandle.Value : RuntimeMethodHandleInternal.EmptyHandle); GC.KeepAlive(methodHandle); } diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 95de9b788bfcb1..6f4d51917f4a51 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -3,7 +3,10 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Serialization; using Internal.Runtime.CompilerServices; namespace System.Runtime.CompilerServices @@ -39,12 +42,16 @@ public static partial class RuntimeHelpers // This call will generate an exception if the specified class constructor threw an // exception when it ran. - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _RunClassConstructor(RuntimeType type); + [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] + private static extern void RunClassConstructor(QCallTypeHandle type); public static void RunClassConstructor(RuntimeTypeHandle type) { - _RunClassConstructor(type.GetRuntimeType()); + RuntimeType rt = type.GetRuntimeType(); + if (rt is null) + throw new ArgumentException(SR.InvalidOperation_HandleIsNotInitialized, nameof(type)); + + RunClassConstructor(new QCallTypeHandle(ref rt)); } // RunModuleConstructor causes the module constructor for the given type to be triggered @@ -55,42 +62,41 @@ public static void RunClassConstructor(RuntimeTypeHandle type) // This call will generate an exception if the specified module constructor threw an // exception when it ran. - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void _RunModuleConstructor(System.Reflection.RuntimeModule module); + [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] + private static extern void RunModuleConstructor(QCallModule module); public static void RunModuleConstructor(ModuleHandle module) { - _RunModuleConstructor(module.GetRuntimeModule()); + RuntimeModule rm = module.GetRuntimeModule(); + if (rm is null) + throw new ArgumentException(SR.InvalidOperation_HandleIsNotInitialized, nameof(module)); + + RunModuleConstructor(new QCallModule(ref rm)); } + [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] + internal static extern void CompileMethod(RuntimeMethodHandleInternal method); [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)] - internal static extern void _CompileMethod(RuntimeMethodHandleInternal method); + private static extern unsafe void PrepareMethod(RuntimeMethodHandleInternal method, IntPtr* pInstantiation, int cInstantiation); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern unsafe void _PrepareMethod(IRuntimeMethodInfo method, IntPtr* pInstantiation, int cInstantiation); + public static void PrepareMethod(RuntimeMethodHandle method) => PrepareMethod(method, null); - public static void PrepareMethod(RuntimeMethodHandle method) + public static unsafe void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[]? instantiation) { - unsafe - { - _PrepareMethod(method.GetMethodInfo(), null, 0); - } - } + IRuntimeMethodInfo methodInfo = method.GetMethodInfo(); + if (methodInfo == null) + throw new ArgumentException(SR.InvalidOperation_HandleIsNotInitialized, nameof(method)); - public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[]? instantiation) - { // defensive copy of user-provided array, per CopyRuntimeTypeHandles contract instantiation = (RuntimeTypeHandle[]?)instantiation?.Clone(); - unsafe + IntPtr[]? instantiationHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(instantiation, out int length); + fixed (IntPtr* pInstantiation = instantiationHandles) { - IntPtr[]? instantiationHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(instantiation, out int length); - fixed (IntPtr* pInstantiation = instantiationHandles) - { - _PrepareMethod(method.GetMethodInfo(), pInstantiation, length); - GC.KeepAlive(instantiation); - } + PrepareMethod(methodInfo.Value, pInstantiation, length); + GC.KeepAlive(instantiation); + GC.KeepAlive(methodInfo); } } @@ -138,15 +144,32 @@ public static int OffsetToStringData [MethodImpl(MethodImplOptions.InternalCall)] public static extern bool TryEnsureSufficientExecutionStack(); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern object GetUninitializedObjectInternal( + public static object GetUninitializedObject( // This API doesn't call any constructors, but the type needs to be seen as constructed. // A type is seen as constructed if a constructor is kept. // This obviously won't cover a type with no constructor. Reference types with no // constructor are an academic problem. Valuetypes with no constructors are a problem, // but IL Linker currently treats them as always implicitly boxed. [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] - Type type); + Type type) + { + if (type is not RuntimeType rt) + { + if (type is null) + { + throw new ArgumentNullException(nameof(type), SR.ArgumentNull_Type); + } + + throw new SerializationException(SR.Format(SR.Serialization_InvalidType, type)); + } + + object? obj = null; + GetUninitializedObject(new QCallTypeHandle(ref rt), ObjectHandleOnStack.Create(ref obj)); + return obj!; + } + + [DllImport(RuntimeHelpers.QCall)] + private static extern void GetUninitializedObject(QCallTypeHandle type, ObjectHandleOnStack retObject); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern object AllocateUninitializedClone(object obj); @@ -280,11 +303,11 @@ public static IntPtr AllocateTypeAssociatedMemory(Type type, int size) if (size < 0) throw new ArgumentOutOfRangeException(nameof(size)); - return AllocateTypeAssociatedMemoryInternal(new QCallTypeHandle(ref rt), (uint)size); + return AllocateTypeAssociatedMemory(new QCallTypeHandle(ref rt), (uint)size); } [DllImport(RuntimeHelpers.QCall)] - private static extern IntPtr AllocateTypeAssociatedMemoryInternal(QCallTypeHandle type, uint size); + private static extern IntPtr AllocateTypeAssociatedMemory(QCallTypeHandle type, uint size); [MethodImpl(MethodImplOptions.InternalCall)] private static extern IntPtr AllocTailCallArgBuffer(int size, IntPtr gcDesc); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs index 8bf969b604081c..cfa743db019e29 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs @@ -200,7 +200,7 @@ private static void PrelinkCore(MethodInfo m) private static object PtrToStructureHelper(IntPtr ptr, Type structureType) { var rt = (RuntimeType)structureType; - object structure = rt.CreateInstanceDefaultCtor(publicOnly: false, skipCheckThis: false, fillCache: false, wrapExceptions: true)!; + object structure = rt.CreateInstanceDefaultCtor(publicOnly: false, wrapExceptions: true)!; PtrToStructureHelper(ptr, structure, allowValueClasses: true); return structure; } diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs index f8ff5504380a7e..fbca319a20c229 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -1218,16 +1218,10 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) public unsafe struct ModuleHandle { - // Returns handle for interop with EE. The handle is guaranteed to be non-null. #region Public Static Members - public static readonly ModuleHandle EmptyHandle = GetEmptyMH(); + public static readonly ModuleHandle EmptyHandle; #endregion - private static ModuleHandle GetEmptyMH() - { - return default; - } - #region Private Data Members private readonly RuntimeModule m_ptr; #endregion diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs index a3d0c9a840b9d4..6e2c218e31bfa0 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -3895,7 +3895,7 @@ private void CreateInstanceCheckThis() if (args.Length == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0 && (IsGenericCOMObjectImpl() || IsValueType)) { - instance = CreateInstanceDefaultCtor(publicOnly, skipCheckThis: false, fillCache: true, wrapExceptions); + instance = CreateInstanceDefaultCtor(publicOnly, wrapExceptions); } else { @@ -3967,7 +3967,7 @@ private void CreateInstanceCheckThis() /// [DebuggerStepThrough] [DebuggerHidden] - internal object? CreateInstanceDefaultCtor(bool publicOnly, bool skipCheckThis, bool fillCache, bool wrapExceptions) + internal object? CreateInstanceDefaultCtor(bool publicOnly, bool wrapExceptions) { // Get or create the cached factory. Creating the cache will fail if one // of our invariant checks fails; e.g., no appropriate ctor found. diff --git a/src/coreclr/src/vm/corelib.h b/src/coreclr/src/vm/corelib.h index fd22fe782981f9..0a1b8f69ebabb2 100644 --- a/src/coreclr/src/vm/corelib.h +++ b/src/coreclr/src/vm/corelib.h @@ -700,7 +700,7 @@ DEFINE_METHOD(RUNTIME_HELPERS, IS_BITWISE_EQUATABLE, IsBitwiseEquatable, DEFINE_METHOD(RUNTIME_HELPERS, GET_METHOD_TABLE, GetMethodTable, NoSig) DEFINE_METHOD(RUNTIME_HELPERS, GET_RAW_DATA, GetRawData, NoSig) DEFINE_METHOD(RUNTIME_HELPERS, GET_RAW_ARRAY_DATA, GetRawArrayData, NoSig) -DEFINE_METHOD(RUNTIME_HELPERS, GET_UNINITIALIZED_OBJECT, GetUninitializedObject, NoSig) +DEFINE_METHOD(RUNTIME_HELPERS, GET_UNINITIALIZED_OBJECT, GetUninitializedObject, SM_Type_RetObj) DEFINE_METHOD(RUNTIME_HELPERS, ENUM_EQUALS, EnumEquals, NoSig) DEFINE_METHOD(RUNTIME_HELPERS, ENUM_COMPARE_TO, EnumCompareTo, NoSig) DEFINE_METHOD(RUNTIME_HELPERS, ALLOC_TAILCALL_ARG_BUFFER, AllocTailCallArgBuffer, SM_Int_IntPtr_RetIntPtr) diff --git a/src/coreclr/src/vm/ecalllist.h b/src/coreclr/src/vm/ecalllist.h index 00cb622a7046de..15468724e0fb9f 100644 --- a/src/coreclr/src/vm/ecalllist.h +++ b/src/coreclr/src/vm/ecalllist.h @@ -871,18 +871,18 @@ FCFuncEnd() FCFuncStart(gRuntimeHelpers) FCFuncElement("GetObjectValue", ObjectNative::GetObjectValue) FCIntrinsic("InitializeArray", ArrayNative::InitializeArray, CORINFO_INTRINSIC_InitializeArray) - FCFuncElement("_RunClassConstructor", ReflectionInvocation::RunClassConstructor) - FCFuncElement("_RunModuleConstructor", ReflectionInvocation::RunModuleConstructor) - QCFuncElement("_CompileMethod", ReflectionInvocation::CompileMethod) - FCFuncElement("_PrepareMethod", ReflectionInvocation::PrepareMethod) + QCFuncElement("RunClassConstructor", ReflectionInvocation::RunClassConstructor) + QCFuncElement("RunModuleConstructor", ReflectionInvocation::RunModuleConstructor) + QCFuncElement("CompileMethod", ReflectionInvocation::CompileMethod) + QCFuncElement("PrepareMethod", ReflectionInvocation::PrepareMethod) FCFuncElement("PrepareDelegate", ReflectionInvocation::PrepareDelegate) FCFuncElement("GetHashCode", ObjectNative::GetHashCode) FCFuncElement("Equals", ObjectNative::Equals) FCFuncElement("AllocateUninitializedClone", ObjectNative::AllocateUninitializedClone) FCFuncElement("EnsureSufficientExecutionStack", ReflectionInvocation::EnsureSufficientExecutionStack) FCFuncElement("TryEnsureSufficientExecutionStack", ReflectionInvocation::TryEnsureSufficientExecutionStack) - FCFuncElement("GetUninitializedObjectInternal", ReflectionSerialization::GetUninitializedObject) - QCFuncElement("AllocateTypeAssociatedMemoryInternal", RuntimeTypeHandle::AllocateTypeAssociatedMemory) + QCFuncElement("GetUninitializedObject", ReflectionSerialization::GetUninitializedObject) + QCFuncElement("AllocateTypeAssociatedMemory", RuntimeTypeHandle::AllocateTypeAssociatedMemory) FCFuncElement("AllocTailCallArgBuffer", TailCallHelp::AllocTailCallArgBuffer) FCFuncElement("GetTailCallInfo", TailCallHelp::GetTailCallInfo) FCFuncElement("GetILBytesJitted", GetJittedBytes) diff --git a/src/coreclr/src/vm/metasig.h b/src/coreclr/src/vm/metasig.h index c9856714883b82..84948f65242cdb 100644 --- a/src/coreclr/src/vm/metasig.h +++ b/src/coreclr/src/vm/metasig.h @@ -352,6 +352,7 @@ DEFINE_METASIG(SM(Int_Str_IntPtr_Int_RetVoid, i s I i, v)) DEFINE_METASIG(SM(Str_IntPtr_RetIntPtr, s I, I)) DEFINE_METASIG(SM(Str_Bool_Int_RetV, s F i, v)) +DEFINE_METASIG_T(SM(Type_RetObj, C(TYPE), j)) DEFINE_METASIG_T(SM(Type_RetInt, C(TYPE), i)) DEFINE_METASIG(SM(ArrByte_RetObj, a(b), j)) DEFINE_METASIG(SM(ArrByte_Bool_RetObj, a(b) F, j)) diff --git a/src/coreclr/src/vm/reflectioninvocation.cpp b/src/coreclr/src/vm/reflectioninvocation.cpp index cef2ecb6d96c36..d1f48ed93e6ada 100644 --- a/src/coreclr/src/vm/reflectioninvocation.cpp +++ b/src/coreclr/src/vm/reflectioninvocation.cpp @@ -1583,72 +1583,44 @@ void QCALLTYPE ReflectionInvocation::CompileMethod(MethodDesc * pMD) } // This method triggers the class constructor for a give type -FCIMPL1(void, ReflectionInvocation::RunClassConstructor, ReflectClassBaseObject *pTypeUNSAFE) +void QCALLTYPE ReflectionInvocation::RunClassConstructor(QCall::TypeHandle pType) { - FCALL_CONTRACT; - - REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE); - - if (refType == NULL) - FCThrowArgumentVoidEx(kArgumentException, NULL, W("InvalidOperation_HandleIsNotInitialized")); + QCALL_CONTRACT; - TypeHandle typeHnd = refType->GetType(); + TypeHandle typeHnd = pType.AsTypeHandle(); if (typeHnd.IsTypeDesc()) return; MethodTable *pMT = typeHnd.AsMethodTable(); + if (pMT->IsClassInited()) + return; - Assembly *pAssem = pMT->GetAssembly(); - - if (!pMT->IsClassInited()) - { - HELPER_METHOD_FRAME_BEGIN_1(refType); - - pMT->CheckRestore(); - pMT->EnsureInstanceActive(); - pMT->CheckRunClassInitThrowing(); - - HELPER_METHOD_FRAME_END(); - } + BEGIN_QCALL; + pMT->CheckRestore(); + pMT->EnsureInstanceActive(); + pMT->CheckRunClassInitThrowing(); + END_QCALL; } -FCIMPLEND // This method triggers the module constructor for a give module -FCIMPL1(void, ReflectionInvocation::RunModuleConstructor, ReflectModuleBaseObject *pModuleUNSAFE) { - FCALL_CONTRACT; - - REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE); - - if(refModule == NULL) - FCThrowArgumentVoidEx(kArgumentException, NULL, W("InvalidOperation_HandleIsNotInitialized")); - - Module *pModule = refModule->GetModule(); - - Assembly *pAssem = pModule->GetAssembly(); +void QCALLTYPE ReflectionInvocation::RunModuleConstructor(QCall::ModuleHandle pModule) +{ + QCALL_CONTRACT; DomainFile *pDomainFile = pModule->GetDomainFile(); - if (pDomainFile==NULL || !pDomainFile->IsActive()) - { - HELPER_METHOD_FRAME_BEGIN_1(refModule); - if(pDomainFile==NULL) - pDomainFile=pModule->GetDomainFile(); - pDomainFile->EnsureActive(); - HELPER_METHOD_FRAME_END(); - } + if (pDomainFile != NULL && pDomainFile->IsActive()) + return; + + BEGIN_QCALL; + if(pDomainFile == NULL) + pDomainFile = pModule->GetDomainFile(); + pDomainFile->EnsureActive(); + END_QCALL; } -FCIMPLEND static void PrepareMethodHelper(MethodDesc * pMD) { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - GCX_PREEMP(); + STANDARD_VM_CONTRACT; pMD->EnsureActive(); @@ -1665,23 +1637,16 @@ static void PrepareMethodHelper(MethodDesc * pMD) // This method triggers a given method to be jitted. CoreCLR implementation of this method triggers jiting of the given method only. // It does not walk a subset of callgraph to provide CER guarantees. -FCIMPL3(void, ReflectionInvocation::PrepareMethod, ReflectMethodObject* pMethodUNSAFE, TypeHandle *pInstantiation, UINT32 cInstantiation) +void QCALLTYPE ReflectionInvocation::PrepareMethod(MethodDesc *pMD, TypeHandle *pInstantiation, UINT32 cInstantiation) { CONTRACTL { - FCALL_CHECK; - PRECONDITION(CheckPointer(pMethodUNSAFE, NULL_OK)); + QCALL_CHECK; + PRECONDITION(pMD != NULL); PRECONDITION(CheckPointer(pInstantiation, NULL_OK)); } CONTRACTL_END; - REFLECTMETHODREF refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE); - - HELPER_METHOD_FRAME_BEGIN_1(refMethod); - - if (refMethod == NULL) - COMPlusThrow(kArgumentException, W("InvalidOperation_HandleIsNotInitialized")); - - MethodDesc *pMD = refMethod->GetMethod(); + BEGIN_QCALL; if (pMD->IsAbstract()) COMPlusThrow(kArgumentException, W("Argument_CannotPrepareAbstract")); @@ -1718,9 +1683,8 @@ FCIMPL3(void, ReflectionInvocation::PrepareMethod, ReflectMethodObject* pMethodU PrepareMethodHelper(pMD); - HELPER_METHOD_FRAME_END(); + END_QCALL; } -FCIMPLEND // This method triggers target of a given method to be jitted. CoreCLR implementation of this method triggers jiting // of the given method only. It does not walk a subset of callgraph to provide CER guarantees. @@ -1742,6 +1706,7 @@ FCIMPL1(void, ReflectionInvocation::PrepareDelegate, Object* delegateUNSAFE) MethodDesc *pMD = COMDelegate::GetMethodDesc(delegate); + GCX_PREEMP(); PrepareMethodHelper(pMD); HELPER_METHOD_FRAME_END(); @@ -2011,13 +1976,7 @@ void RuntimeTypeHandle::ValidateTypeAbleToBeInstantiated( TypeHandle typeHandle, bool fGetUninitializedObject) { - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; + STANDARD_VM_CONTRACT; // Don't allow void if (typeHandle.GetSignatureCorElementType() == ELEMENT_TYPE_VOID) @@ -2260,23 +2219,18 @@ FCIMPLEND //************************************************************************************************* //************************************************************************************************* //************************************************************************************************* -FCIMPL1(Object*, ReflectionSerialization::GetUninitializedObject, ReflectClassBaseObject* objTypeUNSAFE) { - FCALL_CONTRACT; - - OBJECTREF retVal = NULL; - REFLECTCLASSBASEREF objType = (REFLECTCLASSBASEREF) objTypeUNSAFE; +void QCALLTYPE ReflectionSerialization::GetUninitializedObject(QCall::TypeHandle pType, QCall::ObjectHandleOnStack retObject) +{ + QCALL_CONTRACT; - HELPER_METHOD_FRAME_BEGIN_RET_NOPOLL(); + BEGIN_QCALL; - TypeHandle type = objType->GetType(); + TypeHandle type = pType.AsTypeHandle(); RuntimeTypeHandle::ValidateTypeAbleToBeInstantiated(type, true /* fForGetUninitializedInstance */); MethodTable* pMT = type.AsMethodTable(); - // Never allow the allocation of an unitialized ContextBoundObject derived type, these must always be created with a paired - // transparent proxy or the jit will get confused. - #ifdef FEATURE_COMINTEROP // Also do not allow allocation of uninitialized RCWs (COM objects). if (pMT->IsComObjectType()) @@ -2284,16 +2238,17 @@ FCIMPL1(Object*, ReflectionSerialization::GetUninitializedObject, ReflectClassBa #endif // FEATURE_COMINTEROP // If it is a nullable, return the underlying type instead. - if (Nullable::IsNullableType(pMT)) + if (pMT->IsNullable()) pMT = pMT->GetInstantiation()[0].GetMethodTable(); - // Allocation will invoke any precise static cctors as needed. - retVal = pMT->Allocate(); + { + GCX_COOP(); + // Allocation will invoke any precise static cctors as needed. + retObject.Set(pMT->Allocate()); + } - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(retVal); + END_QCALL; } -FCIMPLEND //************************************************************************************************* //************************************************************************************************* diff --git a/src/coreclr/src/vm/reflectioninvocation.h b/src/coreclr/src/vm/reflectioninvocation.h index bd358e8df7fb40..c00c17c883ac84 100644 --- a/src/coreclr/src/vm/reflectioninvocation.h +++ b/src/coreclr/src/vm/reflectioninvocation.h @@ -48,9 +48,15 @@ class ReflectionInvocation { static void QCALLTYPE CompileMethod(MethodDesc * pMD); - static FCDECL1(void, RunClassConstructor, ReflectClassBaseObject *pTypeUNSAFE); - static FCDECL1(void, RunModuleConstructor, ReflectModuleBaseObject *pModuleUNSAFE); - static FCDECL3(void, PrepareMethod, ReflectMethodObject* pMethodUNSAFE, TypeHandle *pInstantiation, UINT32 cInstantiation); + static + void QCALLTYPE RunClassConstructor(QCall::TypeHandle pType); + + static + void QCALLTYPE RunModuleConstructor(QCall::ModuleHandle pModule); + + static + void QCALLTYPE PrepareMethod(MethodDesc* pMD, TypeHandle *pInstantiation, UINT32 cInstantiation); + static FCDECL1(void, PrepareDelegate, Object* delegateUNSAFE); static FCDECL1(void, PrepareContractedDelegate, Object* delegateUNSAFE); static FCDECL0(void, ProbeForSufficientStack); @@ -74,7 +80,8 @@ class ReflectionInvocation { class ReflectionSerialization { public: - static FCDECL1(Object*, GetUninitializedObject, ReflectClassBaseObject* objTypeUNSAFE); + static + void QCALLTYPE GetUninitializedObject(QCall::TypeHandle pType, QCall::ObjectHandleOnStack retObject); }; class ReflectionEnum { diff --git a/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs index 09d3bdf608c218..96ac22ef364295 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs @@ -91,10 +91,10 @@ public static partial class Activator if (type is null) throw new ArgumentNullException(nameof(type)); - if (type.UnderlyingSystemType is RuntimeType rt) - return rt.CreateInstanceDefaultCtor(publicOnly: !nonPublic, skipCheckThis: false, fillCache: true, wrapExceptions: wrapExceptions); + if (type.UnderlyingSystemType is not RuntimeType rt) + throw new ArgumentException(SR.Arg_MustBeType, nameof(type)); - throw new ArgumentException(SR.Arg_MustBeType, nameof(type)); + return rt.CreateInstanceDefaultCtor(publicOnly: !nonPublic, wrapExceptions: wrapExceptions); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", @@ -148,7 +148,7 @@ public static partial class Activator [System.Runtime.CompilerServices.Intrinsic] public static T CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>() { - return (T)((RuntimeType)typeof(T)).CreateInstanceDefaultCtor(publicOnly: true, skipCheckThis: true, fillCache: true, wrapExceptions: true)!; + return (T)((RuntimeType)typeof(T)).CreateInstanceDefaultCtor(publicOnly: true, wrapExceptions: true)!; } private static T CreateDefaultInstance() where T : struct => default; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs index a20b0718e34d8d..f71aabd94e6ef8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs @@ -47,7 +47,7 @@ internal StackCrawlMarkHandle(ref StackCrawlMark stackMark) } } - // Wraps RuntimeModule into a handle. Used to pass RuntimeModule to native code wihtout letting it be collected + // Wraps RuntimeModule into a handle. Used to pass RuntimeModule to native code without letting it be collected internal unsafe ref struct QCallModule { private void* _ptr; @@ -66,7 +66,7 @@ internal QCallModule(ref System.Reflection.Emit.ModuleBuilder module) } } - // Wraps RuntimeAssembly into a handle. Used to pass RuntimeAssembly to native code wihtout letting it be collected + // Wraps RuntimeAssembly into a handle. Used to pass RuntimeAssembly to native code without letting it be collected internal unsafe ref struct QCallAssembly { private void* _ptr; @@ -79,7 +79,7 @@ internal QCallAssembly(ref System.Reflection.RuntimeAssembly assembly) } } - // Wraps RuntimeType into a handle. Used to pass RuntimeType to native code wihtout letting it be collected + // Wraps RuntimeType into a handle. Used to pass RuntimeType to native code without letting it be collected internal unsafe ref struct QCallTypeHandle { private void* _ptr; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs index 727a1bee1a359f..5b91776722c59a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs @@ -3,7 +3,6 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; -using System.Runtime.Serialization; using System.Reflection; using Internal.Runtime.CompilerServices; @@ -66,28 +65,6 @@ ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), offset), return dest; } - public static object GetUninitializedObject( - // This API doesn't call any constructors, but the type needs to be seen as constructed. - // A type is seen as constructed if a constructor is kept. - // This obviously won't cover a type with no constructor. Reference types with no - // constructor are an academic problem. Valuetypes with no constructors are a problem, - // but IL Linker currently treats them as always implicitly boxed. - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] - Type type) - { - if (type is null) - { - throw new ArgumentNullException(nameof(type), SR.ArgumentNull_Type); - } - - if (!type.IsRuntimeImplemented()) - { - throw new SerializationException(SR.Format(SR.Serialization_InvalidType, type.ToString())); - } - - return GetUninitializedObjectInternal(type); - } - [Obsolete(Obsoletions.ConstrainedExecutionRegionMessage, DiagnosticId = Obsoletions.ConstrainedExecutionRegionDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] public static void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, object? userData) { diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs index 9dc704ced44648..57876c8e59ec62 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.Mono.cs @@ -1,5 +1,7 @@ // 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.CodeAnalysis; +using System.Runtime.Serialization; using Internal.Runtime.CompilerServices; namespace System.Runtime.CompilerServices @@ -129,9 +131,26 @@ internal static bool ObjectHasReferences(object obj) return RuntimeTypeHandle.HasReferences(obj.GetType() as RuntimeType); } - private static object GetUninitializedObjectInternal(Type type) + public static object GetUninitializedObject( + // This API doesn't call any constructors, but the type needs to be seen as constructed. + // A type is seen as constructed if a constructor is kept. + // This obviously won't cover a type with no constructor. Reference types with no + // constructor are an academic problem. Valuetypes with no constructors are a problem, + // but IL Linker currently treats them as always implicitly boxed. + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + Type type) { - return GetUninitializedObjectInternal(new RuntimeTypeHandle((RuntimeType)type).Value); + if (type is not RuntimeType rt) + { + if (type is null) + { + throw new ArgumentNullException(nameof(type), SR.ArgumentNull_Type); + } + + throw new SerializationException(SR.Format(SR.Serialization_InvalidType, type)); + } + + return GetUninitializedObjectInternal(new RuntimeTypeHandle(rt).Value); } [MethodImplAttribute(MethodImplOptions.InternalCall)] diff --git a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs index 66b0bbb9b4f80c..eb514d171cf690 100644 --- a/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/netcore/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -1726,7 +1726,7 @@ private void CreateInstanceCheckThis() if (argCnt == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0 && (IsValueType)) { - server = CreateInstanceDefaultCtor(publicOnly, false, true, wrapExceptions); + server = CreateInstanceDefaultCtor(publicOnly, wrapExceptions); } else { @@ -1809,15 +1809,16 @@ private void CreateInstanceCheckThis() } // Helper to invoke the default (parameterless) ctor. - // fillCache is set in the SL2/3 compat mode or when called from Marshal.PtrToStructure. [DebuggerStepThroughAttribute] [Diagnostics.DebuggerHidden] - internal object? CreateInstanceDefaultCtor(bool publicOnly, bool skipCheckThis, bool fillCache, bool wrapExceptions) + internal object? CreateInstanceDefaultCtor(bool publicOnly, bool wrapExceptions) { if (IsByRefLike) throw new NotSupportedException(SR.NotSupported_ByRefLike); - return CreateInstanceSlow(publicOnly, wrapExceptions, skipCheckThis, fillCache); + CreateInstanceCheckThis(); + + return CreateInstanceMono(!publicOnly, wrapExceptions); } #endregion @@ -1923,21 +1924,6 @@ internal override FieldInfo GetField(FieldInfo fromNoninstanciated) return m_serializationCtor; } - internal object? CreateInstanceSlow(bool publicOnly, bool wrapExceptions, bool skipCheckThis, bool fillCache) - { - //bool bNeedSecurityCheck = true; - //bool bCanBeCached = false; - //bool bSecurityCheckOff = false; - - if (!skipCheckThis) - CreateInstanceCheckThis(); - - //if (!fillCache) - // bSecurityCheckOff = true; - - return CreateInstanceMono(!publicOnly, wrapExceptions); - } - private object? CreateInstanceMono(bool nonPublic, bool wrapExceptions) { RuntimeConstructorInfo? ctor = GetDefaultConstructor();