diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
index 2216dda0da2fe6..0acf1624c7591b 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
@@ -410,11 +410,6 @@ private static unsafe IntPtr GetProcAddressWithSuffix(IntPtr hModule, byte* meth
return ptr;
}
- internal static unsafe void CoTaskMemFree(void* p)
- {
- Marshal.FreeCoTaskMem((IntPtr)p);
- }
-
///
/// Retrieves the function pointer for the current open static delegate that is being called
///
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs
index cd1395d9115b56..0322db3c1bf7c8 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs
@@ -182,7 +182,7 @@ internal override bool CleanupRequired
internal override void EmitElementCleanup(ILCodeStream codeStream, ILEmitter emitter)
{
codeStream.Emit(ILOpcode.call, emitter.NewToken(
- Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
+ InteropTypes.GetMarshal(Context).GetKnownMethod("FreeCoTaskMem", null)));
}
protected override void AllocNativeToManaged(ILCodeStream codeStream)
@@ -240,9 +240,10 @@ protected override void TransformNativeToManaged(ILCodeStream codeStream)
protected override void EmitCleanupManaged(ILCodeStream codeStream)
{
+ ILEmitter emitter = _ilCodeStreams.Emitter;
LoadNativeValue(codeStream);
- codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken(
- Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
+ codeStream.Emit(ILOpcode.call, emitter.NewToken(
+ InteropTypes.GetMarshal(Context).GetKnownMethod("FreeCoTaskMem", null)));
}
}
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs
index a59f595311438b..4cd56aea6b17c0 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs
@@ -1491,12 +1491,8 @@ internal override bool CleanupRequired
internal override void EmitElementCleanup(ILCodeStream codeStream, ILEmitter emitter)
{
-#if READYTORUN
- throw new NotSupportedException();
-#else
codeStream.Emit(ILOpcode.call, emitter.NewToken(
- Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
-#endif
+ InteropTypes.GetMarshal(Context).GetKnownMethod("FreeCoTaskMem", null)));
}
protected override void TransformManagedToNative(ILCodeStream codeStream)
@@ -1613,12 +1609,8 @@ internal override bool CleanupRequired
internal override void EmitElementCleanup(ILCodeStream codeStream, ILEmitter emitter)
{
-#if READYTORUN
- throw new NotSupportedException();
-#else
codeStream.Emit(ILOpcode.call, emitter.NewToken(
- Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
-#endif
+ InteropTypes.GetMarshal(Context).GetKnownMethod("FreeCoTaskMem", null)));
}
protected override void TransformManagedToNative(ILCodeStream codeStream)
@@ -1765,7 +1757,7 @@ protected override void EmitCleanupManaged(ILCodeStream codeStream)
LoadNativeValue(codeStream);
codeStream.Emit(ILOpcode.call, emitter.NewToken(
- Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
+ InteropTypes.GetMarshal(Context).GetKnownMethod("FreeCoTaskMem", null)));
codeStream.EmitLabel(lNullCheck);
#endif
@@ -1787,7 +1779,7 @@ internal override void EmitElementCleanup(ILCodeStream codeStream, ILEmitter emi
Debug.Assert(_marshallerInstance is null);
codeStream.Emit(ILOpcode.call, emitter.NewToken(
- InteropTypes.GetMarshal(Context).GetKnownMethod("CoTaskMemFree", null)));
+ InteropTypes.GetMarshal(Context).GetKnownMethod("FreeCoTaskMem", null)));
}
protected override void TransformManagedToNative(ILCodeStream codeStream)
@@ -1858,11 +1850,22 @@ protected override void EmitCleanupManaged(ILCodeStream codeStream)
{
ILEmitter emitter = _ilCodeStreams.Emitter;
- Debug.Assert(_marshallerInstance != null);
+ if (In && !Out && !IsManagedByRef)
+ {
+ Debug.Assert(_marshallerInstance != null);
- codeStream.EmitLdLoca(_marshallerInstance.Value);
- codeStream.Emit(ILOpcode.call, emitter.NewToken(
- Marshaller.GetKnownMethod("FreeNative", null)));
+ codeStream.EmitLdLoca(_marshallerInstance.Value);
+ codeStream.Emit(ILOpcode.call, emitter.NewToken(
+ Marshaller.GetKnownMethod("FreeNative", null)));
+ }
+ else
+ {
+ // The marshaller instance is not guaranteed to be initialized with the latest native value.
+ // Free the native value directly.
+ LoadNativeValue(codeStream);
+ codeStream.Emit(ILOpcode.call, emitter.NewToken(
+ InteropTypes.GetMarshal(Context).GetKnownMethod("FreeCoTaskMem", null)));
+ }
}
}
diff --git a/src/coreclr/vm/ilmarshalers.cpp b/src/coreclr/vm/ilmarshalers.cpp
index 3a37699a07f9ab..1a4f265999f13e 100644
--- a/src/coreclr/vm/ilmarshalers.cpp
+++ b/src/coreclr/vm/ilmarshalers.cpp
@@ -2016,10 +2016,21 @@ void ILCUTF8Marshaler::EmitClearNative(ILCodeStream* pslILEmit)
{
STANDARD_VM_CONTRACT;
- _ASSERTE(m_dwInstance != LOCAL_NUM_UNUSED);
+ bool bPassByValueInOnly = IsIn(m_dwMarshalFlags) && !IsOut(m_dwMarshalFlags) && !IsByref(m_dwMarshalFlags);
+ if (bPassByValueInOnly)
+ {
+ _ASSERTE(m_dwInstance != LOCAL_NUM_UNUSED);
- pslILEmit->EmitLDLOCA(m_dwInstance);
- pslILEmit->EmitCALL(METHOD__UTF8STRINGMARSHALLER__FREE_NATIVE, 1, 0);
+ pslILEmit->EmitLDLOCA(m_dwInstance);
+ pslILEmit->EmitCALL(METHOD__UTF8STRINGMARSHALLER__FREE_NATIVE, 1, 0);
+ }
+ else
+ {
+ // The marshaller instance is not guaranteed to be initialized with the latest native value.
+ // Free the native value directly.
+ EmitLoadNativeValue(pslILEmit);
+ pslILEmit->EmitCALL(METHOD__MARSHAL__FREE_CO_TASK_MEM, 1, 0);
+ }
}
LocalDesc ILCSTRMarshaler::GetManagedType()
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/Utf16StringMarshaller.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/Utf16StringMarshaller.cs
index 7d77bedc19ff51..e207bec5f9fcf1 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/Utf16StringMarshaller.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/Utf16StringMarshaller.cs
@@ -25,17 +25,7 @@ public unsafe ref struct Utf16StringMarshaller
/// The string to marshal.
public Utf16StringMarshaller(string? str)
{
- if (str is null)
- {
- _nativeValue = null;
- return;
- }
-
- // + 1 for null terminator
- _nativeValue = (ushort*)Marshal.AllocCoTaskMem((str.Length + 1) * sizeof(ushort));
-
- str.CopyTo(new Span(_nativeValue, str.Length));
- _nativeValue[str.Length] = '\0'; // null-terminate
+ _nativeValue = (ushort*)Marshal.StringToCoTaskMemUni(str);
}
///