diff --git a/src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs b/src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs index 4256112ea3eb6..e7c2a99eeefa2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs @@ -6,128 +6,148 @@ namespace System { - // This class will not be marked serializable // Note: This type must have the same layout as the CLR's VARARGS type in CLRVarArgs.h. - // It also contains an inline SigPointer data structure - must keep those fields in sync. [StructLayout(LayoutKind.Sequential)] - public ref struct ArgIterator + public unsafe ref partial struct ArgIterator { - private IntPtr ArgCookie; // Cookie from the EE. + private IntPtr _argCookie; // Cookie from the EE. - // The SigPointer structure consists of the following members. (Note: this is an inline native SigPointer data type) - private IntPtr sigPtr; // Pointer to remaining signature. - private IntPtr sigPtrLen; // Remaining length of the pointer - - // Note, sigPtrLen is actually a DWORD, but on 64bit systems this structure becomes - // 8-byte aligned, which requires us to pad it. + [StructLayout(LayoutKind.Sequential)] + private struct SigPointer + { + internal IntPtr _ptr; + internal uint _len; + } + private SigPointer _sigPtr; // Pointer to remaining signature. - private IntPtr ArgPtr; // Pointer to remaining args. - private int RemainingArgs; // # of remaining args. + private IntPtr _argPtr; // Pointer to remaining args. + private int _remainingArgs; // # of remaining args. -#if (TARGET_WINDOWS && !TARGET_ARM) // Native Varargs are not supported on Unix (all architectures) and Windows ARM - [MethodImpl(MethodImplOptions.InternalCall)] - private extern ArgIterator(IntPtr arglist); +#if TARGET_WINDOWS // Native Varargs are not supported on Unix + // ArgIterator is a ref struct. It does not require pinning. + // This method null checks the this pointer as a side-effect. + private ArgIterator* ThisPtr => (ArgIterator*)Unsafe.AsPointer(ref _argCookie); // create an arg iterator that points at the first argument that // is not statically declared (that is the first ... arg) // 'arglist' is the value returned by the ARGLIST instruction - public ArgIterator(RuntimeArgumentHandle arglist) : this(arglist.Value) + public ArgIterator(RuntimeArgumentHandle arglist) { + IntPtr cookie = arglist.Value; + if (cookie == 0) + throw new ArgumentException(SR.InvalidOperation_HandleIsNotInitialized); + Init(ThisPtr, cookie); } - [MethodImpl(MethodImplOptions.InternalCall)] - private extern unsafe ArgIterator(IntPtr arglist, void* ptr); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ArgIterator_Init")] + private static partial void Init(ArgIterator* thisPtr, IntPtr cookie); // create an arg iterator that points just past 'firstArg'. // 'arglist' is the value returned by the ARGLIST instruction // This is much like the C va_start macro [CLSCompliant(false)] - public unsafe ArgIterator(RuntimeArgumentHandle arglist, void* ptr) : this(arglist.Value, ptr) + public ArgIterator(RuntimeArgumentHandle arglist, void* ptr) { + IntPtr cookie = arglist.Value; + if (cookie == 0) + throw new ArgumentException(SR.InvalidOperation_HandleIsNotInitialized); + Init(ThisPtr, cookie, ptr); } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ArgIterator_Init2")] + private static partial void Init(ArgIterator* thisPtr, IntPtr cookie, void* ptr); + +#pragma warning disable CS8500 // Takes a pointer to a managed type // Fetch an argument as a typed referece, advance the iterator. // Throws an exception if past end of argument list [CLSCompliant(false)] public TypedReference GetNextArg() { - TypedReference result = default; - // reference to TypedReference is banned, so have to pass result as pointer - unsafe + if (_argCookie == 0) { -#pragma warning disable CS8500 // Takes a pointer to a managed type - FCallGetNextArg(&result); -#pragma warning restore CS8500 + // This ArgIterator was created by marshaling from an unmanaged va_list - + // can't do this operation + ThrowHelper.ThrowNotSupportedException(); } + + // Make sure there are remaining args. + if (_remainingArgs == 0) + { + throw new InvalidOperationException(SR.InvalidOperation_EnumEnded); + } + + TypedReference result = default; + GetNextArg(ThisPtr, &result); return result; } - [MethodImpl(MethodImplOptions.InternalCall)] - // reference to TypedReference is banned, so have to pass result as void pointer - private extern unsafe void FCallGetNextArg(void* result); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ArgIterator_GetNextArg")] + private static partial void GetNextArg(ArgIterator* thisPtr, TypedReference* pResult); // Alternate version of GetNextArg() intended primarily for IJW code // generated by VC's "va_arg()" construct. [CLSCompliant(false)] public TypedReference GetNextArg(RuntimeTypeHandle rth) { - if (sigPtr != IntPtr.Zero) + if (_sigPtr._ptr != IntPtr.Zero) { // This is an ordinary ArgIterator capable of determining // types from a signature. Just do a regular GetNextArg. return GetNextArg(); } - else + + // Prevent abuse of this API with a default ArgIterator (it + // doesn't require permission to create a zero-inited value + // type). Check that _argPtr isn't zero or this API will allow a + // malicious caller to increment the pointer to an arbitrary + // location in memory and read the contents. + if (_argPtr == IntPtr.Zero) { - // Prevent abuse of this API with a default ArgIterator (it - // doesn't require permission to create a zero-inited value - // type). Check that ArgPtr isn't zero or this API will allow a - // malicious caller to increment the pointer to an arbitrary - // location in memory and read the contents. - if (ArgPtr == IntPtr.Zero) -#pragma warning disable CA2208 // Instantiate argument exceptions correctly, the argument not applicable - throw new ArgumentNullException(); -#pragma warning restore CA2208 - - TypedReference result = default; - // reference to TypedReference is banned, so have to pass result as pointer - unsafe - { -#pragma warning disable CS8500 // Takes a pointer to a managed type - InternalGetNextArg(&result, rth.GetRuntimeType()); -#pragma warning restore CS8500 - } - return result; + throw new ArgumentNullException(null); + } + + if (rth.IsNullHandle()) + { + throw new ArgumentNullException(nameof(rth), SR.Arg_InvalidHandle); } - } + TypedReference result = default; + GetNextArg(ThisPtr, new QCallTypeHandle(ref rth), &result); + return result; + } - [MethodImpl(MethodImplOptions.InternalCall)] - // reference to TypedReference is banned, so have to pass result as void pointer - private extern unsafe void InternalGetNextArg(void* result, RuntimeType rt); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ArgIterator_GetNextArg2")] + private static partial void GetNextArg(ArgIterator* thisPtr, QCallTypeHandle rth, TypedReference* pResult); // This method should invalidate the iterator (va_end). It is not supported yet. public void End() { } - // How many arguments are left in the list - [MethodImpl(MethodImplOptions.InternalCall)] - public extern int GetRemainingCount(); + public int GetRemainingCount() + { + if (_argCookie == 0) + { + // This ArgIterator was created by marshaling from an unmanaged va_list - + // can't do this operation + ThrowHelper.ThrowNotSupportedException(); + } + return _remainingArgs; + } // Gets the type of the current arg, does NOT advance the iterator - [MethodImpl(MethodImplOptions.InternalCall)] - private extern unsafe void* _GetNextArgType(); - public unsafe RuntimeTypeHandle GetNextArgType() { - return new RuntimeTypeHandle(Type.GetTypeFromHandleUnsafe((IntPtr)_GetNextArgType())); + return RuntimeTypeHandle.FromIntPtr(GetNextArgType(ThisPtr)); } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ArgIterator_GetNextArgType")] + private static partial IntPtr GetNextArgType(ArgIterator* thisPtr); + public override int GetHashCode() { - return HashCode.Combine(ArgCookie); + return HashCode.Combine(_argCookie); } // Inherited from object 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 2ccb7ff256847..e0d44a1ab7fd4 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 @@ -248,7 +248,7 @@ public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDel if (pMT->HasInstantiation) throw new ArgumentException(SR.Argument_NeedNonGenericObject, nameof(structure)); - delegate* structMarshalStub; + delegate* structMarshalStub; nuint size; if (!TryGetStructMarshalStub((IntPtr)pMT, &structMarshalStub, &size)) throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, nameof(structure)); @@ -257,10 +257,10 @@ public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDel { if (fDeleteOld) { - structMarshalStub(ref structure.GetRawData(), (byte*)ptr, MarshalOperation.Cleanup, ref Unsafe.NullRef()); + structMarshalStub(ref structure.GetRawData(), (byte*)ptr, MarshalOperation.Cleanup, ref Unsafe.NullRef()); } - structMarshalStub(ref structure.GetRawData(), (byte*)ptr, MarshalOperation.Marshal, ref Unsafe.NullRef()); + structMarshalStub(ref structure.GetRawData(), (byte*)ptr, MarshalOperation.Marshal, ref Unsafe.NullRef()); } else { @@ -278,14 +278,14 @@ private static unsafe void PtrToStructureHelper(IntPtr ptr, object structure, bo if (!allowValueClasses && pMT->IsValueType) throw new ArgumentException(SR.Argument_StructMustNotBeValueClass, nameof(structure)); - delegate* structMarshalStub; + 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()); + structMarshalStub(ref structure.GetRawData(), (byte*)ptr, MarshalOperation.Unmarshal, ref Unsafe.NullRef()); } else { @@ -310,7 +310,7 @@ public static unsafe void DestroyStructure(IntPtr ptr, Type structuretype) if (rt.IsGenericType) throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(structuretype)); - delegate* structMarshalStub; + delegate* structMarshalStub; nuint size; if (!TryGetStructMarshalStub(rt.GetUnderlyingNativeHandle(), &structMarshalStub, &size)) throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, nameof(structuretype)); @@ -319,13 +319,13 @@ public static unsafe void DestroyStructure(IntPtr ptr, Type structuretype) if (structMarshalStub != null) { - structMarshalStub(ref Unsafe.NullRef(), (byte*)ptr, MarshalOperation.Cleanup, ref Unsafe.NullRef()); + 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); + internal 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) @@ -959,11 +959,23 @@ public static void ChangeWrapperHandleStrength(object otp, bool fIsWeak) private static partial void ChangeWrapperHandleStrength(ObjectHandleOnStack otp, [MarshalAs(UnmanagedType.Bool)] bool fIsWeak); #endif // FEATURE_COMINTEROP - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t); + internal static Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, RuntimeType t) + { + Delegate? retDelegate = null; + GetDelegateForFunctionPointerInternal(ptr, new QCallTypeHandle(ref t), ObjectHandleOnStack.Create(ref retDelegate)); + return retDelegate!; + } - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern IntPtr GetFunctionPointerForDelegateInternal(Delegate d); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MarshalNative_GetDelegateForFunctionPointerInternal")] + private static partial void GetDelegateForFunctionPointerInternal(IntPtr ptr, QCallTypeHandle t, ObjectHandleOnStack retDelegate); + + internal static IntPtr GetFunctionPointerForDelegateInternal(Delegate d) + { + return GetFunctionPointerForDelegateInternal(ObjectHandleOnStack.Create(ref d)); + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MarshalNative_GetFunctionPointerForDelegateInternal")] + private static partial IntPtr GetFunctionPointerForDelegateInternal(ObjectHandleOnStack d); #if DEBUG // Used for testing in Checked or Debug [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MarshalNative_GetIsInCooperativeGCModeFunctionPointer")] diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 09112d1e1e7a0..73b9bb167f7a7 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -82,6 +82,11 @@ internal RuntimeTypeHandle(RuntimeType type) m_type = type; } + internal bool IsNullHandle() + { + return m_type == null; + } + internal static bool IsTypeDefinition(RuntimeType type) { CorElementType corElemType = GetCorElementType(type); diff --git a/src/coreclr/System.Private.CoreLib/src/System/String.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/String.CoreCLR.cs index befcb1bb19d3d..f15ad03d82182 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/String.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/String.CoreCLR.cs @@ -1,6 +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.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Text; @@ -11,30 +12,25 @@ public partial class String [MethodImpl(MethodImplOptions.InternalCall)] internal static extern string FastAllocateString(int length); - // Set extra byte for odd-sized strings that came from interop as BSTR. - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern void SetTrailByte(byte data); - // Try to retrieve the extra byte - returns false if not present. - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern bool TryGetTrailByte(out byte data); - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern string Intern(); - [MethodImpl(MethodImplOptions.InternalCall)] - private extern string? IsInterned(); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "String_Intern")] + private static partial void Intern(StringHandleOnStack src); public static string Intern(string str) { ArgumentNullException.ThrowIfNull(str); - - return str.Intern(); + Intern(new StringHandleOnStack(ref str!)); + return str!; } + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "String_IsInterned")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial void IsInterned(StringHandleOnStack src); + public static string? IsInterned(string str) { ArgumentNullException.ThrowIfNull(str); - - return str.IsInterned(); + Intern(new StringHandleOnStack(ref str!)); + return str; } // Copies the source String (byte buffer) to the destination IntPtr memory allocated with len bytes. diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index d8d31ec63b548..6c26e38587340 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -231,7 +231,7 @@ internal static unsafe IntPtr ConvertToNative(string strManaged, IntPtr pNativeB } else { - bool hasTrailByte = strManaged.TryGetTrailByte(out byte trailByte); + bool hasTrailByte = StubHelpers.TryGetStringTrailByte(strManaged, out byte trailByte); uint lengthInBytes = (uint)strManaged.Length * 2; @@ -315,7 +315,7 @@ internal static unsafe IntPtr ConvertToNative(string strManaged, IntPtr pNativeB if ((length & 1) == 1) { // odd-sized strings need to have the trailing byte saved in their sync block - ret.SetTrailByte(((byte*)bstr)[length - 1]); + StubHelpers.SetStringTrailByte(ret, ((byte*)bstr)[length - 1]); } return ret; @@ -1142,8 +1142,8 @@ internal static partial class StubHelpers [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void SetLastError(); - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void ThrowInteropParamException(int resID, int paramIdx); + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "StubHelpers_ThrowInteropParamException")] + internal static partial void ThrowInteropParamException(int resID, int paramIdx); internal static IntPtr AddToCleanupList(ref CleanupWorkListElement? pCleanupWorkList, SafeHandle handle) { @@ -1272,12 +1272,72 @@ internal static void CheckStringLength(uint length) } } + // Try to retrieve the extra byte - returns false if not present. [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void FmtClassUpdateNativeInternal(object obj, byte* pNative, ref CleanupWorkListElement? pCleanupWorkList); - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void FmtClassUpdateCLRInternal(object obj, byte* pNative); - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern unsafe void LayoutDestroyNativeInternal(object obj, byte* pNative); + internal static extern bool TryGetStringTrailByte(string str, out byte data); + + // Set extra byte for odd-sized strings that came from interop as BSTR. + internal static void SetStringTrailByte(string str, byte data) + { + SetStringTrailByte(new StringHandleOnStack(ref str!), data); + } + + [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "StubHelpers_SetStringTrailByte")] + private static partial void SetStringTrailByte(StringHandleOnStack str, byte data); + + internal static unsafe void FmtClassUpdateNativeInternal(object obj, byte* pNative, ref CleanupWorkListElement? pCleanupWorkList) + { + MethodTable* pMT = RuntimeHelpers.GetMethodTable(obj); + + delegate* structMarshalStub; + nuint size; + bool success = Marshal.TryGetStructMarshalStub((IntPtr)pMT, &structMarshalStub, &size); + Debug.Assert(success); + + if (structMarshalStub != null) + { + structMarshalStub(ref obj.GetRawData(), pNative, MarshalOperation.Marshal, ref pCleanupWorkList); + } + else + { + Buffer.Memmove(ref *pNative, ref obj.GetRawData(), size); + } + } + + internal static unsafe void FmtClassUpdateCLRInternal(object obj, byte* pNative) + { + MethodTable* pMT = RuntimeHelpers.GetMethodTable(obj); + + delegate* structMarshalStub; + nuint size; + bool success = Marshal.TryGetStructMarshalStub((IntPtr)pMT, &structMarshalStub, &size); + Debug.Assert(success); + + if (structMarshalStub != null) + { + structMarshalStub(ref obj.GetRawData(), pNative, MarshalOperation.Unmarshal, ref Unsafe.NullRef()); + } + else + { + Buffer.Memmove(ref obj.GetRawData(), ref *pNative, size); + } + } + + internal static unsafe void LayoutDestroyNativeInternal(object obj, byte* pNative) + { + MethodTable* pMT = RuntimeHelpers.GetMethodTable(obj); + + delegate* structMarshalStub; + nuint size; + bool success = Marshal.TryGetStructMarshalStub((IntPtr)pMT, &structMarshalStub, &size); + Debug.Assert(success); + + if (structMarshalStub != null) + { + structMarshalStub(ref obj.GetRawData(), pNative, MarshalOperation.Cleanup, ref Unsafe.NullRef()); + } + } + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern object AllocateInternal(IntPtr typeHandle); diff --git a/src/coreclr/classlibnative/bcltype/CMakeLists.txt b/src/coreclr/classlibnative/bcltype/CMakeLists.txt index 265be7e1cf17f..8e4baf95751e3 100644 --- a/src/coreclr/classlibnative/bcltype/CMakeLists.txt +++ b/src/coreclr/classlibnative/bcltype/CMakeLists.txt @@ -4,7 +4,6 @@ set(BCLTYPE_SOURCES arraynative.cpp oavariant.cpp objectnative.cpp - stringnative.cpp system.cpp varargsnative.cpp variant.cpp diff --git a/src/coreclr/classlibnative/bcltype/stringnative.cpp b/src/coreclr/classlibnative/bcltype/stringnative.cpp deleted file mode 100644 index 8fd37e61e22e0..0000000000000 --- a/src/coreclr/classlibnative/bcltype/stringnative.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// File: StringNative.cpp -// - -// -// Purpose: The implementation of the String class. -// - -// - -#include "common.h" - -#include "object.h" -#include "utilcode.h" -#include "excep.h" -#include "frames.h" -#include "field.h" -#include "vars.hpp" -#include "stringnative.h" -#include "comutilnative.h" -#include "metasig.h" -#include "excep.h" - -// Compile the string functionality with these pragma flags (equivalent of the command line /Ox flag) -// Compiling this functionality differently gives us significant throughout gain in some cases. -#if defined(_MSC_VER) && defined(TARGET_X86) -#pragma optimize("tgy", on) -#endif - -FCIMPL2(FC_BOOL_RET, COMString::FCTryGetTrailByte, StringObject* thisRefUNSAFE, UINT8 *pbData) -{ - FCALL_CONTRACT; - - STRINGREF thisRef = ObjectToSTRINGREF(thisRefUNSAFE); - FC_RETURN_BOOL(thisRef->GetTrailByte(pbData)); -} -FCIMPLEND - -FCIMPL2(VOID, COMString::FCSetTrailByte, StringObject* thisRefUNSAFE, UINT8 bData) -{ - FCALL_CONTRACT; - - STRINGREF thisRef = ObjectToSTRINGREF(thisRefUNSAFE); - HELPER_METHOD_FRAME_BEGIN_1(thisRef); - - thisRef->SetTrailByte(bData); - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - -// Revert to command line compilation flags -#if defined(_MSC_VER) && defined(TARGET_X86) -#pragma optimize ("", on) -#endif diff --git a/src/coreclr/classlibnative/bcltype/stringnative.h b/src/coreclr/classlibnative/bcltype/stringnative.h deleted file mode 100644 index 1633facc085fc..0000000000000 --- a/src/coreclr/classlibnative/bcltype/stringnative.h +++ /dev/null @@ -1,62 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// File: StringNative.h -// - -// -// Purpose: Contains types and method signatures for the String class -// - -// - -#include "fcall.h" -#include "qcall.h" -#include "excep.h" - -#ifndef _STRINGNATIVE_H_ -#define _STRINGNATIVE_H_ -// -// Each function that we call through native only gets one argument, -// which is actually a pointer to it's stack of arguments. Our structs -// for accessing these are defined below. -// - -// -//These are the type signatures for String -// -// -// The method signatures for each of the methods we define. -// N.B.: There's a one-to-one mapping between the method signatures and the -// type definitions given above. -// - - -// Compile the string functionality with these pragma flags (equivalent of the command line /Ox flag) -// Compiling this functionality differently gives us significant throughout gain in some cases. -#if defined(_MSC_VER) && defined(TARGET_X86) -#pragma optimize("tgy", on) -#endif - -class COMString { -public: - - // - // Interop - // - static FCDECL2(FC_BOOL_RET, FCTryGetTrailByte, StringObject* thisRefUNSAFE, UINT8 *pbData); - static FCDECL2(VOID, FCSetTrailByte, StringObject* thisRefUNSAFE, UINT8 bData); -}; - -// Revert to command line compilation flags -#if defined(_MSC_VER) && defined(TARGET_X86) -#pragma optimize ("", on) -#endif - -#endif // _STRINGNATIVE_H_ - - - - - - diff --git a/src/coreclr/classlibnative/bcltype/varargsnative.cpp b/src/coreclr/classlibnative/bcltype/varargsnative.cpp index 7fae7d1e3ab6b..be6f771fc69c0 100644 --- a/src/coreclr/classlibnative/bcltype/varargsnative.cpp +++ b/src/coreclr/classlibnative/bcltype/varargsnative.cpp @@ -124,7 +124,7 @@ static void InitCommon(VARARGS *data, VASigCookie** cookie) // After initialization advance the next argument pointer to the first optional // argument. //////////////////////////////////////////////////////////////////////////////// -void AdvanceArgPtr(VARARGS *data) +static void AdvanceArgPtr(VARARGS *data) { CONTRACTL { THROWS; @@ -167,16 +167,11 @@ void AdvanceArgPtr(VARARGS *data) // ArgIterator constructor that initializes the state to support iteration // of the args starting at the first optional argument. //////////////////////////////////////////////////////////////////////////////// -FCIMPL2(void, VarArgsNative::Init, VARARGS* _this, LPVOID cookie) +extern "C" void QCALLTYPE ArgIterator_Init(VARARGS* data, PVOID cookie) { - FCALL_CONTRACT; + QCALL_CONTRACT; - HELPER_METHOD_FRAME_BEGIN_0(); - - _ASSERTE(_this != NULL); - VARARGS* data = _this; - if (cookie == 0) - COMPlusThrow(kArgumentException, W("InvalidOperation_HandleIsNotInitialized")); + BEGIN_QCALL; VASigCookie* pCookie = *(VASigCookie**)(cookie); @@ -193,9 +188,8 @@ FCIMPL2(void, VarArgsNative::Init, VARARGS* _this, LPVOID cookie) AdvanceArgPtr(data); } - HELPER_METHOD_FRAME_END(); + END_QCALL; } -FCIMPLEND //////////////////////////////////////////////////////////////////////////////// // ArgIterator constructor that initializes the state to support iteration @@ -203,21 +197,11 @@ FCIMPLEND // Specifying NULL as the firstArg parameter causes it to start at the first // argument to the call. //////////////////////////////////////////////////////////////////////////////// -FCIMPL3( -void, -VarArgsNative::Init2, - VARARGS * _this, - LPVOID cookie, - LPVOID firstArg) +extern "C" void QCALLTYPE ArgIterator_Init2(VARARGS* data, PVOID cookie, PVOID firstArg) { - FCALL_CONTRACT; - - HELPER_METHOD_FRAME_BEGIN_0(); + QCALL_CONTRACT; - _ASSERTE(_this != NULL); - VARARGS* data = _this; - if (cookie == 0) - COMPlusThrow(kArgumentException, W("InvalidOperation_HandleIsNotInitialized")); + BEGIN_QCALL; // Init most of the structure. InitCommon(data, (VASigCookie**)cookie); @@ -294,188 +278,24 @@ VarArgsNative::Init2, break; } } - HELPER_METHOD_FRAME_END(); -} // VarArgsNative::Init2 -FCIMPLEND - - -//////////////////////////////////////////////////////////////////////////////// -// Return the number of unprocessed args in the argument iterator. -//////////////////////////////////////////////////////////////////////////////// -FCIMPL1(int, VarArgsNative::GetRemainingCount, VARARGS* _this) -{ - FCALL_CONTRACT; - - HELPER_METHOD_FRAME_BEGIN_RET_0(); - - _ASSERTE(_this != NULL); - if (!(_this->ArgCookie)) - { - // this argiterator was created by marshaling from an unmanaged va_list - - // can't do this operation - COMPlusThrow(kNotSupportedException); - } - HELPER_METHOD_FRAME_END(); - return (_this->RemainingArgs); + END_QCALL; } -FCIMPLEND - - -//////////////////////////////////////////////////////////////////////////////// -// Retrieve the type of the next argument without consuming it. -//////////////////////////////////////////////////////////////////////////////// -FCIMPL1(void*, VarArgsNative::GetNextArgType, VARARGS* _this) -{ - FCALL_CONTRACT; - - TypedByRef value; - - HELPER_METHOD_FRAME_BEGIN_RET_0(); - - PREFIX_ASSUME(_this != NULL); - VARARGS data = *_this; - - if (!(_this->ArgCookie)) - { - // this argiterator was created by marshaling from an unmanaged va_list - - // can't do this operation - COMPlusThrow(kNotSupportedException); - } - - - // Make sure there are remaining args. - if (data.RemainingArgs == 0) - COMPlusThrow(kInvalidOperationException, W("InvalidOperation_EnumEnded")); - - GetNextArgHelper(&data, &value, FALSE); - HELPER_METHOD_FRAME_END(); - return value.type.AsPtr(); -} -FCIMPLEND - -//////////////////////////////////////////////////////////////////////////////// -// Retrieve the next argument and return it in a TypedByRef and advance the -// next argument pointer. -//////////////////////////////////////////////////////////////////////////////// -FCIMPL2(void, VarArgsNative::DoGetNextArg, VARARGS* _this, void * value) -{ - FCALL_CONTRACT; - - TypedByRef * result = (TypedByRef *)value; - HELPER_METHOD_FRAME_BEGIN_0(); - GCPROTECT_BEGININTERIOR (result); - - _ASSERTE(_this != NULL); - if (!(_this->ArgCookie)) - { - // this argiterator was created by marshaling from an unmanaged va_list - - // can't do this operation - COMPlusThrow(kInvalidOperationException); - } - - // Make sure there are remaining args. - if (_this->RemainingArgs == 0) - COMPlusThrow(kInvalidOperationException, W("InvalidOperation_EnumEnded")); - - GetNextArgHelper(_this, result, TRUE); - GCPROTECT_END (); - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - - - -//////////////////////////////////////////////////////////////////////////////// -// Retrieve the next argument and return it in a TypedByRef and advance the -// next argument pointer. -//////////////////////////////////////////////////////////////////////////////// -FCIMPL3(void, VarArgsNative::GetNextArg2, VARARGS* _this, void * value, ReflectClassBaseObject *pTypeUNSAFE) -{ - FCALL_CONTRACT; - - TypedByRef * result = (TypedByRef *)value; - REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE); - - if (refType == NULL) - FCThrowResVoid(kArgumentNullException, W("Arg_InvalidHandle")); - - HELPER_METHOD_FRAME_BEGIN_1(refType); - GCPROTECT_BEGININTERIOR (result); - - // IJW - - TypeHandle typehandle = refType->GetType(); - - _ASSERTE(_this != NULL); - unsigned size = 0; - bool isValueType = false; - - CorElementType typ = typehandle.GetInternalCorElementType(); - if (CorTypeInfo::IsPrimitiveType(typ)) - { - size = CorTypeInfo::Size(typ); - } - else if (typ == ELEMENT_TYPE_PTR) - { - size = sizeof(LPVOID); - } - else if (typ == ELEMENT_TYPE_VALUETYPE) - { - isValueType = true; - size = typehandle.AsMethodTable()->GetNativeSize(); - } - else - { - COMPlusThrow(kNotSupportedException, W("NotSupported_Type")); - } - const bool isFloatHfa = false; - size = StackElemSize(size, isValueType, isFloatHfa); - AdjustArgPtrForAlignment(_this, size); - -#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE - if (ArgIterator::IsVarArgPassedByRef(size)) - { - result->data = *(void**)_this->ArgPtr; - size = sizeof(void*); - } - else -#endif - { - result->data = (void*)_this->ArgPtr; - } - - result->type = typehandle; - _this->ArgPtr += size; - - GCPROTECT_END (); - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - - //////////////////////////////////////////////////////////////////////////////// // This is a helper that uses a VARARGS tracking data structure to retrieve // the next argument out of a varargs function call. This does not check if // there are any args remaining (it assumes it has been checked). //////////////////////////////////////////////////////////////////////////////// -void -VarArgsNative::GetNextArgHelper( - VARARGS * data, - TypedByRef * value, - BOOL fData) +static void GetNextArgHelper(VARARGS* data, TypedByRef* value, BOOL fData) { CONTRACTL { THROWS; GC_TRIGGERS; - MODE_ANY; + MODE_COOPERATIVE; PRECONDITION(CheckPointer(data)); PRECONDITION(CheckPointer(value)); } CONTRACTL_END; - GCPROTECT_BEGININTERIOR (value); - CorElementType elemType; - _ASSERTE(data->RemainingArgs != 0); SigTypeContext typeContext; // This is an empty type context. This is OK because the vararg methods may not be generic @@ -501,7 +321,8 @@ VarArgsNative::GetNextArgHelper( TryAgain: - switch (elemType = data->SigPtr.PeekElemTypeClosed(data->ArgCookie->pModule, &typeContext)) + CorElementType elemType = data->SigPtr.PeekElemTypeClosed(data->ArgCookie->pModule, &typeContext); + switch (elemType) { case ELEMENT_TYPE_BOOLEAN: case ELEMENT_TYPE_I1: @@ -643,5 +464,107 @@ VarArgsNative::GetNextArgHelper( // Update the tracking stuff to move past the argument. --data->RemainingArgs; IfFailThrow(data->SigPtr.SkipExactlyOne()); - GCPROTECT_END (); -} // VarArgsNative::GetNextArgHelper +} // GetNextArgHelper + +//////////////////////////////////////////////////////////////////////////////// +// Retrieve the type of the next argument without consuming it. +//////////////////////////////////////////////////////////////////////////////// +extern "C" void* QCALLTYPE ArgIterator_GetNextArgType(VARARGS* data) +{ + QCALL_CONTRACT; + + TypedByRef value = { }; + + BEGIN_QCALL; + + GCX_COOP(); + + _ASSERT(value.data == NULL); + GCPROTECT_BEGININTERIOR(value.data); + + // ArgIterator.GetNextArgType does not update the iterator state. Call GetNextArgHelper on + // on throw away clone of the state. + VARARGS clone = *data; + GetNextArgHelper(&clone, &value, FALSE); + + GCPROTECT_END(); + + END_QCALL; + + return value.type.AsPtr(); +} + +//////////////////////////////////////////////////////////////////////////////// +// Retrieve the next argument and return it in a TypedByRef and advance the +// next argument pointer. +//////////////////////////////////////////////////////////////////////////////// +extern "C" void QCALLTYPE ArgIterator_GetNextArg(VARARGS* data, TypedByRef* pResult) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + GCX_COOP(); + GetNextArgHelper(data, pResult, TRUE); + + END_QCALL; +} + +//////////////////////////////////////////////////////////////////////////////// +// Retrieve the next argument and return it in a TypedByRef and advance the +// next argument pointer. +//////////////////////////////////////////////////////////////////////////////// +extern "C" void QCALLTYPE ArgIterator_GetNextArg2(VARARGS* data, QCall::TypeHandle pType, TypedByRef* pResult) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; + + GCX_COOP(); + + // IJW + + TypeHandle typehandle = pType.AsTypeHandle(); + + unsigned size = 0; + bool isValueType = false; + + CorElementType typ = typehandle.GetInternalCorElementType(); + if (CorTypeInfo::IsPrimitiveType(typ)) + { + size = CorTypeInfo::Size(typ); + } + else if (typ == ELEMENT_TYPE_PTR) + { + size = sizeof(LPVOID); + } + else if (typ == ELEMENT_TYPE_VALUETYPE) + { + isValueType = true; + size = typehandle.AsMethodTable()->GetNativeSize(); + } + else + { + COMPlusThrow(kNotSupportedException, W("NotSupported_Type")); + } + const bool isFloatHfa = false; + size = StackElemSize(size, isValueType, isFloatHfa); + AdjustArgPtrForAlignment(data, size); + +#ifdef ENREGISTERED_PARAMTYPE_MAXSIZE + if (ArgIterator::IsVarArgPassedByRef(size)) + { + pResult->data = *(void**)data->ArgPtr; + size = sizeof(void*); + } + else +#endif + { + pResult->data = (void*)data->ArgPtr; + } + + pResult->type = typehandle; + data->ArgPtr += size; + + END_QCALL; +} diff --git a/src/coreclr/classlibnative/bcltype/varargsnative.h b/src/coreclr/classlibnative/bcltype/varargsnative.h index b36920150356a..7ee42e02affaf 100644 --- a/src/coreclr/classlibnative/bcltype/varargsnative.h +++ b/src/coreclr/classlibnative/bcltype/varargsnative.h @@ -14,19 +14,10 @@ #include "clrvarargs.h" -class VarArgsNative -{ -public: - static FCDECL3(void, Init2, VARARGS* _this, LPVOID cookie, LPVOID firstArg); - static FCDECL2(void, Init, VARARGS* _this, LPVOID cookie); - static FCDECL1(int, GetRemainingCount, VARARGS* _this); - static FCDECL1(void*, GetNextArgType, VARARGS* _this); - //TypedByRef can not be passed by ref, so has to pass it as void pointer - static FCDECL2(void, DoGetNextArg, VARARGS* _this, void * value); - //TypedByRef can not be passed by ref, so has to pass it as void pointer - static FCDECL3(void, GetNextArg2, VARARGS* _this, void * value, ReflectClassBaseObject *pTypeUNSAFE); - - static void GetNextArgHelper(VARARGS *data, TypedByRef *value, BOOL fData); -}; +extern "C" void QCALLTYPE ArgIterator_Init(VARARGS* thisPtr, PVOID cookie); +extern "C" void QCALLTYPE ArgIterator_Init2(VARARGS* thisPtr, PVOID cookie, PVOID firstArg); +extern "C" void* QCALLTYPE ArgIterator_GetNextArgType(VARARGS* thisPtr); +extern "C" void QCALLTYPE ArgIterator_GetNextArg(VARARGS* thisPtr, TypedByRef* pResult); +extern "C" void QCALLTYPE ArgIterator_GetNextArg2(VARARGS* thisPtr, QCall::TypeHandle pType, TypedByRef* pResult); #endif // _VARARGSNATIVE_H_ 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 44903db0e1521..80761d024050e 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 @@ -184,7 +184,7 @@ public static unsafe void StructureToPtr(object structure, IntPtr ptr, bool fDel // This method is effectively a no-op for NativeAOT, everything pre-generated. static partial void PrelinkCore(MethodInfo m); - internal static Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t) + internal static Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, RuntimeType t) { return PInvokeMarshal.GetDelegateForFunctionPointer(ptr, t.TypeHandle); } diff --git a/src/coreclr/vm/appdomainnative.cpp b/src/coreclr/vm/appdomainnative.cpp index 79012785e8ecb..d4e42759bc772 100644 --- a/src/coreclr/vm/appdomainnative.cpp +++ b/src/coreclr/vm/appdomainnative.cpp @@ -112,48 +112,36 @@ FCIMPL0(Object*, AppDomainNative::GetLoadedAssemblies) } // AppDomainNative::GetAssemblies FCIMPLEND -FCIMPL1(Object*, AppDomainNative::IsStringInterned, StringObject* pStringUNSAFE) +extern "C" void QCALLTYPE String_IsInterned(QCall::StringHandleOnStack str) { - FCALL_CONTRACT; - - STRINGREF refString = ObjectToSTRINGREF(pStringUNSAFE); - STRINGREF* prefRetVal = NULL; - - HELPER_METHOD_FRAME_BEGIN_RET_1(refString); - - if (refString == NULL) - COMPlusThrow(kArgumentNullException, W("ArgumentNull_String")); + QCALL_CONTRACT; - prefRetVal = GetAppDomain()->IsStringInterned(&refString); + BEGIN_QCALL; - HELPER_METHOD_FRAME_END(); + GCX_COOP(); - if (prefRetVal == NULL) - return NULL; + STRINGREF refString = str.Get(); + GCPROTECT_BEGIN(refString); + STRINGREF* prefRetVal = GetAppDomain()->IsStringInterned(&refString); + str.Set((prefRetVal != NULL) ? *prefRetVal : NULL); + GCPROTECT_END(); - return OBJECTREFToObject(*prefRetVal); + END_QCALL; } -FCIMPLEND -FCIMPL1(Object*, AppDomainNative::GetOrInternString, StringObject* pStringUNSAFE) +extern "C" void QCALLTYPE String_Intern(QCall::StringHandleOnStack str) { - FCALL_CONTRACT; - - STRINGREF refRetVal = NULL; - STRINGREF pString = (STRINGREF) pStringUNSAFE; + QCALL_CONTRACT; - HELPER_METHOD_FRAME_BEGIN_RET_1(pString); + BEGIN_QCALL; - if (pString == NULL) - COMPlusThrow(kArgumentNullException, W("ArgumentNull_String")); + GCX_COOP(); - STRINGREF* stringVal = GetAppDomain()->GetOrInternString(&pString); - if (stringVal != NULL) - { - refRetVal = *stringVal; - } + STRINGREF refString = str.Get(); + GCPROTECT_BEGIN(refString); + STRINGREF* stringVal = GetAppDomain()->GetOrInternString(&refString); + str.Set(*stringVal); + GCPROTECT_END(); - HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(refRetVal); + END_QCALL; } -FCIMPLEND diff --git a/src/coreclr/vm/appdomainnative.hpp b/src/coreclr/vm/appdomainnative.hpp index df580fe977497..1d58b6e5aec10 100644 --- a/src/coreclr/vm/appdomainnative.hpp +++ b/src/coreclr/vm/appdomainnative.hpp @@ -20,9 +20,11 @@ class AppDomainNative { public: static FCDECL0(Object*, GetLoadedAssemblies); - static FCDECL1(Object*, GetOrInternString, StringObject* pStringUNSAFE); - static FCDECL1(Object*, IsStringInterned, StringObject* pString); }; + +extern "C" void QCALLTYPE String_Intern(QCall::StringHandleOnStack str); +extern "C" void QCALLTYPE String_IsInterned(QCall::StringHandleOnStack str); + extern "C" void QCALLTYPE AppDomain_CreateDynamicAssembly(QCall::ObjectHandleOnStack assemblyLoadContext, NativeAssemblyNameParts* pAssemblyName, INT32 hashAlgorithm, INT32 access, QCall::ObjectHandleOnStack retAssembly); #endif diff --git a/src/coreclr/vm/corelib.cpp b/src/coreclr/vm/corelib.cpp index b6ae49b2a1d1c..c4b0b43450e56 100644 --- a/src/coreclr/vm/corelib.cpp +++ b/src/coreclr/vm/corelib.cpp @@ -13,7 +13,6 @@ // Headers for all ECall entrypoints // #include "arraynative.h" -#include "stringnative.h" #include "objectnative.h" #include "comdelegate.h" #include "customattribute.h" @@ -45,7 +44,6 @@ #include "typestring.h" #include "comdependenthandle.h" #include "weakreferencenative.h" -#include "varargsnative.h" #include "mlinfo.h" #ifdef FEATURE_COMINTEROP diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index c3288e8659a6a..9d091de403ee1 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -469,7 +469,7 @@ DEFINE_METHOD(MARSHAL, GET_HR_FOR_EXCEPTION, GetHRForE #endif // FEATURE_COMINTEROP DEFINE_METHOD(MARSHAL, GET_FUNCTION_POINTER_FOR_DELEGATE, GetFunctionPointerForDelegate, SM_Delegate_RetIntPtr) DEFINE_METHOD(MARSHAL, GET_DELEGATE_FOR_FUNCTION_POINTER, GetDelegateForFunctionPointer, SM_IntPtr_Type_RetDelegate) -DEFINE_METHOD(MARSHAL, GET_DELEGATE_FOR_FUNCTION_POINTER_INTERNAL, GetDelegateForFunctionPointerInternal, SM_IntPtr_Type_RetDelegate) +DEFINE_METHOD(MARSHAL, GET_DELEGATE_FOR_FUNCTION_POINTER_INTERNAL, GetDelegateForFunctionPointerInternal, SM_IntPtr_RuntimeType_RetDelegate) DEFINE_METHOD(MARSHAL, ALLOC_CO_TASK_MEM, AllocCoTaskMem, SM_Int_RetIntPtr) DEFINE_METHOD(MARSHAL, FREE_CO_TASK_MEM, FreeCoTaskMem, SM_IntPtr_RetVoid) diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index a0a6ce0b0eced..43a759be8920e 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -74,10 +74,6 @@ FCFuncStart(gStringFuncs) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_RetVoid, ECall::CtorSBytePtrManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_Int_Int_RetVoid, ECall::CtorSBytePtrStartLengthManaged) FCDynamicSig(COR_CTOR_METHOD_NAME, &gsig_IM_PtrSByt_Int_Int_Encoding_RetVoid, ECall::CtorSBytePtrStartLengthEncodingManaged) - FCFuncElement("SetTrailByte", COMString::FCSetTrailByte) - FCFuncElement("TryGetTrailByte", COMString::FCTryGetTrailByte) - FCFuncElement("IsInterned", AppDomainNative::IsStringInterned) - FCFuncElement("Intern", AppDomainNative::GetOrInternString) FCFuncEnd() FCFuncStart(gValueTypeFuncs) @@ -474,8 +470,6 @@ FCFuncStart(gInteropMarshalFuncs) FCFuncElement("OffsetOfHelper", MarshalNative::OffsetOfHelper) FCFuncElement("GetExceptionForHRInternal", MarshalNative::GetExceptionForHR) - FCFuncElement("GetDelegateForFunctionPointerInternal", MarshalNative::GetDelegateForFunctionPointerInternal) - FCFuncElement("GetFunctionPointerForDelegateInternal", MarshalNative::GetFunctionPointerForDelegateInternal) #ifdef FEATURE_COMINTEROP FCFuncElement("GetHRForException", MarshalNative::GetHRForException) @@ -500,15 +494,6 @@ FCFuncStart(gJitInfoFuncs) FCFuncElement("GetCompilationTimeInTicks", GetCompilationTimeInTicks) FCFuncEnd() -FCFuncStart(gVarArgFuncs) - FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_IntPtr_PtrVoid_RetVoid, VarArgsNative::Init2) - FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_IntPtr_RetVoid, VarArgsNative::Init) - FCFuncElement("GetRemainingCount", VarArgsNative::GetRemainingCount) - FCFuncElement("_GetNextArgType", VarArgsNative::GetNextArgType) - FCFuncElement("FCallGetNextArg", VarArgsNative::DoGetNextArg) - FCFuncElement("InternalGetNextArg", VarArgsNative::GetNextArg2) -FCFuncEnd() - FCFuncStart(gMonitorFuncs) FCFuncElement("Enter", JIT_MonEnter) FCFuncElement("ReliableEnter", JIT_MonReliableEnter) @@ -576,9 +561,9 @@ FCFuncEnd() FCFuncStart(gStubHelperFuncs) FCFuncElement("GetDelegateTarget", StubHelpers::GetDelegateTarget) + FCFuncElement("TryGetStringTrailByte", StubHelpers::TryGetStringTrailByte) FCFuncElement("SetLastError", StubHelpers::SetLastError) FCFuncElement("ClearLastError", StubHelpers::ClearLastError) - FCFuncElement("ThrowInteropParamException", StubHelpers::ThrowInteropParamException) FCFuncElement("InternalGetHRExceptionObject", StubHelpers::GetHRExceptionObject) #ifdef FEATURE_COMINTEROP FCFuncElement("InternalGetCOMHRExceptionObject", StubHelpers::GetCOMHRExceptionObject) @@ -588,9 +573,6 @@ FCFuncStart(gStubHelperFuncs) FCFuncElement("ProfilerBeginTransitionCallback", StubHelpers::ProfilerBeginTransitionCallback) FCFuncElement("ProfilerEndTransitionCallback", StubHelpers::ProfilerEndTransitionCallback) #endif - FCFuncElement("FmtClassUpdateNativeInternal", StubHelpers::FmtClassUpdateNativeInternal) - FCFuncElement("FmtClassUpdateCLRInternal", StubHelpers::FmtClassUpdateCLRInternal) - FCFuncElement("LayoutDestroyNativeInternal", StubHelpers::LayoutDestroyNativeInternal) FCFuncElement("AllocateInternal", StubHelpers::AllocateInternal) FCFuncElement("MarshalToUnmanagedVaListInternal", StubHelpers::MarshalToUnmanagedVaListInternal) FCFuncElement("MarshalToManagedVaListInternal", StubHelpers::MarshalToManagedVaListInternal) @@ -657,7 +639,6 @@ FCFuncEnd() // Note these have to remain sorted by name:namespace pair (Assert will wack you if you don't) // The sorting is case-sensitive -FCClassElement("ArgIterator", "System", gVarArgFuncs) FCClassElement("Array", "System", gArrayFuncs) FCClassElement("AssemblyLoadContext", "System.Runtime.Loader", gAssemblyLoadContextFuncs) FCClassElement("Buffer", "System", gBufferFuncs) diff --git a/src/coreclr/vm/eeconfig.h b/src/coreclr/vm/eeconfig.h index 9c850714883c4..cb6975e87856d 100644 --- a/src/coreclr/vm/eeconfig.h +++ b/src/coreclr/vm/eeconfig.h @@ -374,8 +374,6 @@ class EEConfig #endif #if defined(STRESS_HEAP) || defined(_DEBUG) - void SetGCStressLevel(int val) {LIMITED_METHOD_CONTRACT; iGCStress = val; } - enum GCStressFlags { GCSTRESS_NONE = 0, GCSTRESS_ALLOC = 1, // GC on all allocs and 'easy' places @@ -391,7 +389,6 @@ class EEConfig bool IsGCBreakOnOOMEnabled() const {LIMITED_METHOD_CONTRACT; return fGCBreakOnOOM; } int GetGCconcurrent() const {LIMITED_METHOD_CONTRACT; return iGCconcurrent; } - void SetGCconcurrent(int val) {LIMITED_METHOD_CONTRACT; iGCconcurrent = val; } int GetGCRetainVM () const {LIMITED_METHOD_CONTRACT; return iGCHoardVM;} DWORD GetGCLOHThreshold() const {LIMITED_METHOD_CONTRACT; return iGCLOHThreshold;} diff --git a/src/coreclr/vm/fcall.h b/src/coreclr/vm/fcall.h index 429fffd403268..bbb5ba9ca5320 100644 --- a/src/coreclr/vm/fcall.h +++ b/src/coreclr/vm/fcall.h @@ -1336,9 +1336,6 @@ typedef INT32 FC_INT16_RET; typedef UINT32 FC_UINT16_RET; -// FC_TypedByRef should be used for TypedReferences in FCall signatures -#define FC_TypedByRef TypedByRef - // The fcall entrypoints has to be at unique addresses. Use this helper macro to make // the code of the fcalls unique if you get assert in ecall.cpp that mentions it. diff --git a/src/coreclr/vm/marshalnative.cpp b/src/coreclr/vm/marshalnative.cpp index 5a57cb888e7fe..030cfd80bb219 100644 --- a/src/coreclr/vm/marshalnative.cpp +++ b/src/coreclr/vm/marshalnative.cpp @@ -239,49 +239,38 @@ FCIMPL1(UINT32, MarshalNative::OffsetOfHelper, ReflectFieldObject *pFieldUNSAFE) } FCIMPLEND -FCIMPL2(Object*, MarshalNative::GetDelegateForFunctionPointerInternal, LPVOID FPtr, ReflectClassBaseObject* refTypeUNSAFE) +extern "C" void QCALLTYPE MarshalNative_GetDelegateForFunctionPointerInternal(PVOID FPtr, QCall::TypeHandle t, QCall::ObjectHandleOnStack retDelegate) { - CONTRACTL - { - FCALL_CHECK; - PRECONDITION(refTypeUNSAFE != NULL); - } - CONTRACTL_END; + QCALL_CONTRACT; - OBJECTREF refDelegate = NULL; + BEGIN_QCALL; - REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF) refTypeUNSAFE; - HELPER_METHOD_FRAME_BEGIN_RET_2(refType, refDelegate); + GCX_COOP(); // Retrieve the method table from the RuntimeType. We already verified in managed - // code that the type was a RuntimeType that represented a delegate. Because type handles - // for delegates must have a method table, we are safe in telling prefix to assume it below. - MethodTable* pMT = refType->GetType().GetMethodTable(); - PREFIX_ASSUME(pMT != NULL); - refDelegate = COMDelegate::ConvertToDelegate(FPtr, pMT); - - HELPER_METHOD_FRAME_END(); + // code that the type was a RuntimeType that represented a delegate. + MethodTable* pMT = t.AsTypeHandle().AsMethodTable(); + OBJECTREF refDelegate = COMDelegate::ConvertToDelegate(FPtr, pMT); + retDelegate.Set(refDelegate); - return OBJECTREFToObject(refDelegate); + END_QCALL; } -FCIMPLEND -FCIMPL1(LPVOID, MarshalNative::GetFunctionPointerForDelegateInternal, Object* refDelegateUNSAFE) +extern "C" PVOID QCALLTYPE MarshalNative_GetFunctionPointerForDelegateInternal(QCall::ObjectHandleOnStack d) { - FCALL_CONTRACT; + QCALL_CONTRACT; - LPVOID pFPtr = NULL; + PVOID pFPtr = NULL; - OBJECTREF refDelegate = (OBJECTREF) refDelegateUNSAFE; - HELPER_METHOD_FRAME_BEGIN_RET_1(refDelegate); + BEGIN_QCALL; - pFPtr = COMDelegate::ConvertToCallback(refDelegate); + GCX_COOP(); + pFPtr = COMDelegate::ConvertToCallback(d.Get()); - HELPER_METHOD_FRAME_END(); + END_QCALL; return pFPtr; } -FCIMPLEND #ifdef _DEBUG namespace diff --git a/src/coreclr/vm/marshalnative.h b/src/coreclr/vm/marshalnative.h index a2524b8525f1c..336680f6af992 100644 --- a/src/coreclr/vm/marshalnative.h +++ b/src/coreclr/vm/marshalnative.h @@ -36,9 +36,6 @@ class MarshalNative static FCDECL2(VOID, GCHandleInternalSet, OBJECTHANDLE handle, Object *obj); static FCDECL3(Object*, GCHandleInternalCompareExchange, OBJECTHANDLE handle, Object *obj, Object* oldObj); - static FCDECL2(Object*, GetDelegateForFunctionPointerInternal, LPVOID FPtr, ReflectClassBaseObject* refTypeUNSAFE); - static FCDECL1(LPVOID, GetFunctionPointerForDelegateInternal, Object* refDelegateUNSAFE); - #ifdef FEATURE_COMINTEROP //==================================================================== // Checks whether there are RCWs from any context available for cleanup. @@ -53,6 +50,9 @@ 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" void QCALLTYPE MarshalNative_GetDelegateForFunctionPointerInternal(PVOID FPtr, QCall::TypeHandle t, QCall::ObjectHandleOnStack retDelegate); +extern "C" PVOID QCALLTYPE MarshalNative_GetFunctionPointerForDelegateInternal(QCall::ObjectHandleOnStack delegate); + extern "C" OBJECTHANDLE QCALLTYPE GCHandle_InternalAllocWithGCTransition(QCall::ObjectHandleOnStack obj, int type); extern "C" void QCALLTYPE GCHandle_InternalFreeWithGCTransition(OBJECTHANDLE handle); diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index dc2173f044021..ae546fd6d42fc 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -452,7 +452,6 @@ DEFINE_METASIG_T(IM(Exception_RetVoid, C(EXCEPTION), v)) DEFINE_METASIG(IM(IntPtr_RetObj, I, j)) DEFINE_METASIG(IM(IntPtr_RetVoid, I, v)) -DEFINE_METASIG(IM(IntPtr_PtrVoid_RetVoid, I P(v), v)) DEFINE_METASIG_T(IM(RefGuid_RetIntPtr, r(g(GUID)), I)) DEFINE_METASIG(IM(Obj_RetInt, j, i)) @@ -517,6 +516,7 @@ DEFINE_METASIG_T(SM(RuntimeTypeHandle_RetType, g(RT_TYPE_HANDLE), C(TYPE))) DEFINE_METASIG_T(SM(RuntimeTypeHandle_RetIntPtr, g(RT_TYPE_HANDLE), I)) DEFINE_METASIG_T(SM(RuntimeMethodHandle_RetIntPtr, g(METHOD_HANDLE), I)) DEFINE_METASIG_T(SM(IntPtr_Type_RetDelegate, I C(TYPE), C(DELEGATE))) +DEFINE_METASIG_T(SM(IntPtr_RuntimeType_RetDelegate, I C(CLASS), C(DELEGATE))) DEFINE_METASIG(IM(RetRefByte, _, r(b))) DEFINE_METASIG_T(IM(Type_RetArrObj, C(TYPE) F, a(j))) diff --git a/src/coreclr/vm/qcall.h b/src/coreclr/vm/qcall.h index c8c890f438831..d5f355ad9662b 100644 --- a/src/coreclr/vm/qcall.h +++ b/src/coreclr/vm/qcall.h @@ -159,6 +159,12 @@ class QCall { StringObject ** m_ppStringObject; + STRINGREF Get() + { + LIMITED_METHOD_CONTRACT; + return ObjectToSTRINGREF(*m_ppStringObject); + } + #ifndef DACCESS_COMPILE // // Helpers for returning managed string from QCall @@ -221,7 +227,6 @@ class QCall // Do not add operator overloads to convert this object into a stack reference to a specific object type // such as OBJECTREF *. While such things are correct, our debug checking logic is unable to verify that // the object reference is actually protected from access and therefore will assert. - // See bug 254159 for details. #endif // !DACCESS_COMPILE }; diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp index 03fd3a850723d..593e37387afaa 100644 --- a/src/coreclr/vm/qcallentrypoints.cpp +++ b/src/coreclr/vm/qcallentrypoints.cpp @@ -8,7 +8,6 @@ // Headers for all ECall entrypoints // #include "arraynative.h" -#include "stringnative.h" #include "objectnative.h" #include "comdelegate.h" #include "customattribute.h" @@ -78,6 +77,11 @@ static const Entry s_QCall[] = { + DllImportEntry(ArgIterator_Init) + DllImportEntry(ArgIterator_Init2) + DllImportEntry(ArgIterator_GetNextArgType) + DllImportEntry(ArgIterator_GetNextArg) + DllImportEntry(ArgIterator_GetNextArg2) DllImportEntry(Enum_GetValuesAndNames) DllImportEntry(DebugDebugger_Launch) DllImportEntry(DebugDebugger_Log) @@ -198,6 +202,8 @@ static const Entry s_QCall[] = DllImportEntry(MultiCoreJIT_InternalStartProfile) #endif DllImportEntry(LoaderAllocator_Destroy) + DllImportEntry(String_Intern) + DllImportEntry(String_IsInterned) DllImportEntry(AppDomain_CreateDynamicAssembly) DllImportEntry(ThreadNative_Start) DllImportEntry(ThreadNative_InformThreadNameChange) @@ -235,6 +241,8 @@ static const Entry s_QCall[] = DllImportEntry(MarshalNative_IsBuiltInComSupported) DllImportEntry(MarshalNative_TryGetStructMarshalStub) DllImportEntry(MarshalNative_SizeOfHelper) + DllImportEntry(MarshalNative_GetDelegateForFunctionPointerInternal) + DllImportEntry(MarshalNative_GetFunctionPointerForDelegateInternal) DllImportEntry(MarshalNative_GetHINSTANCE) #ifdef _DEBUG DllImportEntry(MarshalNative_GetIsInCooperativeGCModeFunctionPointer) @@ -348,6 +356,8 @@ static const Entry s_QCall[] = DllImportEntry(X86BaseCpuId) #endif DllImportEntry(StubHelpers_CreateCustomMarshalerHelper) + DllImportEntry(StubHelpers_SetStringTrailByte) + DllImportEntry(StubHelpers_ThrowInteropParamException) #if defined(FEATURE_COMINTEROP) DllImportEntry(ObjectMarshaler_ConvertToNative) DllImportEntry(ObjectMarshaler_ConvertToManaged) diff --git a/src/coreclr/vm/stubhelpers.cpp b/src/coreclr/vm/stubhelpers.cpp index 4bcf47c604107..35ce9bd3dfa7a 100644 --- a/src/coreclr/vm/stubhelpers.cpp +++ b/src/coreclr/vm/stubhelpers.cpp @@ -476,17 +476,37 @@ FCIMPL1(void*, StubHelpers::GetDelegateTarget, DelegateObject *pThisUNSAFE) } FCIMPLEND +#include +FCIMPL2(FC_BOOL_RET, StubHelpers::TryGetStringTrailByte, StringObject* thisRefUNSAFE, UINT8 *pbData) +{ + FCALL_CONTRACT; + STRINGREF thisRef = ObjectToSTRINGREF(thisRefUNSAFE); + FC_RETURN_BOOL(thisRef->GetTrailByte(pbData)); +} +FCIMPLEND +#include -FCIMPL2(void, StubHelpers::ThrowInteropParamException, UINT resID, UINT paramIdx) +extern "C" void QCALLTYPE StubHelpers_SetStringTrailByte(QCall::StringHandleOnStack str, UINT8 bData) { - FCALL_CONTRACT; + QCALL_CONTRACT; - HELPER_METHOD_FRAME_BEGIN_0(); + BEGIN_QCALL; + + GCX_COOP(); + str.Get()->SetTrailByte(bData); + + END_QCALL; +} + +extern "C" void QCALLTYPE StubHelpers_ThrowInteropParamException(INT resID, INT paramIdx) +{ + QCALL_CONTRACT; + + BEGIN_QCALL; ::ThrowInteropParamException(resID, paramIdx); - HELPER_METHOD_FRAME_END(); + END_QCALL; } -FCIMPLEND #ifdef PROFILING_SUPPORTED FCIMPL3(SIZE_T, StubHelpers::ProfilerBeginTransitionCallback, SIZE_T pSecretParam, Thread* pThread, Object* unsafe_pThis) @@ -638,88 +658,6 @@ FCIMPL3(Object*, StubHelpers::GetCOMHRExceptionObject, HRESULT hr, MethodDesc *p FCIMPLEND #endif // FEATURE_COMINTEROP -FCIMPL3(void, StubHelpers::FmtClassUpdateNativeInternal, Object* pObjUNSAFE, BYTE* pbNative, OBJECTREF *ppCleanupWorkListOnStack) -{ - FCALL_CONTRACT; - - OBJECTREF pObj = ObjectToOBJECTREF(pObjUNSAFE); - HELPER_METHOD_FRAME_BEGIN_1(pObj); - - MethodTable* pMT = pObj->GetMethodTable(); - - if (pMT->IsBlittable()) - { - memcpyNoGCRefs(pbNative, pObj->GetData(), pMT->GetNativeSize()); - } - else - { - MethodDesc* structMarshalStub; - - { - GCX_PREEMP(); - structMarshalStub = NDirect::CreateStructMarshalILStub(pMT); - } - - MarshalStructViaILStub(structMarshalStub, pObj->GetData(), pbNative, StructMarshalStubs::MarshalOperation::Marshal, (void**)ppCleanupWorkListOnStack); - } - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - -FCIMPL2(void, StubHelpers::FmtClassUpdateCLRInternal, Object* pObjUNSAFE, BYTE* pbNative) -{ - FCALL_CONTRACT; - - OBJECTREF pObj = ObjectToOBJECTREF(pObjUNSAFE); - HELPER_METHOD_FRAME_BEGIN_1(pObj); - - MethodTable* pMT = pObj->GetMethodTable(); - - if (pMT->IsBlittable()) - { - memcpyNoGCRefs(pObj->GetData(), pbNative, pMT->GetNativeSize()); - } - else - { - MethodDesc* structMarshalStub; - - { - GCX_PREEMP(); - structMarshalStub = NDirect::CreateStructMarshalILStub(pMT); - } - - MarshalStructViaILStub(structMarshalStub, pObj->GetData(), pbNative, StructMarshalStubs::MarshalOperation::Unmarshal); - } - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - -FCIMPL2(void, StubHelpers::LayoutDestroyNativeInternal, Object* pObjUNSAFE, BYTE* pbNative) -{ - FCALL_CONTRACT; - - OBJECTREF pObj = ObjectToOBJECTREF(pObjUNSAFE); - HELPER_METHOD_FRAME_BEGIN_1(pObj); - MethodTable* pMT = pObj->GetMethodTable(); - - if (!pMT->IsBlittable()) - { - MethodDesc* structMarshalStub; - - { - GCX_PREEMP(); - structMarshalStub = NDirect::CreateStructMarshalILStub(pMT); - } - - MarshalStructViaILStub(structMarshalStub, pObj->GetData(), pbNative, StructMarshalStubs::MarshalOperation::Cleanup); - } - - HELPER_METHOD_FRAME_END(); -} -FCIMPLEND - FCIMPL1(Object*, StubHelpers::AllocateInternal, EnregisteredTypeHandle pRegisteredTypeHnd) { FCALL_CONTRACT; diff --git a/src/coreclr/vm/stubhelpers.h b/src/coreclr/vm/stubhelpers.h index 631af074b265c..9f8c2a173b914 100644 --- a/src/coreclr/vm/stubhelpers.h +++ b/src/coreclr/vm/stubhelpers.h @@ -50,16 +50,14 @@ class StubHelpers static FCDECL0(void, ClearLastError ); static FCDECL1(void*, GetDelegateTarget, DelegateObject *pThisUNSAFE); - static FCDECL2(void, ThrowInteropParamException, UINT resID, UINT paramIdx); + static FCDECL2(FC_BOOL_RET, TryGetStringTrailByte, StringObject* thisRefUNSAFE, UINT8 *pbData); + static FCDECL1(Object*, GetHRExceptionObject, HRESULT hr); #ifdef FEATURE_COMINTEROP static FCDECL3(Object*, GetCOMHRExceptionObject, HRESULT hr, MethodDesc *pMD, Object *unsafe_pThis); #endif // FEATURE_COMINTEROP - 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); static FCDECL1(Object*, AllocateInternal, EnregisteredTypeHandle typeHnd); static FCDECL3(void, MarshalToUnmanagedVaListInternal, va_list va, DWORD cbVaListSize, const VARARGS* pArgIterator); static FCDECL2(void, MarshalToManagedVaListInternal, va_list va, VARARGS* pArgIterator); @@ -98,4 +96,7 @@ extern "C" IUnknown* QCALLTYPE InterfaceMarshaler_ConvertToNative(QCall::ObjectH extern "C" void QCALLTYPE InterfaceMarshaler_ConvertToManaged(IUnknown** ppUnk, MethodTable* pItfMT, MethodTable* pClsMT, DWORD dwFlags, QCall::ObjectHandleOnStack retObject); #endif +extern "C" void QCALLTYPE StubHelpers_SetStringTrailByte(QCall::StringHandleOnStack str, UINT8 bData); +extern "C" void QCALLTYPE StubHelpers_ThrowInteropParamException(INT resID, INT paramIdx); + #endif // __STUBHELPERS_h__ 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 1a43108011710..945d8adeff05b 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 @@ -1094,11 +1094,11 @@ public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t) ArgumentNullException.ThrowIfNull(t); ArgumentNullException.ThrowIfNull(ptr); - 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)); } @@ -1106,20 +1106,20 @@ public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t) // For backward compatibility, we allow lookup of existing delegate to // function pointer mappings using abstract MulticastDelegate type. We will check // for the non-abstract delegate type later if no existing mapping is found. - if (t.BaseType != typeof(MulticastDelegate) && t != typeof(MulticastDelegate)) + if (rt.BaseType != typeof(MulticastDelegate) && rt != typeof(MulticastDelegate)) { throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(t)); } - return GetDelegateForFunctionPointerInternal(ptr, t); + return GetDelegateForFunctionPointerInternal(ptr, rt); } public static TDelegate GetDelegateForFunctionPointer(IntPtr ptr) { ArgumentNullException.ThrowIfNull(ptr); - Type t = typeof(TDelegate); - if (t.IsGenericType) + RuntimeType rt = (RuntimeType)typeof(TDelegate); + if (rt.IsGenericType) { throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(TDelegate)); } @@ -1127,12 +1127,12 @@ public static TDelegate GetDelegateForFunctionPointer(IntPtr ptr) // For backward compatibility, we allow lookup of existing delegate to // function pointer mappings using abstract MulticastDelegate type. We will check // for the non-abstract delegate type later if no existing mapping is found. - if (t.BaseType != typeof(MulticastDelegate) && t != typeof(MulticastDelegate)) + if (rt.BaseType != typeof(MulticastDelegate) && rt != typeof(MulticastDelegate)) { throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(TDelegate)); } - return (TDelegate)(object)GetDelegateForFunctionPointerInternal(ptr, t); + return (TDelegate)(object)GetDelegateForFunctionPointerInternal(ptr, rt); } [RequiresDynamicCode("Marshalling code for the delegate might not be available. Use the GetFunctionPointerForDelegate overload instead.")] 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 5d9843c23f654..4e101c99b76b9 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 @@ -71,11 +71,10 @@ private static void PrelinkCore(MethodInfo m) [MethodImpl(MethodImplOptions.InternalCall)] private static extern IntPtr GetFunctionPointerForDelegateInternal(Delegate d); - private static Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t) + private static Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, RuntimeType t) { - RuntimeType rttype = (RuntimeType)t; Delegate? res = null; - GetDelegateForFunctionPointerInternal(new QCallTypeHandle(ref rttype), ptr, ObjectHandleOnStack.Create(ref res)); + GetDelegateForFunctionPointerInternal(new QCallTypeHandle(ref t), ptr, ObjectHandleOnStack.Create(ref res)); return res!; }