Skip to content
Merged
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 87 additions & 3 deletions src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,10 @@ protected override void EmitCleanupManaged(ILCodeStream codeStream)

class AnsiStringMarshaller : Marshaller
{
const int MAX_LOCAL_BUFFER_LENGTH = 260 + 1; // MAX_PATH + 1

private ILLocalVariable _localBuffer = default;

internal override bool CleanupRequired
{
get
Expand All @@ -1605,12 +1609,75 @@ protected override void TransformManagedToNative(ILCodeStream codeStream)

#if READYTORUN
var stringToAnsi =
Context.SystemModule.GetKnownType("System.StubHelpers", "AnsiBSTRMarshaler")
Context.SystemModule.GetKnownType("System.StubHelpers", "CSTRMarshaler")
.GetKnownMethod("ConvertToNative", null);

bool bPassByValueInOnly = In && !Out && !IsManagedByRef;

if (bPassByValueInOnly)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a reason why this logic cant move to System.StubHelpers.CSTRMarshaler ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it would be nice to have majority of the logic in C#, and minimize amount of the hand-emitted IL.

{
var bufSize = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));
_localBuffer = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.IntPtr));

// LocalBuffer = 0
codeStream.Emit(ILOpcode.ldnull);
codeStream.EmitStLoc(_localBuffer);

var noOptimize = emitter.NewCodeLabel();

// if == NULL, goto NoOptimize
LoadManagedValue(codeStream);
codeStream.Emit(ILOpcode.brfalse, noOptimize);

// String.Length + 2
LoadManagedValue(codeStream);
var stringLen =
Context.SystemModule.GetKnownType("System", "String")
.GetKnownMethod("get_Length", null);
codeStream.Emit(ILOpcode.call, emitter.NewToken(stringLen));
codeStream.EmitLdc(2);
codeStream.Emit(ILOpcode.add);

// (String.Length + 2) * GetMaxDBCSCharByteSize()
codeStream.Emit(ILOpcode.ldsfld, emitter.NewToken(Context.SystemModule.GetKnownType(
"System.Runtime.InteropServices","Marshal")
.GetKnownField("SystemMaxDBCSCharSize")));
codeStream.Emit(ILOpcode.mul_ovf);

// BufSize = (String.Length + 2) * GetMaxDBCSCharByteSize()
codeStream.EmitStLoc(bufSize);

// if (MAX_LOCAL_BUFFER_LENGTH < BufSize ) goto NoOptimize
codeStream.EmitLdc(MAX_LOCAL_BUFFER_LENGTH + 1);
codeStream.EmitLdLoc(bufSize);
codeStream.Emit(ILOpcode.clt);
codeStream.Emit(ILOpcode.brtrue, noOptimize);

// LocalBuffer = localloc(BufSize);
codeStream.EmitLdLoc(bufSize);
codeStream.Emit(ILOpcode.localloc);
codeStream.EmitStLoc(_localBuffer);

// NoOptimize:
codeStream.EmitLabel(noOptimize);
}

int flags = (PInvokeFlags.BestFitMapping ? 0x1 : 0)
| (PInvokeFlags.ThrowOnUnmappableChar ? 0x100 : 0);

// CSTRMarshaler.ConvertToNative pManaged, dwAnsiMarshalFlags, pLocalBuffer
codeStream.EmitLdc(flags);
LoadManagedValue(codeStream);

if (_localBuffer != default)
{
codeStream.EmitLdLoc(_localBuffer);
}
else
{
codeStream.Emit(ILOpcode.ldnull);
}

codeStream.Emit(ILOpcode.call, emitter.NewToken(stringToAnsi));
#else
LoadManagedValue(codeStream);
Expand All @@ -1631,7 +1698,7 @@ protected override void TransformNativeToManaged(ILCodeStream codeStream)

#if READYTORUN
var ansiToString =
Context.SystemModule.GetKnownType("System.StubHelpers", "AnsiBSTRMarshaler")
Context.SystemModule.GetKnownType("System.StubHelpers", "CSTRMarshaler")
.GetKnownMethod("ConvertToManaged", null);
#else
var ansiToString = Context.GetHelperEntryPoint("InteropHelpers", "AnsiStringToString");
Expand All @@ -1645,11 +1712,28 @@ protected override void EmitCleanupManaged(ILCodeStream codeStream)
{
var emitter = _ilCodeStreams.Emitter;
#if READYTORUN
var optimize = emitter.NewCodeLabel();

MethodDesc clearNative =
Context.SystemModule.GetKnownType("System.StubHelpers", "AnsiBSTRMarshaler")
Context.SystemModule.GetKnownType("System.StubHelpers", "CSTRMarshaler")
.GetKnownMethod("ClearNative", null);

if (_localBuffer != default)
{
// if (m_dwLocalBuffer) goto Optimize
codeStream.EmitLdLoc(_localBuffer);
codeStream.Emit(ILOpcode.brtrue, optimize);
}

LoadNativeValue(codeStream);
// static void m_idClearNative(IntPtr ptr)
codeStream.Emit(ILOpcode.call, emitter.NewToken(clearNative));

// Optimize:
if (_localBuffer != default)
{
codeStream.EmitLabel(optimize);
}
#else
var lNullCheck = emitter.NewCodeLabel();

Expand Down