diff --git a/src/coreclr/System.Private.CoreLib/src/System/Object.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Object.CoreCLR.cs index a390ec6c03bc8..70cff629fc28e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Object.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Object.CoreCLR.cs @@ -17,7 +17,7 @@ public partial class Object // so that other object may only call this method on themselves. It is intended to // support the ICloneable interface. [Intrinsic] - protected unsafe object MemberwiseClone() + protected internal unsafe object MemberwiseClone() { object clone = RuntimeHelpers.AllocateUninitializedClone(this); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index a931499ac7e2d..6cb159ce33ef4 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -37,9 +37,23 @@ public static partial class RuntimeHelpers // cloned when you pass them around, and are always passed by value. // Of course, reference types are not cloned. // - [MethodImpl(MethodImplOptions.InternalCall)] [return: NotNullIfNotNull(nameof(obj))] - public static extern object? GetObjectValue(object? obj); + public static unsafe object? GetObjectValue(object? obj) + { + if (obj == null) + return null; + + MethodTable* pMT = GetMethodTable(obj); + + if (!pMT->IsValueType || pMT->IsPrimitive) + return obj; + + // Technically we could return boxed DateTimes and Decimals without + // copying them here, but VB realized that this would be a breaking change + // for their customers. So copy them. + + return obj.MemberwiseClone(); + } // RunClassConstructor causes the class constructor for the given type to be triggered // in the current domain. After this call returns, the class constructor is guaranteed to @@ -487,6 +501,8 @@ internal unsafe struct MethodTable private const uint enum_flag_Category_Mask = 0x000F0000; private const uint enum_flag_Category_ValueType = 0x00040000; private const uint enum_flag_Category_Nullable = 0x00050000; + private const uint enum_flag_Category_PrimitiveValueType = 0x00060000; // sub-category of ValueType, Enum or primitive value type + private const uint enum_flag_Category_TruePrimitive = 0x00070000; // sub-category of ValueType, Primitive (ELEMENT_TYPE_I, etc.) private const uint enum_flag_Category_ValueType_Mask = 0x000C0000; private const uint enum_flag_Category_Interface = 0x000C0000; // Types that require non-trivial interface cast have this bit set in the category @@ -565,6 +581,9 @@ public int MultiDimensionalArrayRank public bool IsByRefLike => (Flags & (enum_flag_HasComponentSize | enum_flag_IsByRefLike)) == enum_flag_IsByRefLike; + // Warning! UNLIKE the similarly named Reflection api, this method also returns "true" for Enums. + public bool IsPrimitive => (Flags & enum_flag_Category_Mask) is enum_flag_Category_PrimitiveValueType or enum_flag_Category_TruePrimitive; + public bool HasInstantiation => (Flags & enum_flag_HasComponentSize) == 0 && (Flags & enum_flag_GenericsMask) != enum_flag_GenericsMask_NonGeneric; public bool IsGenericTypeDefinition => (Flags & (enum_flag_HasComponentSize | enum_flag_GenericsMask)) == enum_flag_GenericsMask_TypicalInst; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs index ee7a472b02410..53819b2cc59ce 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace System.Runtime { @@ -26,7 +27,7 @@ namespace System.Runtime /// properties are instead thread-safe, and safe to use if is not concurrently invoked as well. /// /// - public struct DependentHandle : IDisposable + public partial struct DependentHandle : IDisposable { // ========================================================================================= // This struct collects all operations on native DependentHandles. The DependentHandle @@ -62,8 +63,10 @@ public struct DependentHandle : IDisposable /// The dependent object instance to associate with . public DependentHandle(object? target, object? dependent) { - // no need to check for null result: InternalInitialize expected to throw OOM. - _handle = InternalInitialize(target, dependent); + IntPtr handle = InternalAlloc(target, dependent); + if (handle == 0) + handle = InternalAllocWithGCTransition(target, dependent); + _handle = handle; } /// @@ -71,7 +74,7 @@ public DependentHandle(object? target, object? dependent) /// and has not yet been disposed. /// /// This property is thread-safe. - public readonly bool IsAllocated => (nint)_handle != 0; + public readonly bool IsAllocated => _handle != 0; /// /// Gets or sets the target object instance for the current handle. The target can only be set to a value @@ -87,7 +90,7 @@ readonly get { IntPtr handle = _handle; - if ((nint)handle == 0) + if (handle == 0) { ThrowHelper.ThrowInvalidOperationException(); } @@ -98,7 +101,7 @@ readonly get { IntPtr handle = _handle; - if ((nint)handle == 0 || value is not null) + if (handle == 0 || value is not null) { ThrowHelper.ThrowInvalidOperationException(); } @@ -124,7 +127,7 @@ readonly get { IntPtr handle = _handle; - if ((nint)handle == 0) + if (handle == 0) { ThrowHelper.ThrowInvalidOperationException(); } @@ -135,7 +138,7 @@ readonly get { IntPtr handle = _handle; - if ((nint)handle == 0) + if (handle == 0) { ThrowHelper.ThrowInvalidOperationException(); } @@ -160,7 +163,7 @@ public readonly (object? Target, object? Dependent) TargetAndDependent { IntPtr handle = _handle; - if ((nint)handle == 0) + if (handle == 0) { ThrowHelper.ThrowInvalidOperationException(); } @@ -222,16 +225,26 @@ public void Dispose() // (if not already there) and frees the handle if needed. IntPtr handle = _handle; - if ((nint)handle != 0) + if (handle != 0) { - _handle = IntPtr.Zero; + _handle = 0; - InternalFree(handle); + if (!InternalFree(handle)) + { + InternalFreeWithGCTransition(handle); + } } } [MethodImpl(MethodImplOptions.InternalCall)] - private static extern IntPtr InternalInitialize(object? target, object? dependent); + private static extern IntPtr InternalAlloc(object? target, object? dependent); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static IntPtr InternalAllocWithGCTransition(object? target, object? dependent) + => _InternalAllocWithGCTransition(ObjectHandleOnStack.Create(ref target), ObjectHandleOnStack.Create(ref dependent)); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DependentHandle_InternalAllocWithGCTransition")] + private static partial IntPtr _InternalAllocWithGCTransition(ObjectHandleOnStack target, ObjectHandleOnStack dependent); #if DEBUG [MethodImpl(MethodImplOptions.InternalCall)] @@ -258,6 +271,13 @@ public void Dispose() private static extern void InternalSetTargetToNull(IntPtr dependentHandle); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void InternalFree(IntPtr dependentHandle); + private static extern bool InternalFree(IntPtr dependentHandle); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void InternalFreeWithGCTransition(IntPtr dependentHandle) + => _InternalFreeWithGCTransition(dependentHandle); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "DependentHandle_InternalFreeWithGCTransition")] + private static partial void _InternalFreeWithGCTransition(IntPtr dependentHandle); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs index c62d6aeb75fe4..1238b029598d0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs @@ -7,11 +7,39 @@ namespace System.Runtime.InteropServices { public partial struct GCHandle { + internal static IntPtr InternalAlloc(object? value, GCHandleType type) + { + IntPtr handle = _InternalAlloc(value, type); + if (handle == 0) + handle = InternalAllocWithGCTransition(value, type); + return handle; + } + [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern IntPtr InternalAlloc(object? value, GCHandleType type); + private static extern IntPtr _InternalAlloc(object? value, GCHandleType type); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static IntPtr InternalAllocWithGCTransition(object? value, GCHandleType type) + => _InternalAllocWithGCTransition(ObjectHandleOnStack.Create(ref value), type); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "GCHandle_InternalAllocWithGCTransition")] + private static partial IntPtr _InternalAllocWithGCTransition(ObjectHandleOnStack value, GCHandleType type); + + internal static void InternalFree(IntPtr handle) + { + if (!_InternalFree(handle)) + InternalFreeWithGCTransition(handle); + } [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void InternalFree(IntPtr handle); + private static extern bool _InternalFree(IntPtr handle); + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void InternalFreeWithGCTransition(IntPtr dependentHandle) + => _InternalFreeWithGCTransition(dependentHandle); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "GCHandle_InternalFreeWithGCTransition")] + private static partial void _InternalFreeWithGCTransition(IntPtr dependentHandle); #if DEBUG // The runtime performs additional checks in debug builds diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs index 43c680cedfe0d..2ccb7ff256847 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs @@ -24,8 +24,11 @@ public static partial class Marshal internal static Guid IID_IUnknown = new Guid(0, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46); #endif //FEATURE_COMINTEROP - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern int SizeOfHelper(Type t, bool throwIfNotMarshalable); + internal static int SizeOfHelper(RuntimeType t, [MarshalAs(UnmanagedType.Bool)] bool throwIfNotMarshalable) + => SizeOfHelper(new QCallTypeHandle(ref t), throwIfNotMarshalable); + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MarshalNative_SizeOfHelper")] + private static partial int SizeOfHelper(QCallTypeHandle t, [MarshalAs(UnmanagedType.Bool)] bool throwIfNotMarshalable); [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "Trimming doesn't affect types eligible for marshalling. Different exception for invalid inputs doesn't matter.")] @@ -234,24 +237,95 @@ private static void PrelinkCore(MethodInfo m) /// true, this routine will call DestroyStructure() first. /// [RequiresDynamicCode("Marshalling code for the object might not be available. Use the StructureToPtr overload instead.")] - [MethodImpl(MethodImplOptions.InternalCall)] [EditorBrowsable(EditorBrowsableState.Never)] - public static extern void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld); + public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld) + { + ArgumentNullException.ThrowIfNull(ptr); + ArgumentNullException.ThrowIfNull(structure); + + MethodTable* pMT = RuntimeHelpers.GetMethodTable(structure); + + if (pMT->HasInstantiation) + throw new ArgumentException(SR.Argument_NeedNonGenericObject, nameof(structure)); + + delegate* structMarshalStub; + nuint size; + if (!TryGetStructMarshalStub((IntPtr)pMT, &structMarshalStub, &size)) + throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, nameof(structure)); + + if (structMarshalStub != null) + { + if (fDeleteOld) + { + structMarshalStub(ref structure.GetRawData(), (byte*)ptr, MarshalOperation.Cleanup, ref Unsafe.NullRef()); + } + + structMarshalStub(ref structure.GetRawData(), (byte*)ptr, MarshalOperation.Marshal, ref Unsafe.NullRef()); + } + else + { + Buffer.Memmove(ref *(byte*)ptr, ref structure.GetRawData(), size); + } + } /// /// Helper function to copy a pointer into a preallocated structure. /// - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void PtrToStructureHelper(IntPtr ptr, object structure, bool allowValueClasses); + private static unsafe void PtrToStructureHelper(IntPtr ptr, object structure, bool allowValueClasses) + { + MethodTable* pMT = RuntimeHelpers.GetMethodTable(structure); + + if (!allowValueClasses && pMT->IsValueType) + throw new ArgumentException(SR.Argument_StructMustNotBeValueClass, nameof(structure)); + + delegate* structMarshalStub; + nuint size; + if (!TryGetStructMarshalStub((IntPtr)pMT, &structMarshalStub, &size)) + throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, nameof(structure)); + + if (structMarshalStub != null) + { + structMarshalStub(ref structure.GetRawData(), (byte*)ptr, MarshalOperation.Unmarshal, ref Unsafe.NullRef()); + } + else + { + Buffer.Memmove(ref structure.GetRawData(), ref *(byte*)ptr, size); + } + } /// /// Frees all substructures pointed to by the native memory block. - /// "structuretype" is used to provide layout information. + /// nameof(structuretype) is used to provide layout information. /// [RequiresDynamicCode("Marshalling code for the object might not be available. Use the DestroyStructure overload instead.")] - [MethodImpl(MethodImplOptions.InternalCall)] [EditorBrowsable(EditorBrowsableState.Never)] - public static extern void DestroyStructure(IntPtr ptr, Type structuretype); + public static unsafe void DestroyStructure(IntPtr ptr, Type structuretype) + { + ArgumentNullException.ThrowIfNull(ptr); + ArgumentNullException.ThrowIfNull(structuretype); + + if (structuretype is not RuntimeType rt) + throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(structuretype)); + + if (rt.IsGenericType) + throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(structuretype)); + + delegate* structMarshalStub; + nuint size; + if (!TryGetStructMarshalStub(rt.GetUnderlyingNativeHandle(), &structMarshalStub, &size)) + throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, nameof(structuretype)); + + GC.KeepAlive(rt); + + if (structMarshalStub != null) + { + structMarshalStub(ref Unsafe.NullRef(), (byte*)ptr, MarshalOperation.Cleanup, ref Unsafe.NullRef()); + } + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MarshalNative_TryGetStructMarshalStub")] + [return: MarshalAs(UnmanagedType.Bool)] + private static unsafe partial bool TryGetStructMarshalStub(IntPtr th, delegate** structMarshalStub, nuint* size); // Note: Callers are required to keep obj alive internal static unsafe bool IsPinnable(object? obj) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 3f7527f06cfc2..c723fed4de9b3 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using System.Text; namespace System.StubHelpers @@ -461,16 +462,37 @@ internal static unsafe string ConvertToManaged(IntPtr nativeHome, int length) } // class WSTRBufferMarshaler #if FEATURE_COMINTEROP - internal static class ObjectMarshaler + internal static partial class ObjectMarshaler { - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void ConvertToNative(object objSrc, IntPtr pDstVariant); + internal static void ConvertToNative(object objSrc, IntPtr pDstVariant) + { + ConvertToNative(ObjectHandleOnStack.Create(ref objSrc), pDstVariant); + } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern object ConvertToManaged(IntPtr pSrcVariant); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ObjectMarshaler_ConvertToNative")] + private static partial void ConvertToNative(ObjectHandleOnStack objSrc, IntPtr pDstVariant); - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void ClearNative(IntPtr pVariant); + internal static object ConvertToManaged(IntPtr pSrcVariant) + { + object? retObject = null; + ConvertToManaged(pSrcVariant, ObjectHandleOnStack.Create(ref retObject)); + return retObject!; + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ObjectMarshaler_ConvertToManaged")] + private static partial void ConvertToManaged(IntPtr pSrcVariant, ObjectHandleOnStack retObject); + + internal static unsafe void ClearNative(IntPtr pVariant) + { + if (pVariant != IntPtr.Zero) + { + Interop.OleAut32.VariantClear(pVariant); + + // VariantClear resets the instance to VT_EMPTY (0) + // COMPAT: Clear the remaining memory for compat. The instance remains set to VT_EMPTY (0). + *(ComVariant*)pVariant = default; + } + } } // class ObjectMarshaler #endif // FEATURE_COMINTEROP @@ -870,7 +892,7 @@ private unsafe IntPtr ConvertLayoutToNative(object pManagedHome, int dwFlags) // of pManagedHome is not marshalable. That's intentional because we // want to maintain the original behavior where this was indicated // by TypeLoadException during the actual field marshaling. - int allocSize = Marshal.SizeOfHelper(pManagedHome.GetType(), false); + int allocSize = Marshal.SizeOfHelper((RuntimeType)pManagedHome.GetType(), false); IntPtr pNativeHome = Marshal.AllocCoTaskMem(allocSize); // marshal the object as class with layout (UnmanagedType.LPStruct) @@ -1001,37 +1023,12 @@ internal void ClearNative(IntPtr pNativeHome) } } // struct AsAnyMarshaler - [StructLayout(LayoutKind.Sequential)] - internal struct NativeVariant + // Constants for direction argument of struct marshalling stub. + internal static class MarshalOperation { - private ushort vt; - private ushort wReserved1; - private ushort wReserved2; - private ushort wReserved3; - - // The union portion of the structure contains at least one 64-bit type that on some 32-bit platforms - // (notably ARM) requires 64-bit alignment. So on 32-bit platforms we'll actually size the variant - // portion of the struct with an Int64 so the type loader notices this requirement (a no-op on x86, - // but on ARM it will allow us to correctly determine the layout of native argument lists containing - // VARIANTs). Note that the field names here don't matter: none of the code refers to these fields, - // the structure just exists to provide size information to the IL marshaler. -#if TARGET_64BIT - private IntPtr data1; - private IntPtr data2; -#else - private long data1; -#endif - } // struct NativeVariant - - // This NativeDecimal type is very similar to the System.Decimal type, except it requires an 8-byte alignment - // like the native DECIMAL type instead of the 4-byte requirement of the System.Decimal type. - [StructLayout(LayoutKind.Sequential)] - internal struct NativeDecimal - { - private ushort reserved; - private ushort signScale; - private uint hi32; - private ulong lo64; + internal const int Marshal = 0; + internal const int Unmarshal = 1; + internal const int Cleanup = 2; } internal abstract class CleanupWorkListElement @@ -1111,7 +1108,7 @@ public IntPtr AddRef() } } // class CleanupWorkListElement - internal static class StubHelpers + internal static partial class StubHelpers { [MethodImpl(MethodImplOptions.InternalCall)] internal static extern IntPtr GetDelegateTarget(Delegate pThis); @@ -1190,8 +1187,8 @@ internal static void SetPendingExceptionObject(Exception? exception) s_pendingExceptionObject = exception; } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern IntPtr CreateCustomMarshalerHelper(IntPtr pMD, int paramToken, IntPtr hndManagedType); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "StubHelpers_CreateCustomMarshalerHelper")] + internal static partial IntPtr CreateCustomMarshalerHelper(IntPtr pMD, int paramToken, IntPtr hndManagedType); //------------------------------------------------------- // SafeHandle Helpers diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Monitor.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Monitor.CoreCLR.cs index 41183e9be8587..fdfc1c333e971 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Monitor.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Monitor.CoreCLR.cs @@ -144,8 +144,9 @@ public static bool IsEntered(object obj) ** ** Exceptions: ArgumentNullException if object is null. ========================================================================*/ - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool ObjWait(int millisecondsTimeout, object obj); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Monitor_Wait")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool Wait(ObjectHandleOnStack obj, int millisecondsTimeout); [UnsupportedOSPlatform("browser")] public static bool Wait(object obj, int millisecondsTimeout) @@ -153,7 +154,7 @@ public static bool Wait(object obj, int millisecondsTimeout) ArgumentNullException.ThrowIfNull(obj); ArgumentOutOfRangeException.ThrowIfLessThan(millisecondsTimeout, -1); - return ObjWait(millisecondsTimeout, obj); + return Wait(ObjectHandleOnStack.Create(ref obj), millisecondsTimeout); } /*======================================================================== @@ -161,26 +162,26 @@ public static bool Wait(object obj, int millisecondsTimeout) * Exceptions: SynchronizationLockException if this method is not called inside * a synchronized block of code. ========================================================================*/ - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void ObjPulse(object obj); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Monitor_Pulse")] + private static partial void Pulse(ObjectHandleOnStack obj); public static void Pulse(object obj) { ArgumentNullException.ThrowIfNull(obj); - ObjPulse(obj); + Pulse(ObjectHandleOnStack.Create(ref obj)); } /*======================================================================== ** Sends a notification to all waiting objects. ========================================================================*/ - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern void ObjPulseAll(object obj); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Monitor_PulseAll")] + private static partial void PulseAll(ObjectHandleOnStack obj); public static void PulseAll(object obj) { ArgumentNullException.ThrowIfNull(obj); - ObjPulseAll(obj); + PulseAll(ObjectHandleOnStack.Create(ref obj)); } /// @@ -188,7 +189,7 @@ public static void PulseAll(object obj) /// public static long LockContentionCount => GetLockContentionCount() + Lock.ContentionCount; - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ObjectNative_GetMonitorLockContentionCount")] + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Monitor_GetLockContentionCount")] private static partial long GetLockContentionCount(); } } diff --git a/src/coreclr/classlibnative/bcltype/objectnative.cpp b/src/coreclr/classlibnative/bcltype/objectnative.cpp index 01192057756d7..4622955b44adf 100644 --- a/src/coreclr/classlibnative/bcltype/objectnative.cpp +++ b/src/coreclr/classlibnative/bcltype/objectnative.cpp @@ -20,52 +20,6 @@ #include "eeconfig.h" -/********************************************************************/ -/* gets an object's 'value'. For normal classes, with reference - based semantics, this means the object's pointer. For boxed - primitive types, it also means just returning the pointer (because - they are immutable), for other value class, it means returning - a boxed copy. */ - -FCIMPL1(Object*, ObjectNative::GetObjectValue, Object* obj) -{ - CONTRACTL - { - FCALL_CHECK; - INJECT_FAULT(FCThrow(kOutOfMemoryException);); - } - CONTRACTL_END; - - VALIDATEOBJECT(obj); - - if (obj == 0) - return(obj); - - MethodTable* pMT = obj->GetMethodTable(); - // optimize for primitive types since GetVerifierCorElementType is slow. - if (pMT->IsTruePrimitive() || TypeHandle(pMT).GetVerifierCorElementType() != ELEMENT_TYPE_VALUETYPE) { - return(obj); - } - - Object* retVal = NULL; - OBJECTREF objRef(obj); - HELPER_METHOD_FRAME_BEGIN_RET_1(objRef); // Set up a frame - - // Technically we could return boxed DateTimes and Decimals without - // copying them here, but VB realized that this would be a breaking change - // for their customers. So copy them. - // - // MethodTable::Box is a cleaner way to copy value class, but it is slower than following code. - // - retVal = OBJECTREFToObject(AllocateObject(pMT)); - CopyValueClass(retVal->GetData(), objRef->GetData(), pMT); - HELPER_METHOD_FRAME_END(); - - return(retVal); -} -FCIMPLEND - - NOINLINE static INT32 GetHashCodeHelper(OBJECTREF objRef) { DWORD idx = 0; @@ -292,56 +246,54 @@ FCIMPL1(Object*, ObjectNative::AllocateUninitializedClone, Object* pObjUNSAFE) } FCIMPLEND -FCIMPL2(FC_BOOL_RET, ObjectNative::WaitTimeout, INT32 Timeout, Object* pThisUNSAFE) +extern "C" BOOL QCALLTYPE Monitor_Wait(QCall::ObjectHandleOnStack pThis, INT32 Timeout) { - FCALL_CONTRACT; + QCALL_CONTRACT; BOOL retVal = FALSE; - OBJECTREF pThis = (OBJECTREF) pThisUNSAFE; - HELPER_METHOD_FRAME_BEGIN_RET_1(pThis); + + BEGIN_QCALL; + + GCX_COOP(); // Arguments validated on managed side - _ASSERTE(pThis != NULL); + _ASSERTE(pThis.Get() != NULL); _ASSERTE(Timeout >= INFINITE_TIMEOUT); - retVal = pThis->Wait(Timeout); + retVal = pThis.Get()->Wait(Timeout); - HELPER_METHOD_FRAME_END(); - FC_RETURN_BOOL(retVal); + END_QCALL; + + return retVal; } -FCIMPLEND -FCIMPL1(void, ObjectNative::Pulse, Object* pThisUNSAFE) +extern "C" void QCALLTYPE Monitor_Pulse(QCall::ObjectHandleOnStack pThis) { - FCALL_CONTRACT; + QCALL_CONTRACT; - OBJECTREF pThis = (OBJECTREF) pThisUNSAFE; - HELPER_METHOD_FRAME_BEGIN_1(pThis); + BEGIN_QCALL; - if (pThis == NULL) - COMPlusThrow(kNullReferenceException, W("NullReference_This")); + GCX_COOP(); - pThis->Pulse(); + _ASSERTE(pThis.Get() != NULL); + pThis.Get()->Pulse(); - HELPER_METHOD_FRAME_END(); + END_QCALL; } -FCIMPLEND -FCIMPL1(void, ObjectNative::PulseAll, Object* pThisUNSAFE) +extern "C" void QCALLTYPE Monitor_PulseAll(QCall::ObjectHandleOnStack pThis) { - FCALL_CONTRACT; + QCALL_CONTRACT; - OBJECTREF pThis = (OBJECTREF) pThisUNSAFE; - HELPER_METHOD_FRAME_BEGIN_1(pThis); + BEGIN_QCALL; - if (pThis == NULL) - COMPlusThrow(kNullReferenceException, W("NullReference_This")); + GCX_COOP(); - pThis->PulseAll(); + _ASSERTE(pThis.Get() != NULL); + pThis.Get()->PulseAll(); - HELPER_METHOD_FRAME_END(); + END_QCALL; } -FCIMPLEND FCIMPL1(FC_BOOL_RET, ObjectNative::IsLockHeld, Object* pThisUNSAFE) { @@ -362,7 +314,7 @@ FCIMPL1(FC_BOOL_RET, ObjectNative::IsLockHeld, Object* pThisUNSAFE) } FCIMPLEND -extern "C" INT64 QCALLTYPE ObjectNative_GetMonitorLockContentionCount() +extern "C" INT64 QCALLTYPE Monitor_GetLockContentionCount() { QCALL_CONTRACT; diff --git a/src/coreclr/classlibnative/bcltype/objectnative.h b/src/coreclr/classlibnative/bcltype/objectnative.h index 819469a983458..d8948922dd0b7 100644 --- a/src/coreclr/classlibnative/bcltype/objectnative.h +++ b/src/coreclr/classlibnative/bcltype/objectnative.h @@ -25,20 +25,17 @@ class ObjectNative { public: - // This method will return a Class object for the object - // iff the Class object has already been created. - // If the Class object doesn't exist then you must call the GetClass() method. - static FCDECL1(Object*, GetObjectValue, Object* vThisRef); static FCDECL1(INT32, GetHashCode, Object* vThisRef); static FCDECL1(INT32, TryGetHashCode, Object* vThisRef); static FCDECL2(FC_BOOL_RET, Equals, Object *pThisRef, Object *pCompareRef); static FCDECL1(Object*, AllocateUninitializedClone, Object* pObjUNSAFE); static FCDECL1(Object*, GetClass, Object* pThis); - static FCDECL2(FC_BOOL_RET, WaitTimeout, INT32 Timeout, Object* pThisUNSAFE); - static FCDECL1(void, Pulse, Object* pThisUNSAFE); - static FCDECL1(void, PulseAll, Object* pThisUNSAFE); static FCDECL1(FC_BOOL_RET, IsLockHeld, Object* pThisUNSAFE); }; -extern "C" INT64 QCALLTYPE ObjectNative_GetMonitorLockContentionCount(); +extern "C" BOOL QCALLTYPE Monitor_Wait(QCall::ObjectHandleOnStack pThis, INT32 Timeout); +extern "C" void QCALLTYPE Monitor_Pulse(QCall::ObjectHandleOnStack pThis); +extern "C" void QCALLTYPE Monitor_PulseAll(QCall::ObjectHandleOnStack pThis); +extern "C" INT64 QCALLTYPE Monitor_GetLockContentionCount(); + #endif // _OBJECTNATIVE_H_ diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index 2b853993311eb..6624968f544b6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -929,10 +929,6 @@ CP0002 M:System.TypedReference.get_IsNull - - CP0014 - M:System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(System.Object)->object?:[T:System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute] - CP0015 M:System.Diagnostics.Tracing.EventSource.Write``1(System.String,``0):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs index 7895376c608ec..3342337435419 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs @@ -58,7 +58,8 @@ public static void RunModuleConstructor(ModuleHandle module) // Nothing to do for the native AOT. All module cctors execute eagerly. } - public static object GetObjectValue(object? obj) + [return: NotNullIfNotNull(nameof(obj))] + public static object? GetObjectValue(object? obj) { if (obj == null) return null; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NativeAot.cs index a3c5c5d9e1884..44903db0e1521 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NativeAot.cs @@ -15,13 +15,10 @@ namespace System.Runtime.InteropServices { public static partial class Marshal { - internal static int SizeOfHelper(Type t, bool throwIfNotMarshalable) + internal static int SizeOfHelper(RuntimeType t, bool throwIfNotMarshalable) { Debug.Assert(throwIfNotMarshalable); - if (t is not RuntimeType) - throw new ArgumentException(SR.Argument_MustBeRuntimeType); - if (t.IsPointer /* or IsFunctionPointer */) return IntPtr.Size; @@ -54,9 +51,6 @@ public static IntPtr OffsetOf(Type t, string fieldName) private static void PtrToStructureHelper(IntPtr ptr, object structure, bool allowValueClasses) { - ArgumentNullException.ThrowIfNull(ptr); - ArgumentNullException.ThrowIfNull(structure); - if (!allowValueClasses && structure.GetEETypePtr().IsValueType) { throw new ArgumentException(SR.Argument_StructMustNotBeValueClass, nameof(structure)); @@ -106,12 +100,12 @@ internal static unsafe void PtrToStructureImpl(IntPtr ptr, object structure) public static unsafe void DestroyStructure(IntPtr ptr, Type structuretype) { ArgumentNullException.ThrowIfNull(ptr); - ArgumentNullException.ThrowIfNull(structuretype, "structureType"); + ArgumentNullException.ThrowIfNull(structuretype, nameof(structuretype)); RuntimeTypeHandle structureTypeHandle = structuretype.TypeHandle; - if (structureTypeHandle.IsGenericType() || structureTypeHandle.IsGenericTypeDefinition()) - throw new ArgumentException(SR.Argument_NeedNonGenericType, "structure"); + if (structureTypeHandle.IsGenericType()) + throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(structuretype)); if (structureTypeHandle.IsEnum() || structureTypeHandle.IsInterface() || @@ -143,14 +137,9 @@ public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDel ArgumentNullException.ThrowIfNull(structure); ArgumentNullException.ThrowIfNull(ptr); - if (fDeleteOld) - { - DestroyStructure(ptr, structure.GetType()); - } - RuntimeTypeHandle structureTypeHandle = structure.GetType().TypeHandle; - if (structureTypeHandle.IsGenericType() || structureTypeHandle.IsGenericTypeDefinition()) + if (structureTypeHandle.IsGenericType()) { throw new ArgumentException(SR.Argument_NeedNonGenericObject, nameof(structure)); } @@ -168,6 +157,11 @@ public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDel marshalStub = RuntimeInteropData.GetStructMarshalStub(structureTypeHandle); } + if (fDeleteOld) + { + DestroyStructure(ptr, structure.GetType()); + } + if (marshalStub != IntPtr.Zero) { if (structureTypeHandle.IsValueType()) diff --git a/src/coreclr/vm/binder.cpp b/src/coreclr/vm/binder.cpp index 23b14a34ee43b..3415ba3a2336a 100644 --- a/src/coreclr/vm/binder.cpp +++ b/src/coreclr/vm/binder.cpp @@ -1122,8 +1122,6 @@ void CoreLibBinder::CheckExtended() #define ASMCONSTANTS_RUNTIME_ASSERT(cond) _ASSERTE(cond) #include "asmconstants.h" - _ASSERTE(sizeof(VARIANT) == CoreLibBinder::GetClass(CLASS__NATIVEVARIANT)->GetNativeSize()); - printf("CheckExtended: completed without exception.\n"); ErrExit: diff --git a/src/coreclr/vm/comdependenthandle.cpp b/src/coreclr/vm/comdependenthandle.cpp index b222190810233..8f78d01b365bc 100644 --- a/src/coreclr/vm/comdependenthandle.cpp +++ b/src/coreclr/vm/comdependenthandle.cpp @@ -5,33 +5,40 @@ // // -// FCall's for the DependentHandle class -// -// Handle functions require cooperative mode, making these fcalls poor candidates for QCall conversion. +// FCalls and QCalls for the DependentHandle class // #include "common.h" #include "comdependenthandle.h" -FCIMPL2(OBJECTHANDLE, DependentHandle::InternalInitialize, Object *_target, Object *_dependent) +FCIMPL2(OBJECTHANDLE, DependentHandle::InternalAlloc, Object *target, Object *dependent) { FCALL_CONTRACT; - OBJECTREF target(_target); - OBJECTREF dependent(_dependent); + // Use slow path if profiler is tracking GC + if (CORProfilerTrackGC()) + return NULL; + + return GetAppDomain()->GetHandleStore()->CreateDependentHandle(target, dependent); +} +FCIMPLEND + +extern "C" OBJECTHANDLE QCALLTYPE DependentHandle_InternalAllocWithGCTransition(QCall::ObjectHandleOnStack target, QCall::ObjectHandleOnStack dependent) +{ + QCALL_CONTRACT; + OBJECTHANDLE result = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_NOPOLL(); + BEGIN_QCALL; - // Create the handle. - result = GetAppDomain()->CreateDependentHandle(target, dependent); + GCX_COOP(); + result = GetAppDomain()->CreateDependentHandle(target.Get(), dependent.Get()); - HELPER_METHOD_FRAME_END_POLL(); + END_QCALL; return result; } -FCIMPLEND FCIMPL1(Object*, DependentHandle::InternalGetTarget, OBJECTHANDLE handle) { @@ -97,16 +104,31 @@ FCIMPL2(VOID, DependentHandle::InternalSetDependent, OBJECTHANDLE handle, Object } FCIMPLEND -FCIMPL1(VOID, DependentHandle::InternalFree, OBJECTHANDLE handle) +FCIMPL1(FC_BOOL_RET, DependentHandle::InternalFree, OBJECTHANDLE handle) { FCALL_CONTRACT; _ASSERTE(handle != NULL); - HELPER_METHOD_FRAME_BEGIN_0(); + // Use slow path if profiler is tracking GC + if (CORProfilerTrackGC()) + FC_RETURN_BOOL(false); DestroyDependentHandle(handle); - - HELPER_METHOD_FRAME_END(); + FC_RETURN_BOOL(true); } FCIMPLEND + +extern "C" void QCALLTYPE DependentHandle_InternalFreeWithGCTransition(OBJECTHANDLE handle) +{ + QCALL_CONTRACT; + + _ASSERTE(handle != NULL); + + BEGIN_QCALL; + + GCX_COOP(); + DestroyDependentHandle(handle); + + END_QCALL; +} diff --git a/src/coreclr/vm/comdependenthandle.h b/src/coreclr/vm/comdependenthandle.h index 06786e6257746..62e94161d884e 100644 --- a/src/coreclr/vm/comdependenthandle.h +++ b/src/coreclr/vm/comdependenthandle.h @@ -40,13 +40,16 @@ class DependentHandle { public: - static FCDECL2(OBJECTHANDLE, InternalInitialize, Object *target, Object *dependent); + static FCDECL2(OBJECTHANDLE, InternalAlloc, Object *target, Object *dependent); static FCDECL1(Object *, InternalGetTarget, OBJECTHANDLE handle); static FCDECL1(Object *, InternalGetDependent, OBJECTHANDLE handle); static FCDECL2(Object *, InternalGetTargetAndDependent, OBJECTHANDLE handle, Object **outDependent); static FCDECL1(VOID, InternalSetTargetToNull, OBJECTHANDLE handle); static FCDECL2(VOID, InternalSetDependent, OBJECTHANDLE handle, Object *dependent); - static FCDECL1(VOID, InternalFree, OBJECTHANDLE handle); + static FCDECL1(FC_BOOL_RET, InternalFree, OBJECTHANDLE handle); }; +extern "C" OBJECTHANDLE QCALLTYPE DependentHandle_InternalAllocWithGCTransition(QCall::ObjectHandleOnStack target, QCall::ObjectHandleOnStack dependent); +extern "C" void QCALLTYPE DependentHandle_InternalFreeWithGCTransition(OBJECTHANDLE handle); + #endif diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 0dd79fb124f82..c3288e8659a6a 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1068,8 +1068,7 @@ DEFINE_METHOD(HANDLE_MARSHALER, CONVERT_SAFEHANDLE_TO_NATIVE,ConvertSaf DEFINE_METHOD(HANDLE_MARSHALER, THROW_SAFEHANDLE_FIELD_CHANGED, ThrowSafeHandleFieldChanged, SM_RetVoid) DEFINE_METHOD(HANDLE_MARSHALER, THROW_CRITICALHANDLE_FIELD_CHANGED, ThrowCriticalHandleFieldChanged, SM_RetVoid) -DEFINE_CLASS(NATIVEVARIANT, StubHelpers, NativeVariant) -DEFINE_CLASS(NATIVEDECIMAL, StubHelpers, NativeDecimal) +DEFINE_CLASS(COMVARIANT, Marshalling, ComVariant) DEFINE_CLASS(SZARRAYHELPER, System, SZArrayHelper) // Note: The order of methods here has to match order they are implemented on the interfaces in diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 227fcecbbc814..79e094023188f 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -45,7 +45,7 @@ // FCFuncStart(gDependentHandleFuncs) - FCFuncElement("InternalInitialize", DependentHandle::InternalInitialize) + FCFuncElement("InternalAlloc", DependentHandle::InternalAlloc) FCFuncElement("InternalGetTarget", DependentHandle::InternalGetTarget) FCFuncElement("InternalGetDependent", DependentHandle::InternalGetDependent) FCFuncElement("InternalGetTargetAndDependent", DependentHandle::InternalGetTargetAndDependent) @@ -469,10 +469,6 @@ FCFuncEnd() FCFuncStart(gInteropMarshalFuncs) FCFuncElement("GetLastPInvokeError", MarshalNative::GetLastPInvokeError) FCFuncElement("SetLastPInvokeError", MarshalNative::SetLastPInvokeError) - FCFuncElement("SizeOfHelper", MarshalNative::SizeOfClass) - FCFuncElement("StructureToPtr", MarshalNative::StructureToPtr) - FCFuncElement("PtrToStructureHelper", MarshalNative::PtrToStructureHelper) - FCFuncElement("DestroyStructure", MarshalNative::DestroyStructure) FCFuncElement("GetExceptionCode", ExceptionNative::GetExceptionCode) FCFuncElement("GetExceptionPointers", ExceptionNative::GetExceptionPointers) @@ -518,14 +514,10 @@ FCFuncStart(gMonitorFuncs) FCFuncElement("ReliableEnter", JIT_MonReliableEnter) FCFuncElement("ReliableEnterTimeout", JIT_MonTryEnter) FCFuncElement("Exit", JIT_MonExit) - FCFuncElement("ObjWait", ObjectNative::WaitTimeout) - FCFuncElement("ObjPulse", ObjectNative::Pulse) - FCFuncElement("ObjPulseAll", ObjectNative::PulseAll) FCFuncElement("IsEnteredNative", ObjectNative::IsLockHeld) FCFuncEnd() FCFuncStart(gRuntimeHelpers) - FCFuncElement("GetObjectValue", ObjectNative::GetObjectValue) FCFuncElement("InitializeArray", ArrayNative::InitializeArray) FCFuncElement("GetSpanDataFrom", ArrayNative::GetSpanDataFrom) FCFuncElement("PrepareDelegate", ReflectionInvocation::PrepareDelegate) @@ -564,11 +556,6 @@ FCFuncStart(gMngdNativeArrayMarshalerFuncs) FCFuncEnd() #ifdef FEATURE_COMINTEROP -FCFuncStart(gObjectMarshalerFuncs) - FCFuncElement("ConvertToNative", StubHelpers::ObjectMarshaler__ConvertToNative) - FCFuncElement("ConvertToManaged", StubHelpers::ObjectMarshaler__ConvertToManaged) - FCFuncElement("ClearNative", StubHelpers::ObjectMarshaler__ClearNative) -FCFuncEnd() FCFuncStart(gInterfaceMarshalerFuncs) FCFuncElement("ConvertToNative", StubHelpers::InterfaceMarshaler__ConvertToNative) @@ -608,7 +595,6 @@ FCFuncStart(gStubHelperFuncs) FCFuncElement("ProfilerBeginTransitionCallback", StubHelpers::ProfilerBeginTransitionCallback) FCFuncElement("ProfilerEndTransitionCallback", StubHelpers::ProfilerEndTransitionCallback) #endif - FCFuncElement("CreateCustomMarshalerHelper", StubHelpers::CreateCustomMarshalerHelper) FCFuncElement("FmtClassUpdateNativeInternal", StubHelpers::FmtClassUpdateNativeInternal) FCFuncElement("FmtClassUpdateCLRInternal", StubHelpers::FmtClassUpdateCLRInternal) FCFuncElement("LayoutDestroyNativeInternal", StubHelpers::LayoutDestroyNativeInternal) @@ -630,8 +616,8 @@ FCFuncStart(gStubHelperFuncs) FCFuncEnd() FCFuncStart(gGCHandleFuncs) - FCFuncElement("InternalAlloc", MarshalNative::GCHandleInternalAlloc) - FCFuncElement("InternalFree", MarshalNative::GCHandleInternalFree) + FCFuncElement("_InternalAlloc", MarshalNative::GCHandleInternalAlloc) + FCFuncElement("_InternalFree", MarshalNative::GCHandleInternalFree) FCFuncElement("InternalGet", MarshalNative::GCHandleInternalGet) FCFuncElement("InternalSet", MarshalNative::GCHandleInternalSet) FCFuncElement("InternalCompareExchange", MarshalNative::GCHandleInternalCompareExchange) @@ -722,9 +708,6 @@ FCClassElement("Monitor", "System.Threading", gMonitorFuncs) FCClassElement("OAVariantLib", "Microsoft.Win32", gOAVariantFuncs) #endif FCClassElement("Object", "System", gObjectFuncs) -#ifdef FEATURE_COMINTEROP -FCClassElement("ObjectMarshaler", "System.StubHelpers", gObjectMarshalerFuncs) -#endif FCClassElement("RuntimeAssembly", "System.Reflection", gRuntimeAssemblyFuncs) FCClassElement("RuntimeFieldHandle", "System", gCOMFieldHandleNewFuncs) diff --git a/src/coreclr/vm/fieldmarshaler.cpp b/src/coreclr/vm/fieldmarshaler.cpp index ae92fd97c2cd4..57fc5b82bad14 100644 --- a/src/coreclr/vm/fieldmarshaler.cpp +++ b/src/coreclr/vm/fieldmarshaler.cpp @@ -127,9 +127,7 @@ VOID ParseNativeType(Module* pModule, *pNFD = NativeFieldDescriptor(pFD, CoreLibBinder::GetClass(CLASS__CURRENCY)); break; case MarshalInfo::MARSHAL_TYPE_DECIMAL: - // The decimal type can't be blittable since the managed and native alignment requirements differ. - // Native needs 8-byte alignment since one field is a 64-bit integer, but managed only needs 4-byte alignment since all fields are ints. - *pNFD = NativeFieldDescriptor(pFD, CoreLibBinder::GetClass(CLASS__NATIVEDECIMAL)); + *pNFD = NativeFieldDescriptor(pFD, CoreLibBinder::GetClass(CLASS__DECIMAL)); break; case MarshalInfo::MARSHAL_TYPE_GUID: *pNFD = NativeFieldDescriptor(pFD, CoreLibBinder::GetClass(CLASS__GUID)); @@ -163,7 +161,7 @@ VOID ParseNativeType(Module* pModule, break; #ifdef FEATURE_COMINTEROP case MarshalInfo::MARSHAL_TYPE_OBJECT: - *pNFD = NativeFieldDescriptor(pFD, CoreLibBinder::GetClass(CLASS__NATIVEVARIANT)); + *pNFD = NativeFieldDescriptor(pFD, CoreLibBinder::GetClass(CLASS__COMVARIANT)); break; #endif case MarshalInfo::MARSHAL_TYPE_SAFEHANDLE: diff --git a/src/coreclr/vm/ilmarshalers.cpp b/src/coreclr/vm/ilmarshalers.cpp index 431064f4e121d..1c87acac73685 100644 --- a/src/coreclr/vm/ilmarshalers.cpp +++ b/src/coreclr/vm/ilmarshalers.cpp @@ -1138,7 +1138,7 @@ LocalDesc ILObjectMarshaler::GetNativeType() { STANDARD_VM_CONTRACT; - return LocalDesc(TypeHandle(CoreLibBinder::GetClass(CLASS__NATIVEVARIANT))); + return LocalDesc(TypeHandle(CoreLibBinder::GetClass(CLASS__COMVARIANT))); } LocalDesc ILObjectMarshaler::GetManagedType() diff --git a/src/coreclr/vm/marshalnative.cpp b/src/coreclr/vm/marshalnative.cpp index ebe3fdf64f0d3..5a57cb888e7fe 100644 --- a/src/coreclr/vm/marshalnative.cpp +++ b/src/coreclr/vm/marshalnative.cpp @@ -91,190 +91,74 @@ extern "C" BOOL QCALLTYPE MarshalNative_IsBuiltInComSupported() return ret; } -FCIMPL3(VOID, MarshalNative::StructureToPtr, Object* pObjUNSAFE, LPVOID ptr, CLR_BOOL fDeleteOld) +extern "C" BOOL QCALLTYPE MarshalNative_TryGetStructMarshalStub(void* enregisteredTypeHandle, PCODE* pStructMarshalStub, SIZE_T* pSize) { - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(CheckPointer(ptr, NULL_OK)); - } - CONTRACTL_END; - - OBJECTREF pObj = (OBJECTREF) pObjUNSAFE; - - HELPER_METHOD_FRAME_BEGIN_1(pObj); - - if (ptr == NULL) - COMPlusThrowArgumentNull(W("ptr")); - if (pObj == NULL) - COMPlusThrowArgumentNull(W("structure")); - - // Code path will accept both regular layout objects and boxed value classes - // with layout. - - MethodTable *pMT = pObj->GetMethodTable(); - - if (pMT->HasInstantiation()) - COMPlusThrowArgumentException(W("structure"), W("Argument_NeedNonGenericObject")); - - if (pMT->IsBlittable()) - { - memcpyNoGCRefs(ptr, pObj->GetData(), pMT->GetNativeSize()); - } - else if (pMT->HasLayout()) - { - EEMarshalingData* pEEMarshalingData = pMT->GetLoaderAllocator()->GetMarshalingDataIfAvailable(); - MethodDesc* structMarshalStub = (pEEMarshalingData != NULL) ? pEEMarshalingData->LookupStructILStubSpeculative(pMT) : NULL; - - if (structMarshalStub == NULL) - { - GCX_PREEMP(); - structMarshalStub = NDirect::CreateStructMarshalILStub(pMT); - } - - if (fDeleteOld) - { - MarshalStructViaILStub(structMarshalStub, pObj->GetData(), ptr, StructMarshalStubs::MarshalOperation::Cleanup); - } - - MarshalStructViaILStub(structMarshalStub, pObj->GetData(), ptr, StructMarshalStubs::MarshalOperation::Marshal); - } - else - { - COMPlusThrowArgumentException(W("structure"), W("Argument_MustHaveLayoutOrBeBlittable")); - } - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - -FCIMPL3(VOID, MarshalNative::PtrToStructureHelper, LPVOID ptr, Object* pObjIn, CLR_BOOL allowValueClasses) -{ - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(CheckPointer(ptr, NULL_OK)); - } - CONTRACTL_END; - - OBJECTREF pObj = ObjectToOBJECTREF(pObjIn); - - HELPER_METHOD_FRAME_BEGIN_1(pObj); - - if (ptr == NULL) - COMPlusThrowArgumentNull(W("ptr")); - if (pObj == NULL) - COMPlusThrowArgumentNull(W("structure")); - - // Code path will accept regular layout objects. - MethodTable *pMT = pObj->GetMethodTable(); - - // Validate that the object passed in is not a value class. - if (!allowValueClasses && pMT->IsValueType()) - { - COMPlusThrowArgumentException(W("structure"), W("Argument_StructMustNotBeValueClass")); - } - else if (pMT->IsBlittable()) - { - memcpyNoGCRefs(pObj->GetData(), ptr, pMT->GetNativeSize()); - } - else if (pMT->HasLayout()) - { - EEMarshalingData* pEEMarshalingData = pMT->GetLoaderAllocator()->GetMarshalingDataIfAvailable(); - MethodDesc* structMarshalStub = (pEEMarshalingData != NULL) ? pEEMarshalingData->LookupStructILStubSpeculative(pMT) : NULL; - - if (structMarshalStub == NULL) - { - GCX_PREEMP(); - structMarshalStub = NDirect::CreateStructMarshalILStub(pMT); - } - - MarshalStructViaILStub(structMarshalStub, pObj->GetData(), ptr, StructMarshalStubs::MarshalOperation::Unmarshal); - } - else - { - COMPlusThrowArgumentException(W("structure"), W("Argument_MustHaveLayoutOrBeBlittable")); - } - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - - -FCIMPL2(VOID, MarshalNative::DestroyStructure, LPVOID ptr, ReflectClassBaseObject* refClassUNSAFE) -{ - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(CheckPointer(ptr, NULL_OK)); - } - CONTRACTL_END; + QCALL_CONTRACT; - REFLECTCLASSBASEREF refClass = (REFLECTCLASSBASEREF) refClassUNSAFE; - HELPER_METHOD_FRAME_BEGIN_1(refClass); + BOOL ret = FALSE; - if (ptr == NULL) - COMPlusThrowArgumentNull(W("ptr")); - if (refClass == NULL) - COMPlusThrowArgumentNull(W("structureType")); - if (refClass->GetMethodTable() != g_pRuntimeTypeClass) - COMPlusThrowArgumentException(W("structureType"), W("Argument_MustBeRuntimeType")); + BEGIN_QCALL; - TypeHandle th = refClass->GetType(); - - if (th.HasInstantiation()) - COMPlusThrowArgumentException(W("structureType"), W("Argument_NeedNonGenericType")); + TypeHandle th = TypeHandle::FromPtr(enregisteredTypeHandle); if (th.IsBlittable()) { - // ok to call with blittable structure, but no work to do in this case. + *pStructMarshalStub = NULL; + *pSize = th.GetMethodTable()->GetNativeSize(); + ret = TRUE; } else if (th.HasLayout()) { MethodTable* pMT = th.GetMethodTable(); + MethodDesc* structMarshalStub = NULL; + EEMarshalingData* pEEMarshalingData = pMT->GetLoaderAllocator()->GetMarshalingDataIfAvailable(); - MethodDesc* structMarshalStub = (pEEMarshalingData != NULL) ? pEEMarshalingData->LookupStructILStubSpeculative(pMT) : NULL; + if (pEEMarshalingData != NULL) + { + GCX_COOP(); + structMarshalStub = pEEMarshalingData->LookupStructILStubSpeculative(pMT); + } if (structMarshalStub == NULL) { - GCX_PREEMP(); structMarshalStub = NDirect::CreateStructMarshalILStub(pMT); } - MarshalStructViaILStub(structMarshalStub, nullptr, ptr, StructMarshalStubs::MarshalOperation::Cleanup); + *pStructMarshalStub = structMarshalStub->GetSingleCallableAddrOfCode(); + *pSize = 0; + ret = TRUE; } else { - COMPlusThrowArgumentException(W("structureType"), W("Argument_MustHaveLayoutOrBeBlittable")); + *pStructMarshalStub = NULL; + *pSize = 0; } - HELPER_METHOD_FRAME_END(); + END_QCALL; + + return ret; } -FCIMPLEND /************************************************************************ * PInvoke.SizeOf(Class) */ -FCIMPL2(UINT32, MarshalNative::SizeOfClass, ReflectClassBaseObject* refClassUNSAFE, CLR_BOOL throwIfNotMarshalable) +extern "C" INT32 QCALLTYPE MarshalNative_SizeOfHelper(QCall::TypeHandle t, BOOL throwIfNotMarshalable) { CONTRACTL { - FCALL_CHECK; - PRECONDITION(CheckPointer(refClassUNSAFE)); + QCALL_CHECK; } CONTRACTL_END; - UINT32 rv = 0; - REFLECTCLASSBASEREF refClass = (REFLECTCLASSBASEREF)refClassUNSAFE; + INT32 rv = 0; - HELPER_METHOD_FRAME_BEGIN_RET_1(refClass); + BEGIN_QCALL; // refClass is validated to be non-NULL RuntimeType by callers - TypeHandle th = refClass->GetType(); + TypeHandle th = t.AsTypeHandle(); if (throwIfNotMarshalable && (!th.IsBlittable() || th.IsArray())) { - GCX_PREEMP(); // Determine if the type is marshalable if (!IsStructMarshalable(th)) { @@ -287,10 +171,10 @@ FCIMPL2(UINT32, MarshalNative::SizeOfClass, ReflectClassBaseObject* refClassUNSA // The type is marshalable or we don't care so return its size. rv = th.GetMethodTable()->GetNativeSize(); - HELPER_METHOD_FRAME_END(); + + END_QCALL; return rv; } -FCIMPLEND /************************************************************************ @@ -450,18 +334,18 @@ FCIMPLEND * Support for the GCHandle class. */ -NOINLINE static OBJECTHANDLE FCDiagCreateHandle(OBJECTREF objRef, int type) +extern "C" OBJECTHANDLE QCALLTYPE GCHandle_InternalAllocWithGCTransition(QCall::ObjectHandleOnStack obj, int type) { + QCALL_CONTRACT; + OBJECTHANDLE hnd = NULL; - FC_INNER_PROLOG(MarshalNative::GCHandleInternalAlloc); + BEGIN_QCALL; - // Make the stack walkable for the profiler - HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_NOPOLL(Frame::FRAME_ATTR_EXACT_DEPTH | Frame::FRAME_ATTR_CAPTURE_DEPTH_2); - hnd = GetAppDomain()->CreateTypedHandle(objRef, static_cast(type)); - HELPER_METHOD_FRAME_END_POLL(); + GCX_COOP(); + hnd = GetAppDomain()->CreateTypedHandle(obj.Get(), static_cast(type)); - FC_INNER_EPILOG(); + END_QCALL; return hnd; } @@ -470,47 +354,39 @@ FCIMPL2(LPVOID, MarshalNative::GCHandleInternalAlloc, Object *obj, int type) { FCALL_CONTRACT; - OBJECTREF objRef(obj); - assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_SIZEDREF); if (CORProfilerTrackGC()) - { - FC_INNER_RETURN(LPVOID, (LPVOID) FCDiagCreateHandle(objRef, type)); - } + return NULL; - OBJECTHANDLE hnd = GetAppDomain()->GetHandleStore()->CreateHandleOfType(OBJECTREFToObject(objRef), static_cast(type)); - if (!hnd) - { - FCThrow(kOutOfMemoryException); - } - return (LPVOID) hnd; + return GetAppDomain()->GetHandleStore()->CreateHandleOfType(obj, static_cast(type)); } FCIMPLEND -NOINLINE static void FCDiagDestroyHandle(OBJECTHANDLE handle) +extern "C" void QCALLTYPE GCHandle_InternalFreeWithGCTransition(OBJECTHANDLE handle) { - FC_INNER_PROLOG(MarshalNative::GCHandleInternalFree); + QCALL_CONTRACT; + + _ASSERTE(handle != NULL); - // Make the stack walkable for the profiler - HELPER_METHOD_FRAME_BEGIN_ATTRIB(Frame::FRAME_ATTR_EXACT_DEPTH | Frame::FRAME_ATTR_CAPTURE_DEPTH_2); + BEGIN_QCALL; + + GCX_COOP(); DestroyTypedHandle(handle); - HELPER_METHOD_FRAME_END(); - FC_INNER_EPILOG(); + END_QCALL; } // Free a GC handle. -FCIMPL1(VOID, MarshalNative::GCHandleInternalFree, OBJECTHANDLE handle) +FCIMPL1(FC_BOOL_RET, MarshalNative::GCHandleInternalFree, OBJECTHANDLE handle) { FCALL_CONTRACT; if (CORProfilerTrackGC()) - { - FC_INNER_RETURN_VOID(FCDiagDestroyHandle(handle)); - } + FC_RETURN_BOOL(false); GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfUnknownType(handle); + FC_RETURN_BOOL(true); } FCIMPLEND diff --git a/src/coreclr/vm/marshalnative.h b/src/coreclr/vm/marshalnative.h index 28c4b6b0de22a..a2524b8525f1c 100644 --- a/src/coreclr/vm/marshalnative.h +++ b/src/coreclr/vm/marshalnative.h @@ -14,8 +14,6 @@ #include "fcall.h" -#define MAX_UTF8_CHAR_SIZE 3 - class MarshalNative { public: @@ -28,18 +26,12 @@ class MarshalNative static FCDECL1(int, GetHRForException, Object* eUNSAFE); #endif // FEATURE_COMINTEROP - static FCDECL2(UINT32, SizeOfClass, ReflectClassBaseObject* refClass, CLR_BOOL throwIfNotMarshalable); - static FCDECL1(UINT32, OffsetOfHelper, ReflectFieldObject* pFieldUNSAFE); static FCDECL0(int, GetLastPInvokeError); static FCDECL1(void, SetLastPInvokeError, int error); - static FCDECL3(VOID, StructureToPtr, Object* pObjUNSAFE, LPVOID ptr, CLR_BOOL fDeleteOld); - static FCDECL3(VOID, PtrToStructureHelper, LPVOID ptr, Object* pObjIn, CLR_BOOL allowValueClasses); - static FCDECL2(VOID, DestroyStructure, LPVOID ptr, ReflectClassBaseObject* refClassUNSAFE); - static FCDECL2(LPVOID, GCHandleInternalAlloc, Object *obj, int type); - static FCDECL1(VOID, GCHandleInternalFree, OBJECTHANDLE handle); + static FCDECL1(FC_BOOL_RET, GCHandleInternalFree, OBJECTHANDLE handle); static FCDECL1(LPVOID, GCHandleInternalGet, OBJECTHANDLE handle); static FCDECL2(VOID, GCHandleInternalSet, OBJECTHANDLE handle, Object *obj); static FCDECL3(Object*, GCHandleInternalCompareExchange, OBJECTHANDLE handle, Object *obj, Object* oldObj); @@ -58,6 +50,12 @@ class MarshalNative extern "C" VOID QCALLTYPE MarshalNative_Prelink(MethodDesc * pMD); extern "C" BOOL QCALLTYPE MarshalNative_IsBuiltInComSupported(); +extern "C" BOOL QCALLTYPE MarshalNative_TryGetStructMarshalStub(void* enregisteredTypeHandle, PCODE* pStructMarshalStub, SIZE_T* pSize); +extern "C" INT32 QCALLTYPE MarshalNative_SizeOfHelper(QCall::TypeHandle t, BOOL throwIfNotMarshalable); + +extern "C" OBJECTHANDLE QCALLTYPE GCHandle_InternalAllocWithGCTransition(QCall::ObjectHandleOnStack obj, int type); +extern "C" void QCALLTYPE GCHandle_InternalFreeWithGCTransition(OBJECTHANDLE handle); + #ifdef _DEBUG using IsInCooperativeGCMode_fn = BOOL(STDMETHODCALLTYPE*)(void); extern "C" IsInCooperativeGCMode_fn QCALLTYPE MarshalNative_GetIsInCooperativeGCModeFunctionPointer(); diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp index 8e50860a73bff..4c63edb027f30 100644 --- a/src/coreclr/vm/mlinfo.cpp +++ b/src/coreclr/vm/mlinfo.cpp @@ -391,9 +391,7 @@ CustomMarshalerHelper *SetupCustomMarshalerHelper(LPCUTF8 strMarshalerTypeName, { CONTRACT (CustomMarshalerHelper*) { - THROWS; - GC_TRIGGERS; - MODE_ANY; + STANDARD_VM_CHECK; PRECONDITION(CheckPointer(pAssembly)); POSTCONDITION(CheckPointer(RETVAL)); } @@ -4057,21 +4055,18 @@ bool IsUnsupportedTypedrefReturn(MetaSig& msig) #include "stubhelpers.h" -FCIMPL3(void*, StubHelpers::CreateCustomMarshalerHelper, - MethodDesc* pMD, - mdToken paramToken, - TypeHandle hndManagedType) + +extern "C" void* QCALLTYPE StubHelpers_CreateCustomMarshalerHelper(MethodDesc* pMD, mdToken paramToken, TypeHandle hndManagedType) { - FCALL_CONTRACT; + QCALL_CONTRACT; CustomMarshalerHelper* pCMHelper = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_0(); + BEGIN_QCALL; Module* pModule = pMD->GetModule(); Assembly* pAssembly = pModule->GetAssembly(); - #ifdef FEATURE_COMINTEROP if (!hndManagedType.IsTypeDesc() && IsTypeRefOrDef(g_CollectionsEnumeratorClassName, hndManagedType.GetModule(), hndManagedType.GetCl())) @@ -4108,9 +4103,8 @@ FCIMPL3(void*, StubHelpers::CreateCustomMarshalerHelper, hndManagedType); } - HELPER_METHOD_FRAME_END(); + END_QCALL; return (void*)pCMHelper; } -FCIMPLEND diff --git a/src/coreclr/vm/namespace.h b/src/coreclr/vm/namespace.h index 8b51f9ca62391..42389240d6f0d 100644 --- a/src/coreclr/vm/namespace.h +++ b/src/coreclr/vm/namespace.h @@ -20,9 +20,7 @@ #define g_ResourcesNS g_SystemNS ".Resources" #define g_DiagnosticsNS g_SystemNS ".Diagnostics" #define g_CodeContractsNS g_DiagnosticsNS ".Contracts" -#define g_AssembliesNS g_SystemNS ".Configuration.Assemblies" #define g_GlobalizationNS g_SystemNS ".Globalization" -#define g_IsolatedStorageNS g_SystemNS ".IO.IsolatedStorage" #define g_TextNS g_SystemNS ".Text" #define g_CollectionsGenericNS g_SystemNS ".Collections.Generic" @@ -43,22 +41,8 @@ #define g_ConstrainedExecutionNS g_RuntimeNS ".ConstrainedExecution" #define g_SecurityNS g_SystemNS ".Security" -#define g_UtilNS g_SecurityNS ".Util" -#define g_PublicKeyNS g_SecurityNS ".PublicKey" -#define g_PermissionsNS g_SecurityNS ".Permissions" -#define g_PrincipalNS g_SecurityNS ".Principal" -#define g_PolicyNS g_SecurityNS ".Policy" #define g_CryptographyNS g_SecurityNS ".Cryptography" -#define g_X509NS g_CryptographyNS ".X509Certificates" - #define g_SerializationNS g_RuntimeNS ".Serialization" -#define g_RemotingNS g_RuntimeNS ".Remoting" -#define g_ActivationNS g_RemotingNS ".Activation" -#define g_ProxiesNS g_RemotingNS ".Proxies" -#define g_ContextsNS g_RemotingNS ".Contexts" -#define g_MessagingNS g_RemotingNS ".Messaging" -#define g_RemotingServicesNS g_RemotingNS ".Services" -#define g_LifetimeNS g_RemotingNS ".Lifetime" #define g_MicrosoftNS "Microsoft" diff --git a/src/coreclr/vm/olevariant.cpp b/src/coreclr/vm/olevariant.cpp index e4d9174dc3edc..888ebdd380dae 100644 --- a/src/coreclr/vm/olevariant.cpp +++ b/src/coreclr/vm/olevariant.cpp @@ -835,7 +835,7 @@ MethodTable* OleVariant::GetNativeMethodTableForVarType(VARTYPE vt, MethodTable* case VT_CARRAY: return CoreLibBinder::GetClass(CLASS__INTPTR); case VT_VARIANT: - return CoreLibBinder::GetClass(CLASS__NATIVEVARIANT); + return CoreLibBinder::GetClass(CLASS__COMVARIANT); case VTHACK_ANSICHAR: return CoreLibBinder::GetClass(CLASS__BYTE); case VT_UI2: @@ -845,7 +845,7 @@ MethodTable* OleVariant::GetNativeMethodTableForVarType(VARTYPE vt, MethodTable* // MethodTable to ensure the correct size. return CoreLibBinder::GetClass(CLASS__UINT16); case VT_DECIMAL: - return CoreLibBinder::GetClass(CLASS__NATIVEDECIMAL); + return CoreLibBinder::GetClass(CLASS__DECIMAL); default: PREFIX_ASSUME(pManagedMT != NULL); return pManagedMT; @@ -1154,15 +1154,6 @@ void VariantData::NewVariant(VariantData * const& dest, const CVTypes type, INT6 } } -void SafeVariantClearHelper(_Inout_ VARIANT* pVar) -{ - WRAPPER_NO_CONTRACT; - - VariantClear(pVar); -} - -class OutOfMemoryException; - void SafeVariantClear(VARIANT* pVar) { CONTRACTL @@ -1176,52 +1167,19 @@ void SafeVariantClear(VARIANT* pVar) if (pVar) { GCX_PREEMP(); - SCAN_EHMARKER(); - PAL_CPP_TRY - { - // These are holders to tell the contract system that we're catching all exceptions. - SCAN_EHMARKER_TRY(); - CLR_TRY_MARKER(); - - // Most of time, oleaut32.dll is loaded already when we get here. - // Sometimes, CLR initializes Variant without loading oleaut32.dll, e.g. VT_BOOL. - // It is better for performance with EX_TRY than - - SafeVariantClearHelper(pVar); - - SCAN_EHMARKER_END_TRY(); - } -#pragma warning(suppress: 4101) - PAL_CPP_CATCH_DERIVED(OutOfMemoryException, obj) - { - SCAN_EHMARKER_CATCH(); - -#if defined(STACK_GUARDS_DEBUG) - // Catching and just swallowing an exception means we need to tell - // the SO code that it should go back to normal operation, as it - // currently thinks that the exception is still on the fly. - GetThread()->GetCurrentStackGuard()->RestoreCurrentGuard(); -#endif - - SCAN_EHMARKER_END_CATCH(); - } - PAL_CPP_ENDTRY; + VariantClear(pVar); - FillMemory(pVar, sizeof(VARIANT), 0x00); + // VariantClear resets the instance to VT_EMPTY (0) + // COMPAT: Clear the remaining memory for compat. The instance remains set to VT_EMPTY (0). + ZeroMemory(pVar, sizeof(VARIANT)); } } -FORCEINLINE void EmptyVariant(VARIANT* value) -{ - WRAPPER_NO_CONTRACT; - SafeVariantClear(value); -} - -class VariantEmptyHolder : public Wrapper, EmptyVariant, NULL> +class VariantEmptyHolder : public Wrapper, SafeVariantClear, NULL> { public: VariantEmptyHolder(VARIANT* p = NULL) : - Wrapper, EmptyVariant, NULL>(p) + Wrapper, SafeVariantClear, NULL>(p) { WRAPPER_NO_CONTRACT; } @@ -1230,7 +1188,7 @@ class VariantEmptyHolder : public Wrapper, Empty { WRAPPER_NO_CONTRACT; - Wrapper, EmptyVariant, NULL>::operator=(p); + Wrapper, SafeVariantClear, NULL>::operator=(p); } }; diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 943ec19bcc2ad..7400c9d535a1a 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -212,6 +212,8 @@ static const Entry s_QCall[] = DllImportEntry(ClrConfig_GetConfigBoolValue) DllImportEntry(Buffer_Clear) DllImportEntry(Buffer_MemMove) + DllImportEntry(DependentHandle_InternalAllocWithGCTransition) + DllImportEntry(DependentHandle_InternalFreeWithGCTransition) DllImportEntry(GCInterface_StartNoGCRegion) DllImportEntry(GCInterface_EndNoGCRegion) DllImportEntry(GCInterface_GetTotalMemory) @@ -227,8 +229,12 @@ static const Entry s_QCall[] = DllImportEntry(GCInterface_RefreshMemoryLimit) DllImportEntry(GCInterface_EnableNoGCRegionCallback) DllImportEntry(GCInterface_GetGenerationBudget) + DllImportEntry(GCHandle_InternalAllocWithGCTransition) + DllImportEntry(GCHandle_InternalFreeWithGCTransition) DllImportEntry(MarshalNative_Prelink) DllImportEntry(MarshalNative_IsBuiltInComSupported) + DllImportEntry(MarshalNative_TryGetStructMarshalStub) + DllImportEntry(MarshalNative_SizeOfHelper) DllImportEntry(MarshalNative_GetHINSTANCE) #ifdef _DEBUG DllImportEntry(MarshalNative_GetIsInCooperativeGCModeFunctionPointer) @@ -262,7 +268,10 @@ static const Entry s_QCall[] = DllImportEntry(GetFileLoadExceptionMessage) DllImportEntry(FileLoadException_GetMessageForHR) DllImportEntry(Interlocked_MemoryBarrierProcessWide) - DllImportEntry(ObjectNative_GetMonitorLockContentionCount) + DllImportEntry(Monitor_Wait) + DllImportEntry(Monitor_Pulse) + DllImportEntry(Monitor_PulseAll) + DllImportEntry(Monitor_GetLockContentionCount) DllImportEntry(ReflectionInvocation_RunClassConstructor) DllImportEntry(ReflectionInvocation_RunModuleConstructor) DllImportEntry(ReflectionInvocation_CompileMethod) @@ -338,7 +347,10 @@ static const Entry s_QCall[] = #if defined(TARGET_X86) || defined(TARGET_AMD64) DllImportEntry(X86BaseCpuId) #endif + DllImportEntry(StubHelpers_CreateCustomMarshalerHelper) #if defined(FEATURE_COMINTEROP) + DllImportEntry(ObjectMarshaler_ConvertToNative) + DllImportEntry(ObjectMarshaler_ConvertToManaged) DllImportEntry(InterfaceMarshaler__ClearNative) #endif #if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS) diff --git a/src/coreclr/vm/stubhelpers.cpp b/src/coreclr/vm/stubhelpers.cpp index 9988a912967cf..1e87c7c87f236 100644 --- a/src/coreclr/vm/stubhelpers.cpp +++ b/src/coreclr/vm/stubhelpers.cpp @@ -326,13 +326,17 @@ FCIMPLEND #include -FCIMPL2(void, StubHelpers::ObjectMarshaler__ConvertToNative, Object* pSrcUNSAFE, VARIANT* pDest) +extern "C" void QCALLTYPE ObjectMarshaler_ConvertToNative(QCall::ObjectHandleOnStack pSrcUNSAFE, VARIANT* pDest) { - FCALL_CONTRACT; + QCALL_CONTRACT; - OBJECTREF pSrc = ObjectToOBJECTREF(pSrcUNSAFE); + BEGIN_QCALL; + + GCX_COOP(); + + OBJECTREF pSrc = pSrcUNSAFE.Get(); + GCPROTECT_BEGIN(pSrc); - HELPER_METHOD_FRAME_BEGIN_1(pSrc); if (pDest->vt & VT_BYREF) { OleVariant::MarshalOleRefVariantForObject(&pSrc, pDest); @@ -341,34 +345,32 @@ FCIMPL2(void, StubHelpers::ObjectMarshaler__ConvertToNative, Object* pSrcUNSAFE, { OleVariant::MarshalOleVariantForObject(&pSrc, pDest); } - HELPER_METHOD_FRAME_END(); + + GCPROTECT_END(); + + END_QCALL; } -FCIMPLEND -FCIMPL1(Object*, StubHelpers::ObjectMarshaler__ConvertToManaged, VARIANT* pSrc) +extern "C" void QCALLTYPE ObjectMarshaler_ConvertToManaged(VARIANT* pSrc, QCall::ObjectHandleOnStack retObject) { - FCALL_CONTRACT; + QCALL_CONTRACT; + + BEGIN_QCALL; + + GCX_COOP(); OBJECTREF retVal = NULL; - HELPER_METHOD_FRAME_BEGIN_RET_1(retVal); - // The IL stub is going to call ObjectMarshaler__ClearNative() afterwards. + GCPROTECT_BEGIN(retVal); + + // The IL stub is going to call ObjectMarshaler.ClearNative() afterwards. // If it doesn't it's a bug in ILObjectMarshaler. OleVariant::MarshalObjectForOleVariant(pSrc, &retVal); - HELPER_METHOD_FRAME_END(); + retObject.Set(retVal); - return OBJECTREFToObject(retVal); -} -FCIMPLEND + GCPROTECT_END(); -FCIMPL1(void, StubHelpers::ObjectMarshaler__ClearNative, VARIANT* pSrc) -{ - FCALL_CONTRACT; - - HELPER_METHOD_FRAME_BEGIN_0(); - SafeVariantClear(pSrc); - HELPER_METHOD_FRAME_END(); + END_QCALL; } -FCIMPLEND #include FCIMPL4(IUnknown*, StubHelpers::InterfaceMarshaler__ConvertToNative, Object* pObjUNSAFE, MethodTable* pItfMT, MethodTable* pClsMT, DWORD dwFlags) @@ -624,7 +626,7 @@ FCIMPL3(Object*, StubHelpers::GetCOMHRExceptionObject, HRESULT hr, MethodDesc *p { IErrorInfo *pErrInfo = NULL; - if (pErrInfo == NULL && pMD != NULL) + if (pMD != NULL) { // Retrieve the interface method table. MethodTable *pItfMT = ComPlusCallInfo::FromMethodDesc(pMD)->m_pInterfaceMT; diff --git a/src/coreclr/vm/stubhelpers.h b/src/coreclr/vm/stubhelpers.h index b9b5ea279a14a..725710b44da7b 100644 --- a/src/coreclr/vm/stubhelpers.h +++ b/src/coreclr/vm/stubhelpers.h @@ -45,10 +45,6 @@ class StubHelpers #ifdef FEATURE_COMINTEROP static FCDECL4(IUnknown*, GetCOMIPFromRCW, Object* pSrcUNSAFE, MethodDesc* pMD, void **ppTarget, CLR_BOOL* pfNeedsRelease); - static FCDECL2(void, ObjectMarshaler__ConvertToNative, Object* pSrcUNSAFE, VARIANT* pDest); - static FCDECL1(Object*, ObjectMarshaler__ConvertToManaged, VARIANT* pSrc); - static FCDECL1(void, ObjectMarshaler__ClearNative, VARIANT* pSrc); - static FCDECL4(IUnknown*, InterfaceMarshaler__ConvertToNative, Object* pObjUNSAFE, MethodTable* pItfMT, MethodTable* pClsMT, DWORD dwFlags); static FCDECL4(Object*, InterfaceMarshaler__ConvertToManaged, IUnknown **ppUnk, MethodTable *pItfMT, MethodTable *pClsMT, DWORD dwFlags); static FCDECL1(Object *, InterfaceMarshaler__ConvertToManagedWithoutUnboxing, IUnknown *pNative); @@ -65,8 +61,6 @@ class StubHelpers static FCDECL3(Object*, GetCOMHRExceptionObject, HRESULT hr, MethodDesc *pMD, Object *unsafe_pThis); #endif // FEATURE_COMINTEROP - static FCDECL3(void*, CreateCustomMarshalerHelper, MethodDesc* pMD, mdToken paramToken, TypeHandle hndManagedType); - static FCDECL3(void, FmtClassUpdateNativeInternal, Object* pObjUNSAFE, BYTE* pbNative, OBJECTREF *ppCleanupWorkListOnStack); static FCDECL2(void, FmtClassUpdateCLRInternal, Object* pObjUNSAFE, BYTE* pbNative); static FCDECL2(void, LayoutDestroyNativeInternal, Object* pObjUNSAFE, BYTE* pbNative); @@ -98,7 +92,12 @@ class StubHelpers static FCDECL0(void*, NextCallReturnAddress); }; +extern "C" void* QCALLTYPE StubHelpers_CreateCustomMarshalerHelper(MethodDesc* pMD, mdToken paramToken, TypeHandle hndManagedType); + #ifdef FEATURE_COMINTEROP +extern "C" void QCALLTYPE ObjectMarshaler_ConvertToNative(QCall::ObjectHandleOnStack pSrcUNSAFE, VARIANT* pDest); +extern "C" void QCALLTYPE ObjectMarshaler_ConvertToManaged(VARIANT* pSrc, QCall::ObjectHandleOnStack retObject); + extern "C" void QCALLTYPE InterfaceMarshaler__ClearNative(IUnknown * pUnk); #endif diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs index 7a4f50bf6bcc1..7a45e868a3d02 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs @@ -46,7 +46,7 @@ private GCHandle(object? value, GCHandleType type) if (type == GCHandleType.Pinned) { // Record if the handle is pinned. - handle = (IntPtr)((nint)handle | 1); + handle |= 1; } _handle = handle; @@ -58,12 +58,14 @@ private GCHandle(object? value, GCHandleType type) /// Creates a new GC handle for an object. /// The object that the GC handle is created for. /// A new GC handle that protects the object. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static GCHandle Alloc(object? value) => new GCHandle(value, GCHandleType.Normal); /// Creates a new GC handle for an object. /// The object that the GC handle is created for. /// The type of GC handle to create. /// A new GC handle that protects the object. + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static GCHandle Alloc(object? value, GCHandleType type) => new GCHandle(value, type); /// Frees a GC handle. @@ -141,7 +143,7 @@ public readonly IntPtr AddrOfPinnedObject() } /// Determine whether this handle has been allocated or not. - public readonly bool IsAllocated => (nint)_handle != 0; + public readonly bool IsAllocated => _handle != 0; /// /// Used to create a GCHandle from an int. This is intended to @@ -169,21 +171,21 @@ public static GCHandle FromIntPtr(IntPtr value) /// true if the current instance is equal to the other instance; otherwise, false. public readonly bool Equals(GCHandle other) => _handle == other._handle; - public static bool operator ==(GCHandle a, GCHandle b) => (nint)a._handle == (nint)b._handle; + public static bool operator ==(GCHandle a, GCHandle b) => a._handle == b._handle; - public static bool operator !=(GCHandle a, GCHandle b) => (nint)a._handle != (nint)b._handle; + public static bool operator !=(GCHandle a, GCHandle b) => a._handle != b._handle; [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static IntPtr GetHandleValue(IntPtr handle) => new IntPtr((nint)handle & ~(nint)1); // Remove Pin flag + private static IntPtr GetHandleValue(IntPtr handle) => new IntPtr(handle & ~1); // Remove Pin flag [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static bool IsPinned(IntPtr handle) => ((nint)handle & 1) != 0; // Check Pin flag + private static bool IsPinned(IntPtr handle) => (handle & 1) != 0; // Check Pin flag [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void ThrowIfInvalid(IntPtr handle) { // Check if the handle was never initialized or was freed. - if ((nint)handle == 0) + if (handle == 0) { ThrowHelper.ThrowInvalidOperationException_HandleIsNotInitialized(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs index 11a3319196ad9..71c6cecbc2251 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs @@ -91,14 +91,14 @@ public static int SizeOf(object structure) { ArgumentNullException.ThrowIfNull(structure); - return SizeOfHelper(structure.GetType(), throwIfNotMarshalable: true); + return SizeOfHelper((RuntimeType)structure.GetType(), throwIfNotMarshalable: true); } public static int SizeOf(T structure) { ArgumentNullException.ThrowIfNull(structure); - return SizeOfHelper(structure.GetType(), throwIfNotMarshalable: true); + return SizeOfHelper((RuntimeType)structure.GetType(), throwIfNotMarshalable: true); } [RequiresDynamicCode("Marshalling code for the object might not be available. Use the SizeOf overload instead.")] @@ -107,21 +107,21 @@ public static int SizeOf(Type t) { ArgumentNullException.ThrowIfNull(t); - if (t is not RuntimeType) + if (t is not RuntimeType rt) { throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(t)); } - if (t.IsGenericType) + if (rt.IsGenericType) { throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t)); } - return SizeOfHelper(t, throwIfNotMarshalable: true); + return SizeOfHelper(rt, throwIfNotMarshalable: true); } public static int SizeOf() { - Type t = typeof(T); + RuntimeType t = (RuntimeType)typeof(T); if (t.IsGenericType) { throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(T)); @@ -585,12 +585,20 @@ public static void StructureToPtr([DisallowNull] T structure, IntPtr ptr, boo [EditorBrowsable(EditorBrowsableState.Never)] public static void PtrToStructure(IntPtr ptr, object structure) { + ArgumentNullException.ThrowIfNull(ptr); + ArgumentNullException.ThrowIfNull(structure); + PtrToStructureHelper(ptr, structure, allowValueClasses: false); } public static void PtrToStructure(IntPtr ptr, [DisallowNull] T structure) { - PtrToStructureHelper(ptr, structure, allowValueClasses: false); + ArgumentNullException.ThrowIfNull(ptr); + + object boxedStructure = structure; + ArgumentNullException.ThrowIfNull(boxedStructure, nameof(structure)); + + PtrToStructureHelper(ptr, boxedStructure, allowValueClasses: false); } public static T? PtrToStructure<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]T>(IntPtr ptr) diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs index 66fa0edb4a24a..1dcf1fbdbc698 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs @@ -64,7 +64,7 @@ public void DestroyStructure_ZeroPointer_ThrowsArgumentNullException() [Fact] public void DestroyStructure_NullStructureType_ThrowsArgumentNullException() { - AssertExtensions.Throws("structureType", () => Marshal.DestroyStructure((IntPtr)1, null)); + AssertExtensions.Throws("structuretype", () => Marshal.DestroyStructure((IntPtr)1, null)); } public static IEnumerable DestroyStructure_InvalidType_TestData() @@ -99,15 +99,15 @@ public static IEnumerable DestroyStructure_InvalidType_TestData() [MemberData(nameof(DestroyStructure_InvalidType_TestData))] public void DestroyStructure_NonRuntimeType_ThrowsArgumentException(Type invalidType) { - AssertExtensions.Throws("structureType", () => Marshal.DestroyStructure((IntPtr)1, invalidType)); + AssertExtensions.Throws("structuretype", () => Marshal.DestroyStructure((IntPtr)1, invalidType)); } [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/75666", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] public void DestroyStructure_AutoLayout_ThrowsArgumentException() { - AssertExtensions.Throws("structureType", () => Marshal.DestroyStructure((IntPtr)1)); - AssertExtensions.Throws("structureType", () => Marshal.DestroyStructure((IntPtr)1, typeof(AutoLayoutStruct))); + AssertExtensions.Throws("structuretype", () => Marshal.DestroyStructure((IntPtr)1)); + AssertExtensions.Throws("structuretype", () => Marshal.DestroyStructure((IntPtr)1, typeof(AutoLayoutStruct))); } [Fact] diff --git a/src/mono/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Mono.cs index e2574f415c0de..505cbcffc0426 100644 --- a/src/mono/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Mono.cs @@ -63,14 +63,7 @@ private static void PrelinkCore(MethodInfo m) } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void PtrToStructureInternal(IntPtr ptr, object structure, bool allowValueClasses); - - private static void PtrToStructureHelper(IntPtr ptr, object? structure, bool allowValueClasses) - { - ArgumentNullException.ThrowIfNull(structure); - ArgumentNullException.ThrowIfNull(ptr); - PtrToStructureInternal(ptr, structure, allowValueClasses); - } + private static extern void PtrToStructureHelper(IntPtr ptr, object structure, bool allowValueClasses); [MethodImpl(MethodImplOptions.InternalCall)] private static extern void GetDelegateForFunctionPointerInternal(QCallTypeHandle t, IntPtr ptr, ObjectHandleOnStack res); @@ -92,9 +85,8 @@ private static Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t [MethodImpl(MethodImplOptions.InternalCall)] private static extern int SizeOfHelper(QCallTypeHandle t, bool throwIfNotMarshalable); - private static int SizeOfHelper(Type t, bool throwIfNotMarshalable) + private static int SizeOfHelper(RuntimeType rttype, bool throwIfNotMarshalable) { - RuntimeType rttype = (RuntimeType)t; return SizeOfHelper(new QCallTypeHandle(ref rttype), throwIfNotMarshalable); } diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h index b18d285c421ca..556eb8708c439 100644 --- a/src/mono/mono/metadata/icall-def.h +++ b/src/mono/mono/metadata/icall-def.h @@ -454,7 +454,7 @@ HANDLES(MARSHAL_10, "GetFunctionPointerForDelegateInternal", ves_icall_System_Ru NOHANDLES(ICALL(MARSHAL_11, "GetLastPInvokeError", ves_icall_System_Runtime_InteropServices_Marshal_GetLastPInvokeError)) HANDLES(MARSHAL_12, "OffsetOf", ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf, int, 2, (MonoReflectionType, MonoString)) HANDLES(MARSHAL_13, "PrelinkInternal", ves_icall_System_Runtime_InteropServices_Marshal_Prelink, void, 1, (MonoReflectionMethod)) -HANDLES(MARSHAL_20, "PtrToStructureInternal", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructureInternal, void, 3, (gconstpointer, MonoObject, MonoBoolean)) +HANDLES(MARSHAL_20, "PtrToStructureHelper", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructureHelper, void, 3, (gconstpointer, MonoObject, MonoBoolean)) NOHANDLES(ICALL(MARSHAL_29a, "SetLastPInvokeError", ves_icall_System_Runtime_InteropServices_Marshal_SetLastPInvokeError)) HANDLES(MARSHAL_31, "SizeOfHelper", ves_icall_System_Runtime_InteropServices_Marshal_SizeOfHelper, guint32, 2, (MonoQCallTypeHandle, MonoBoolean)) HANDLES(MARSHAL_34, "StructureToPtr", ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr, void, 3, (MonoObject, gpointer, MonoBoolean)) diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 02309b933f160..8d68b450556f2 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -5409,7 +5409,7 @@ ptr_to_structure (gconstpointer src, MonoObjectHandle dst, MonoError *error) } void -ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructureInternal (gconstpointer src, MonoObjectHandle dst, MonoBoolean allow_vtypes, MonoError *error) +ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructureHelper (gconstpointer src, MonoObjectHandle dst, MonoBoolean allow_vtypes, MonoError *error) { MonoType *t; MonoClass *klass; @@ -5598,10 +5598,10 @@ void ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, MonoReflectionTypeHandle type, MonoError *error) { MONO_CHECK_ARG_NULL_NAMED (src, "ptr",); - MONO_CHECK_ARG_NULL_HANDLE_NAMED (type, "structureType",); + MONO_CHECK_ARG_NULL_HANDLE_NAMED (type, "structuretype",); if (!m_class_is_runtime_type (MONO_HANDLE_GET_CLASS (type))) { - mono_error_set_argument (error, "structureType", ""); + mono_error_set_argument (error, "structuretype", ""); return; } @@ -5610,7 +5610,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_DestroyStructure (gpointer src, return; if (m_class_is_auto_layout (klass)) { - mono_error_set_argument (error, "structureType", "The specified structure must be blittable or have layout information."); + mono_error_set_argument (error, "structuretype", "The specified structure must be blittable or have layout information."); return; }